14d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
2a02d44a02bd2b3f3848f30e335adc3c076b3f905Divy Le Ray * Copyright (c) 2006-2008 Chelsio, Inc. All rights reserved.
34d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
44d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * This software is available to you under a choice of one of two
54d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * licenses.  You may choose to be licensed under the terms of the GNU
64d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * General Public License (GPL) Version 2, available from the file
74d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * COPYING in the main directory of this source tree, or the
84d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * OpenIB.org BSD license below:
94d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *     Redistribution and use in source and binary forms, with or
114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *     without modification, are permitted provided that the following
124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *     conditions are met:
134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *      - Redistributions of source code must retain the above
154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *        copyright notice, this list of conditions and the following
164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *        disclaimer.
174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *      - Redistributions in binary form must reproduce the above
194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *        copyright notice, this list of conditions and the following
204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *        disclaimer in the documentation and/or other materials
214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *        provided with the distribution.
224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * SOFTWARE.
314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/list.h>
345a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <net/neighbour.h>
364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/notifier.h>
3760063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/proc_fs.h>
394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/if_vlan.h>
404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <net/netevent.h>
414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/highmem.h>
424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include <linux/vmalloc.h>
43ee40fa0656a730491765545ff7550f3c1ceb0fbcPaul Gortmaker#include <linux/export.h>
444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "common.h"
464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "regs.h"
474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "cxgb3_ioctl.h"
484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "cxgb3_ctl_defs.h"
494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "cxgb3_defs.h"
504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "l2t.h"
514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "firmware_exports.h"
524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#include "cxgb3_offload.h"
534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic LIST_HEAD(client_list);
554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic LIST_HEAD(ofld_dev_list);
564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic DEFINE_MUTEX(cxgb3_db_lock);
574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic DEFINE_RWLOCK(adapter_list_lock);
594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic LIST_HEAD(adapter_list);
604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic const unsigned int MAX_ATIDS = 64 * 1024;
62c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Raystatic const unsigned int ATID_BASE = 0x10000;
634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
64a5190b4eea1f1c53ee26b3d1176441cafa8e7f79stephen hemmingerstatic void cxgb_neigh_update(struct neighbour *neigh);
65a5190b4eea1f1c53ee26b3d1176441cafa8e7f79stephen hemmingerstatic void cxgb_redirect(struct dst_entry *old, struct dst_entry *new);
66a5190b4eea1f1c53ee26b3d1176441cafa8e7f79stephen hemminger
674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline int offload_activated(struct t3cdev *tdev)
684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	const struct adapter *adapter = tdev2adap(tdev);
704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
71807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/**
754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	cxgb3_register_client - register an offload client
764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	@client: the client
774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	Add the client to the client list,
794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	and call backs the client for each activated offload device
804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_register_client(struct cxgb3_client *client)
824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev;
844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_lock(&cxgb3_db_lock);
864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_add_tail(&client->client_list, &client_list);
874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (client->add) {
894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		list_for_each_entry(tdev, &ofld_dev_list, ofld_dev_list) {
904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			if (offload_activated(tdev))
914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				client->add(tdev);
924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_register_client);
984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/**
1004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	cxgb3_unregister_client - unregister an offload client
1014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	@client: the client
1024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
1034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	Remove the client to the client list,
1044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	and call backs the client for each activated offload device.
1054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
1064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_unregister_client(struct cxgb3_client *client)
1074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
1084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev;
1094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_lock(&cxgb3_db_lock);
1114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_del(&client->client_list);
1124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (client->remove) {
1144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		list_for_each_entry(tdev, &ofld_dev_list, ofld_dev_list) {
1154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			if (offload_activated(tdev))
1164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				client->remove(tdev);
1174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
1184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
1194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
1204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
1214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_unregister_client);
1234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/**
1254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	cxgb3_add_clients - activate registered clients for an offload device
1264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	@tdev: the offload device
1274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
1284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	Call backs all registered clients once a offload device is activated
1294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
1304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_add_clients(struct t3cdev *tdev)
1314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
1324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cxgb3_client *client;
1334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_lock(&cxgb3_db_lock);
1354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_for_each_entry(client, &client_list, client_list) {
1364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (client->add)
1374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			client->add(tdev);
1384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
1394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
1404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
1414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/**
1434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	cxgb3_remove_clients - deactivates registered clients
1444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *			       for an offload device
1454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	@tdev: the offload device
1464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *
1474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray *	Call backs all registered clients once a offload device is deactivated
1484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
1494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_remove_clients(struct t3cdev *tdev)
1504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
1514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cxgb3_client *client;
1524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_lock(&cxgb3_db_lock);
1544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_for_each_entry(client, &client_list, client_list) {
1554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (client->remove)
1564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			client->remove(tdev);
1574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
1584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
1594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
1604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
161fa0d4c11c4b6eb49708b82b638ceb0761152f46aSteve Wisevoid cxgb3_event_notify(struct t3cdev *tdev, u32 event, u32 port)
162cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray{
163cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray	struct cxgb3_client *client;
164cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray
165cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray	mutex_lock(&cxgb3_db_lock);
166cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray	list_for_each_entry(client, &client_list, client_list) {
167fa0d4c11c4b6eb49708b82b638ceb0761152f46aSteve Wise		if (client->event_handler)
168fa0d4c11c4b6eb49708b82b638ceb0761152f46aSteve Wise			client->event_handler(tdev, event, port);
169cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray	}
170cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
171cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray}
172cb0bc205959bf8c60acae9c71f3da0597e756f8eDivy Le Ray
1734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic struct net_device *get_iff_from_mac(struct adapter *adapter,
1744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray					   const unsigned char *mac,
1754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray					   unsigned int vlan)
1764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
1774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int i;
1784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	for_each_port(adapter, i) {
1804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct net_device *dev = adapter->port[i];
1814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (!memcmp(dev->dev_addr, mac, ETH_ALEN)) {
1834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			if (vlan && vlan != VLAN_VID_MASK) {
184892ef5d85259e193505d553c10237fd5dc9a3d0dJiri Pirko				rcu_read_lock();
185892ef5d85259e193505d553c10237fd5dc9a3d0dJiri Pirko				dev = __vlan_find_dev_deep(dev, vlan);
186892ef5d85259e193505d553c10237fd5dc9a3d0dJiri Pirko				rcu_read_unlock();
1871765a575334f1a232c1478accdee5c7d19f4b3e3Jiri Pirko			} else if (netif_is_bond_slave(dev)) {
1884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				while (dev->master)
1894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray					dev = dev->master;
1901765a575334f1a232c1478accdee5c7d19f4b3e3Jiri Pirko			}
1914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			return dev;
1924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
1934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
1944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return NULL;
1954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
1964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req,
1984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			      void *data)
1994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
200a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie	int i;
2014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int ret = 0;
202a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie	unsigned int val = 0;
2034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct ulp_iscsi_info *uiip = data;
2044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
2054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	switch (req) {
2064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case ULP_ISCSI_GET_PARAMS:
2074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		uiip->pdev = adapter->pdev;
2084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		uiip->llimit = t3_read_reg(adapter, A_ULPRX_ISCSI_LLIMIT);
2094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		uiip->ulimit = t3_read_reg(adapter, A_ULPRX_ISCSI_ULIMIT);
2104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		uiip->tagmask = t3_read_reg(adapter, A_ULPRX_ISCSI_TAGMASK);
211a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie
212a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		val = t3_read_reg(adapter, A_ULPRX_ISCSI_PSZ);
213a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		for (i = 0; i < 4; i++, val >>= 8)
214a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			uiip->pgsz_factor[i] = val & 0xFF;
215a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie
216a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		val = t3_read_reg(adapter, A_TP_PARA_REG7);
217a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		uiip->max_txsz =
218a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		uiip->max_rxsz = min((val >> S_PMMAXXFERLEN0)&M_PMMAXXFERLEN0,
219a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				     (val >> S_PMMAXXFERLEN1)&M_PMMAXXFERLEN1);
2204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		/*
2214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		 * On tx, the iscsi pdu has to be <= tx page size and has to
2224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		 * fit into the Tx PM FIFO.
2234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		 */
224a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		val = min(adapter->params.tp.tx_pg_size,
225a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			  t3_read_reg(adapter, A_PM1_TX_CFG) >> 17);
226a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		uiip->max_txsz = min(val, uiip->max_txsz);
227a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie
228a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		/* set MaxRxData to 16224 */
229a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		val = t3_read_reg(adapter, A_TP_PARA_REG2);
230a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		if ((val >> S_MAXRXDATA) != 0x3f60) {
231a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			val &= (M_RXCOALESCESIZE << S_RXCOALESCESIZE);
232a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			val |= V_MAXRXDATA(0x3f60);
233a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			printk(KERN_INFO
234a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				"%s, iscsi set MaxRxData to 16224 (0x%x).\n",
235a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				adapter->name, val);
236a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			t3_write_reg(adapter, A_TP_PARA_REG2, val);
237a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		}
238a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie
239a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		/*
240a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		 * on rx, the iscsi pdu has to be < rx page size and the
241a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		 * the max rx data length programmed in TP
242a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		 */
243a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		val = min(adapter->params.tp.rx_pg_size,
244a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			  ((t3_read_reg(adapter, A_TP_PARA_REG2)) >>
245a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				S_MAXRXDATA) & M_MAXRXDATA);
246a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		uiip->max_rxsz = min(val, uiip->max_rxsz);
2474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
2484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case ULP_ISCSI_SET_PARAMS:
2494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask);
2509439f749441f3a7c2c8ef9e32b698cfe9ed60f48Karen Xie		/* program the ddp page sizes */
251a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		for (i = 0; i < 4; i++)
252a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			val |= (uiip->pgsz_factor[i] & 0xF) << (8 * i);
253a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		if (val && (val != t3_read_reg(adapter, A_ULPRX_ISCSI_PSZ))) {
254a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			printk(KERN_INFO
255a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				"%s, setting iscsi pgsz 0x%x, %u,%u,%u,%u.\n",
256a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				adapter->name, val, uiip->pgsz_factor[0],
257a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				uiip->pgsz_factor[1], uiip->pgsz_factor[2],
258a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie				uiip->pgsz_factor[3]);
259a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie			t3_write_reg(adapter, A_ULPRX_ISCSI_PSZ, val);
2609439f749441f3a7c2c8ef9e32b698cfe9ed60f48Karen Xie		}
2614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
2624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	default:
2634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ret = -EOPNOTSUPP;
2644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
2654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return ret;
2664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
2674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
2684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* Response queue used for RDMA events. */
2694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#define ASYNC_NOTIF_RSPQ 0
2704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
2714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int cxgb_rdma_ctl(struct adapter *adapter, unsigned int req, void *data)
2724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
2734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int ret = 0;
2744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
2754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	switch (req) {
2769265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger	case RDMA_GET_PARAMS: {
2779265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		struct rdma_info *rdma = data;
2784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct pci_dev *pdev = adapter->pdev;
2794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
2809265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->udbell_physbase = pci_resource_start(pdev, 2);
2819265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->udbell_len = pci_resource_len(pdev, 2);
2829265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->tpt_base =
2834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			t3_read_reg(adapter, A_ULPTX_TPT_LLIMIT);
2849265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->tpt_top = t3_read_reg(adapter, A_ULPTX_TPT_ULIMIT);
2859265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->pbl_base =
2864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			t3_read_reg(adapter, A_ULPTX_PBL_LLIMIT);
2879265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->pbl_top = t3_read_reg(adapter, A_ULPTX_PBL_ULIMIT);
2889265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->rqt_base = t3_read_reg(adapter, A_ULPRX_RQ_LLIMIT);
2899265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->rqt_top = t3_read_reg(adapter, A_ULPRX_RQ_ULIMIT);
2909265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->kdb_addr = adapter->regs + A_SG_KDOORBELL;
2919265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		rdma->pdev = pdev;
2924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
2934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
2944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CQ_OP:{
2954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		unsigned long flags;
2969265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		struct rdma_cq_op *rdma = data;
2974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
2984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		/* may be called in any context */
2994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_lock_irqsave(&adapter->sge.reg_lock, flags);
3009265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		ret = t3_sge_cqcntxt_op(adapter, rdma->id, rdma->op,
3019265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger					rdma->credits);
3024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_unlock_irqrestore(&adapter->sge.reg_lock, flags);
3034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
3054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_GET_MEM:{
3064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct ch_mem_range *t = data;
3074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct mc7 *mem;
3084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
3094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if ((t->addr & 7) || (t->len & 7))
3104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			return -EINVAL;
3114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (t->mem_id == MEM_CM)
3124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			mem = &adapter->cm;
3134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		else if (t->mem_id == MEM_PMRX)
3144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			mem = &adapter->pmrx;
3154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		else if (t->mem_id == MEM_PMTX)
3164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			mem = &adapter->pmtx;
3174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		else
3184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			return -EINVAL;
3194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
3204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ret =
3214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			t3_mc7_bd_read(mem, t->addr / 8, t->len / 8,
3224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray					(u64 *) t->buf);
3234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (ret)
3244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			return ret;
3254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
3274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CQ_SETUP:{
3289265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		struct rdma_cq_setup *rdma = data;
3294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
3304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_lock_irq(&adapter->sge.reg_lock);
3314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ret =
3329265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger			t3_sge_init_cqcntxt(adapter, rdma->id,
3339265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger					rdma->base_addr, rdma->size,
3344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray					ASYNC_NOTIF_RSPQ,
3359265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger					rdma->ovfl_mode, rdma->credits,
3369265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger					rdma->credit_thres);
3374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_unlock_irq(&adapter->sge.reg_lock);
3384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
3404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CQ_DISABLE:
3414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_lock_irq(&adapter->sge.reg_lock);
3424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ret = t3_sge_disable_cqcntxt(adapter, *(unsigned int *)data);
3434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_unlock_irq(&adapter->sge.reg_lock);
3444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CTRL_QP_SETUP:{
3469265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger		struct rdma_ctrlqp_setup *rdma = data;
3474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
3484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_lock_irq(&adapter->sge.reg_lock);
3494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ret = t3_sge_init_ecntxt(adapter, FW_RI_SGEEC_START, 0,
3504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray						SGE_CNTXT_RDMA,
3514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray						ASYNC_NOTIF_RSPQ,
3529265fabf0d4c3d0a52e169d4b9149d52fd91db69Stephen Hemminger						rdma->base_addr, rdma->size,
3534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray						FW_RI_TID_START, 1, 0);
3544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_unlock_irq(&adapter->sge.reg_lock);
3554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
35714cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise	case RDMA_GET_MIB: {
35814cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise		spin_lock(&adapter->stats_lock);
35914cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise		t3_tp_get_mib_stats(adapter, (struct tp_mib_stats *)data);
36014cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise		spin_unlock(&adapter->stats_lock);
36114cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise		break;
36214cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise	}
3634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	default:
3644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ret = -EOPNOTSUPP;
3654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
3664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return ret;
3674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
3684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
3694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int cxgb_offload_ctl(struct t3cdev *tdev, unsigned int req, void *data)
3704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
3714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct adapter *adapter = tdev2adap(tdev);
3724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_range *tid;
3734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct mtutab *mtup;
3744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct iff_mac *iffmacp;
3754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct ddp_params *ddpp;
3764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct adap_ports *ports;
377e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray	struct ofld_page_info *rx_page_info;
378e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray	struct tp_params *tp = &adapter->params.tp;
3794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int i;
3804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
3814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	switch (req) {
3824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_MAX_OUTSTANDING_WR:
3834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		*(unsigned int *)data = FW_WR_NUM;
3844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_WR_LEN:
3864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		*(unsigned int *)data = WR_FLITS;
3874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_TX_MAX_CHUNK:
3894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		*(unsigned int *)data = 1 << 20;	/* 1MB */
3904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_TID_RANGE:
3924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		tid = data;
3934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		tid->num = t3_mc5_size(&adapter->mc5) -
3944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    adapter->params.mc5.nroutes -
3954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    adapter->params.mc5.nfilters - adapter->params.mc5.nservers;
3964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		tid->base = 0;
3974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
3984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_STID_RANGE:
3994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		tid = data;
4004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		tid->num = adapter->params.mc5.nservers;
4014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		tid->base = t3_mc5_size(&adapter->mc5) - tid->num -
4024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    adapter->params.mc5.nfilters - adapter->params.mc5.nroutes;
4034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
4044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_L2T_CAPACITY:
4054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		*(unsigned int *)data = 2048;
4064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
4074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_MTUS:
4084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		mtup = data;
4094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		mtup->size = NMTUS;
4104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		mtup->mtus = adapter->params.mtus;
4114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
4124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_IFF_FROM_MAC:
4134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		iffmacp = data;
4144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		iffmacp->dev = get_iff_from_mac(adapter, iffmacp->mac_addr,
4154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray						iffmacp->vlan_tag &
4164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray						VLAN_VID_MASK);
4174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
4184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_DDP_PARAMS:
4194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ddpp = data;
4204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ddpp->llimit = t3_read_reg(adapter, A_ULPRX_TDDP_LLIMIT);
4214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ddpp->ulimit = t3_read_reg(adapter, A_ULPRX_TDDP_ULIMIT);
4224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ddpp->tag_mask = t3_read_reg(adapter, A_ULPRX_TDDP_TAGMASK);
4234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
4244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case GET_PORTS:
4254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ports = data;
4264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		ports->nports = adapter->params.nports;
4274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		for_each_port(adapter, i)
4284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			ports->lldevs[i] = adapter->port[i];
4294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
4304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case ULP_ISCSI_GET_PARAMS:
4314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case ULP_ISCSI_SET_PARAMS:
4324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (!offload_running(adapter))
4334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			return -EAGAIN;
4344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return cxgb_ulp_iscsi_ctl(adapter, req, data);
4354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_GET_PARAMS:
4364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CQ_OP:
4374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CQ_SETUP:
4384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CQ_DISABLE:
4394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_CTRL_QP_SETUP:
4404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case RDMA_GET_MEM:
44114cc180f7b032f8484c1a3d0533b1129ffe307fdSteve Wise	case RDMA_GET_MIB:
4424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (!offload_running(adapter))
4434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			return -EAGAIN;
4444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return cxgb_rdma_ctl(adapter, req, data);
445e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray	case GET_RX_PAGE_INFO:
446e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray		rx_page_info = data;
447e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray		rx_page_info->page_size = tp->rx_pg_size;
448e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray		rx_page_info->num = tp->rx_num_pgs;
449e22bb45d772b5e5c850a6223c2a3245f520de641Divy Le Ray		break;
450a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie	case GET_ISCSI_IPV4ADDR: {
451a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		struct iscsi_ipv4addr *p = data;
452a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		struct port_info *pi = netdev_priv(p->dev);
453a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		p->ipv4addr = pi->iscsi_ipv4addr;
454a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie		break;
455a109a5b916bc180e14fad0d1e9c37a08c85652c0Karen Xie	}
4564d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray	case GET_EMBEDDED_INFO: {
4574d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray		struct ch_embedded_info *e = data;
4584d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray
4594d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray		spin_lock(&adapter->stats_lock);
4604d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray		t3_get_fw_version(adapter, &e->fw_vers);
4614d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray		t3_get_tp_version(adapter, &e->tp_vers);
4624d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray		spin_unlock(&adapter->stats_lock);
4634d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray		break;
4644d8cd002602987ddc9507b5390800343f820ac92Divy Le Ray	}
4654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	default:
4664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return -EOPNOTSUPP;
4674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
4684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
4694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
4704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
4714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
4724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Dummy handler for Rx offload packets in case we get an offload packet before
4734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * proper processing is setup.  This complains and drops the packet as it isn't
4744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * normal to get offload packets at this stage.
4754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
4764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int rx_offload_blackhole(struct t3cdev *dev, struct sk_buff **skbs,
4774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				int n)
4784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
4794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	while (n--)
4804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		dev_kfree_skb_any(skbs[n]);
4814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
4824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
4834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
4844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic void dummy_neigh_update(struct t3cdev *dev, struct neighbour *neigh)
4854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
4864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
4874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
4884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_set_dummy_ops(struct t3cdev *dev)
4894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
4904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	dev->recv = rx_offload_blackhole;
4914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	dev->neigh_update = dummy_neigh_update;
4924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
4934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
4944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
4954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Free an active-open TID.
4964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
4974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid *cxgb3_free_atid(struct t3cdev *tdev, int atid)
4984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
4994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
5004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	union active_open_entry *p = atid2entry(t, atid);
5014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	void *ctx = p->t3c_tid.ctx;
5024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_bh(&t->atid_lock);
5044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	p->next = t->afree;
5054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->afree = p;
5064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->atids_in_use--;
5074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_unlock_bh(&t->atid_lock);
5084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return ctx;
5104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
5114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_free_atid);
5134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
5154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Free a server TID and return it to the free pool.
5164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
5174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_free_stid(struct t3cdev *tdev, int stid)
5184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
5194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
5204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	union listen_entry *p = stid2entry(t, stid);
5214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_bh(&t->stid_lock);
5234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	p->next = t->sfree;
5244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->sfree = p;
5254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->stids_in_use--;
5264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_unlock_bh(&t->stid_lock);
5274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
5284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_free_stid);
5304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_insert_tid(struct t3cdev *tdev, struct cxgb3_client *client,
5324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		      void *ctx, unsigned int tid)
5334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
5344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
5354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->tid_tab[tid].client = client;
5374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->tid_tab[tid].ctx = ctx;
5384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	atomic_inc(&t->tids_in_use);
5394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
5404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_insert_tid);
5424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
5444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Populate a TID_RELEASE WR.  The skb must be already propely sized.
5454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
5464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void mk_tid_release(struct sk_buff *skb, unsigned int tid)
5474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
5484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_tid_release *req;
5494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	skb->priority = CPL_PRIORITY_SETUP;
5514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req = (struct cpl_tid_release *)__skb_put(skb, sizeof(*req));
5524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
5534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid));
5544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
5554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic void t3_process_tid_release_list(struct work_struct *work)
5574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
5584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_data *td = container_of(work, struct t3c_data,
5594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray					   tid_release_task);
5604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct sk_buff *skb;
5614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev = td->dev;
5622eab17ab880ad8d570d27517e6c9d9fe74adc214Jeff Garzik
5634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_bh(&td->tid_release_lock);
5654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	while (td->tid_release_list) {
5664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct t3c_tid_entry *p = td->tid_release_list;
5674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
56843d620c82985b19008d87a437b4cf83f356264f7Joe Perches		td->tid_release_list = p->ctx;
5694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_unlock_bh(&td->tid_release_lock);
5704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		skb = alloc_skb(sizeof(struct cpl_tid_release),
57274b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray				GFP_KERNEL);
57374b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray		if (!skb)
57474b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			skb = td->nofail_skb;
57574b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray		if (!skb) {
57674b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			spin_lock_bh(&td->tid_release_lock);
57774b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			p->ctx = (void *)td->tid_release_list;
57874b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			td->tid_release_list = (struct t3c_tid_entry *)p;
57974b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			break;
58074b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray		}
5814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		mk_tid_release(skb, p - td->tid_maps.tid_tab);
5824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		cxgb3_ofld_send(tdev, skb);
5834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		p->ctx = NULL;
58474b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray		if (skb == td->nofail_skb)
58574b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			td->nofail_skb =
58674b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray				alloc_skb(sizeof(struct cpl_tid_release),
58774b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray					GFP_KERNEL);
5884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		spin_lock_bh(&td->tid_release_lock);
5894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
59074b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray	td->release_list_incomplete = (td->tid_release_list == NULL) ? 0 : 1;
5914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_unlock_bh(&td->tid_release_lock);
59274b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray
59374b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray	if (!td->nofail_skb)
59474b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray		td->nofail_skb =
59574b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray			alloc_skb(sizeof(struct cpl_tid_release),
59674b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray				GFP_KERNEL);
5974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
5984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
5994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/* use ctx as a next pointer in the tid release list */
6004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_queue_tid_release(struct t3cdev *tdev, unsigned int tid)
6014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
6024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_data *td = T3C_DATA(tdev);
6034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *p = &td->tid_maps.tid_tab[tid];
6044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_bh(&td->tid_release_lock);
6064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	p->ctx = (void *)td->tid_release_list;
607606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	p->client = NULL;
6084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	td->tid_release_list = p;
60974b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray	if (!p->ctx || td->release_list_incomplete)
6104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		schedule_work(&td->tid_release_task);
6114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_unlock_bh(&td->tid_release_lock);
6124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
6134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_queue_tid_release);
6154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
6174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Remove a tid from the TID table.  A client may defer processing its last
6184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * CPL message if it is locked at the time it arrives, and while the message
6194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * sits in the client's backlog the TID may be reused for another connection.
6204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * To handle this we atomically switch the TID association if it still points
6214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * to the original client context.
6224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
6234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_remove_tid(struct t3cdev *tdev, void *ctx, unsigned int tid)
6244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
6254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
6264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	BUG_ON(tid >= t->ntids);
6284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (tdev->type == T3A)
6294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		(void)cmpxchg(&t->tid_tab[tid].ctx, ctx, NULL);
6304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	else {
6314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct sk_buff *skb;
6324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
6344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (likely(skb)) {
6354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			mk_tid_release(skb, tid);
6364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			cxgb3_ofld_send(tdev, skb);
6374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			t->tid_tab[tid].ctx = NULL;
6384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		} else
6394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			cxgb3_queue_tid_release(tdev, tid);
6404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
6414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	atomic_dec(&t->tids_in_use);
6424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
6434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_remove_tid);
6454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint cxgb3_alloc_atid(struct t3cdev *tdev, struct cxgb3_client *client,
6474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		     void *ctx)
6484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
6494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int atid = -1;
6504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
6514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_bh(&t->atid_lock);
6539f238486f5438b2e44f760b11fa3a08714c1ddb6Divy Le Ray	if (t->afree &&
6549f238486f5438b2e44f760b11fa3a08714c1ddb6Divy Le Ray	    t->atids_in_use + atomic_read(&t->tids_in_use) + MC5_MIN_TIDS <=
6559f238486f5438b2e44f760b11fa3a08714c1ddb6Divy Le Ray	    t->ntids) {
6564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		union active_open_entry *p = t->afree;
6574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		atid = (p - t->atid_tab) + t->atid_base;
6594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t->afree = p->next;
6604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		p->t3c_tid.ctx = ctx;
6614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		p->t3c_tid.client = client;
6624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t->atids_in_use++;
6634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
6644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_unlock_bh(&t->atid_lock);
6654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return atid;
6664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
6674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_alloc_atid);
6694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint cxgb3_alloc_stid(struct t3cdev *tdev, struct cxgb3_client *client,
6714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		     void *ctx)
6724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
6734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int stid = -1;
6744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *t = &(T3C_DATA(tdev))->tid_maps;
6754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_bh(&t->stid_lock);
6774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (t->sfree) {
6784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		union listen_entry *p = t->sfree;
6794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		stid = (p - t->stid_tab) + t->stid_base;
6814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t->sfree = p->next;
6824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		p->t3c_tid.ctx = ctx;
6834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		p->t3c_tid.client = client;
6844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t->stids_in_use++;
6854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
6864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_unlock_bh(&t->stid_lock);
6874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return stid;
6884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
6894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_alloc_stid);
6914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
6925fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray/* Get the t3cdev associated with a net_device */
6935fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Raystruct t3cdev *dev2t3cdev(struct net_device *dev)
6945fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray{
6955fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray	const struct port_info *pi = netdev_priv(dev);
6965fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray
6975fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray	return (struct t3cdev *)pi->adapter;
6985fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray}
6995fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray
7005fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le RayEXPORT_SYMBOL(dev2t3cdev);
7015fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray
7024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_smt_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
7034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
7044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_smt_write_rpl *rpl = cplhdr(skb);
7054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (rpl->status != CPL_ERR_NONE)
7074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR
7084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       "Unexpected SMT_WRITE_RPL status %u for entry %u\n",
7094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       rpl->status, GET_TID(rpl));
7104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return CPL_RET_BUF_DONE;
7124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
7134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_l2t_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
7154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
7164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_l2t_write_rpl *rpl = cplhdr(skb);
7174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (rpl->status != CPL_ERR_NONE)
7194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR
7204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       "Unexpected L2T_WRITE_RPL status %u for entry %u\n",
7214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       rpl->status, GET_TID(rpl));
7224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return CPL_RET_BUF_DONE;
7244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
7254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
726b881955b7d045e7486e9af08398242aeb7199f67Divy Le Raystatic int do_rte_write_rpl(struct t3cdev *dev, struct sk_buff *skb)
727b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray{
728b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray	struct cpl_rte_write_rpl *rpl = cplhdr(skb);
729b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray
730b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray	if (rpl->status != CPL_ERR_NONE)
731b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray		printk(KERN_ERR
732b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray		       "Unexpected RTE_WRITE_RPL status %u for entry %u\n",
733b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray		       rpl->status, GET_TID(rpl));
734b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray
735b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray	return CPL_RET_BUF_DONE;
736b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray}
737b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray
7384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_act_open_rpl(struct t3cdev *dev, struct sk_buff *skb)
7394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
7404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_act_open_rpl *rpl = cplhdr(skb);
7414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int atid = G_TID(ntohl(rpl->atid));
7424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
7434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3c_tid = lookup_atid(&(T3C_DATA(dev))->tid_maps, atid);
745606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client &&
746606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	    t3c_tid->client->handlers &&
7474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[CPL_ACT_OPEN_RPL]) {
7484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[CPL_ACT_OPEN_RPL] (dev, skb,
7494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray								    t3c_tid->
7504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray								    ctx);
7514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
7524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
7534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       dev->name, CPL_ACT_OPEN_RPL);
7544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
7554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
7564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
7574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_stid_rpl(struct t3cdev *dev, struct sk_buff *skb)
7594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
7604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	union opcode_tid *p = cplhdr(skb);
7614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int stid = G_TID(ntohl(p->opcode_tid));
7624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
7634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3c_tid = lookup_stid(&(T3C_DATA(dev))->tid_maps, stid);
765606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
7664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[p->opcode]) {
7674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[p->opcode] (dev, skb,
7684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray							     t3c_tid->ctx);
7694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
7704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
7714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       dev->name, p->opcode);
7724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
7734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
7744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
7754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_hwtid_rpl(struct t3cdev *dev, struct sk_buff *skb)
7774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
7784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	union opcode_tid *p = cplhdr(skb);
7794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int hwtid = G_TID(ntohl(p->opcode_tid));
7804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
7814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
783606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
7844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[p->opcode]) {
7854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[p->opcode]
7864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    (dev, skb, t3c_tid->ctx);
7874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
7884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
7894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       dev->name, p->opcode);
7904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
7914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
7924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
7934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
7944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_cr(struct t3cdev *dev, struct sk_buff *skb)
7954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
7964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_pass_accept_req *req = cplhdr(skb);
7974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int stid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
798c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	struct tid_info *t = &(T3C_DATA(dev))->tid_maps;
7994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
800c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	unsigned int tid = GET_TID(req);
8014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
802c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	if (unlikely(tid >= t->ntids)) {
803c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		printk("%s: passive open TID %u too large\n",
804c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		       dev->name, tid);
805c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		t3_fatal_err(tdev2adap(dev));
806c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		return CPL_RET_BUF_DONE;
807c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	}
808c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray
809c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	t3c_tid = lookup_stid(t, stid);
810c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
8114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[CPL_PASS_ACCEPT_REQ]) {
8124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[CPL_PASS_ACCEPT_REQ]
8134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    (dev, skb, t3c_tid->ctx);
8144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
8154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
8164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       dev->name, CPL_PASS_ACCEPT_REQ);
8174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
8184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
8194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
8204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
821606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray/*
822606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray * Returns an sk_buff for a reply CPL message of size len.  If the input
823606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray * sk_buff has no other users it is trimmed and reused, otherwise a new buffer
824606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray * is allocated.  The input skb must be of size at least len.  Note that this
825606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray * operation does not destroy the original skb data even if it decides to reuse
826606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray * the buffer.
827606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray */
828606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Raystatic struct sk_buff *cxgb3_get_cpl_reply_skb(struct sk_buff *skb, size_t len,
8291f41bb3a5a24c82900b33071edcedec679b99de7Al Viro					       gfp_t gfp)
830606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray{
831606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (likely(!skb_cloned(skb))) {
832606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		BUG_ON(skb->len < len);
833606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		__skb_trim(skb, len);
834606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		skb_get(skb);
835606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	} else {
836606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		skb = alloc_skb(len, gfp);
837606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		if (skb)
838606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray			__skb_put(skb, len);
839606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	}
840606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	return skb;
841606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray}
842606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray
8434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_abort_req_rss(struct t3cdev *dev, struct sk_buff *skb)
8444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
8454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	union opcode_tid *p = cplhdr(skb);
8464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int hwtid = G_TID(ntohl(p->opcode_tid));
8474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
8484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
8494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
850606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
8514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[p->opcode]) {
8524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[p->opcode]
8534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    (dev, skb, t3c_tid->ctx);
8544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
8554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct cpl_abort_req_rss *req = cplhdr(skb);
8564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct cpl_abort_rpl *rpl;
857606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		struct sk_buff *reply_skb;
858606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		unsigned int tid = GET_TID(req);
859606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		u8 cmd = req->status;
860606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray
861606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		if (req->status == CPL_ERR_RTX_NEG_ADVICE ||
862606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		    req->status == CPL_ERR_PERSIST_NEG_ADVICE)
863606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray			goto out;
8644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
865606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		reply_skb = cxgb3_get_cpl_reply_skb(skb,
866606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray						    sizeof(struct
867606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray							   cpl_abort_rpl),
868606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray						    GFP_ATOMIC);
869606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray
870606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		if (!reply_skb) {
8714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			printk("do_abort_req_rss: couldn't get skb!\n");
8724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			goto out;
8734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
874606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		reply_skb->priority = CPL_PRIORITY_DATA;
875606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		__skb_put(reply_skb, sizeof(struct cpl_abort_rpl));
876606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		rpl = cplhdr(reply_skb);
8774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		rpl->wr.wr_hi =
8784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
879606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		rpl->wr.wr_lo = htonl(V_WR_TID(tid));
880606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
881606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		rpl->cmd = cmd;
882606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		cxgb3_ofld_send(dev, reply_skb);
8834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayout:
8844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE;
8854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
8864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
8874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
8884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_act_establish(struct t3cdev *dev, struct sk_buff *skb)
8894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
8904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_act_establish *req = cplhdr(skb);
8914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int atid = G_PASS_OPEN_TID(ntohl(req->tos_tid));
892c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	struct tid_info *t = &(T3C_DATA(dev))->tid_maps;
8934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
894c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	unsigned int tid = GET_TID(req);
8954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
896c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	if (unlikely(tid >= t->ntids)) {
897c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		printk("%s: active establish TID %u too large\n",
898c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		       dev->name, tid);
899c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		t3_fatal_err(tdev2adap(dev));
900c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		return CPL_RET_BUF_DONE;
901c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	}
902c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray
903c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray	t3c_tid = lookup_atid(t, atid);
904606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
9054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[CPL_ACT_ESTABLISH]) {
9064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[CPL_ACT_ESTABLISH]
9074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		    (dev, skb, t3c_tid->ctx);
9084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
9094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
910c9a6ce500d78932c43361eae28c3de81b3660c77Divy Le Ray		       dev->name, CPL_ACT_ESTABLISH);
9114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
9124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
9134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
9144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
9154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_trace(struct t3cdev *dev, struct sk_buff *skb)
9164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
9174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_trace_pkt *p = cplhdr(skb);
9184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
919b53449725a9a436fb9cc2f2ef8579368a704db03Al Viro	skb->protocol = htons(0xffff);
9204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	skb->dev = dev->lldev;
9214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	skb_pull(skb, sizeof(*p));
922459a98ed881802dee55897441bc7f77af614368eArnaldo Carvalho de Melo	skb_reset_mac_header(skb);
9234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	netif_receive_skb(skb);
9244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
9254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
9264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
927fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro/*
928fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro * That skb would better have come from process_responses() where we abuse
929fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro * ->priority and ->csum to carry our data.  NB: if we get to per-arch
930fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro * ->csum, the things might get really interesting here.
931fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro */
932fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro
933fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Virostatic inline u32 get_hwtid(struct sk_buff *skb)
934fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro{
935fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro	return ntohl((__force __be32)skb->priority) >> 8 & 0xfffff;
936fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro}
937fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro
938fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Virostatic inline u32 get_opcode(struct sk_buff *skb)
939fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro{
940fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro	return G_OPCODE(ntohl((__force __be32)skb->csum));
941fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro}
942fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro
9434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_term(struct t3cdev *dev, struct sk_buff *skb)
9444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
945fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro	unsigned int hwtid = get_hwtid(skb);
946fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro	unsigned int opcode = get_opcode(skb);
9474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *t3c_tid;
9484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
9494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3c_tid = lookup_tid(&(T3C_DATA(dev))->tid_maps, hwtid);
950606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray	if (t3c_tid && t3c_tid->ctx && t3c_tid->client->handlers &&
9514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    t3c_tid->client->handlers[opcode]) {
9524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return t3c_tid->client->handlers[opcode] (dev, skb,
9534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray							  t3c_tid->ctx);
9544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	} else {
9554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: received clientless CPL command 0x%x\n",
9564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       dev->name, opcode);
9574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
9584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
9594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
9604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
9614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int nb_callback(struct notifier_block *self, unsigned long event,
9624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       void *ctx)
9634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
9644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	switch (event) {
9654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case (NETEVENT_NEIGH_UPDATE):{
9664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		cxgb_neigh_update((struct neighbour *)ctx);
9674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
9684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
9694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	case (NETEVENT_REDIRECT):{
9704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct netevent_redirect *nr = ctx;
9714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		cxgb_redirect(nr->old, nr->new);
9722721745501a26d0dc3b88c0d2f3aa11471891388David Miller		cxgb_neigh_update(dst_get_neighbour_noref(nr->new));
9734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
9744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
9754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	default:
9764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		break;
9774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
9784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
9794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
9804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
9814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic struct notifier_block nb = {
9824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	.notifier_call = nb_callback
9834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray};
9844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
9854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
9864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Process a received packet with an unknown/unexpected CPL opcode.
9874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
9884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int do_bad_cpl(struct t3cdev *dev, struct sk_buff *skb)
9894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
9904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	printk(KERN_ERR "%s: received bad CPL command 0x%x\n", dev->name,
9914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	       *skb->data);
9924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return CPL_RET_BUF_DONE | CPL_RET_BAD_MSG;
9934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
9944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
9954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
9964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Handlers for each CPL opcode
9974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
9984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic cpl_handler_func cpl_handlers[NUM_CPL_CMDS];
9994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
10014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Add a new handler to the CPL dispatch table.  A NULL handler may be supplied
10024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * to unregister an existing handler.
10034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
10044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid t3_register_cpl_handler(unsigned int opcode, cpl_handler_func h)
10054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
10064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (opcode < NUM_CPL_CMDS)
10074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		cpl_handlers[opcode] = h ? h : do_bad_cpl;
10084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	else
10094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "T3C: handler registration for "
10104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		       "opcode %x failed\n", opcode);
10114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
10124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(t3_register_cpl_handler);
10144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
10164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * T3CDEV's receive method.
10174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
1018a5190b4eea1f1c53ee26b3d1176441cafa8e7f79stephen hemmingerstatic int process_rx(struct t3cdev *dev, struct sk_buff **skbs, int n)
10194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
10204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	while (n--) {
10214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		struct sk_buff *skb = *skbs++;
1022fa3a6cb4a6feacd712ca58fd1c6e99b33fde5d5dAl Viro		unsigned int opcode = get_opcode(skb);
10234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		int ret = cpl_handlers[opcode] (dev, skb);
10244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#if VALIDATE_TID
10264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (ret & CPL_RET_UNKNOWN_TID) {
10274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			union opcode_tid *p = cplhdr(skb);
10284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			printk(KERN_ERR "%s: CPL message (opcode %u) had "
10304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			       "unknown TID %u\n", dev->name, opcode,
10314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			       G_TID(ntohl(p->opcode_tid)));
10324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
10334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray#endif
10344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		if (ret & CPL_RET_BUF_DONE)
10354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			kfree_skb(skb);
10364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
10374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
10384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
10394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
10414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Sends an sk_buff to a T3C driver after dealing with any active network taps.
10424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
10434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint cxgb3_ofld_send(struct t3cdev *dev, struct sk_buff *skb)
10444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
10454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int r;
10464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	local_bh_disable();
10484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	r = dev->send(dev, skb);
10494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	local_bh_enable();
10504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return r;
10514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
10524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le RayEXPORT_SYMBOL(cxgb3_ofld_send);
10544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int is_offloading(struct net_device *dev)
10564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
10574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct adapter *adapter;
10584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int i;
10594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	read_lock_bh(&adapter_list_lock);
10614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_for_each_entry(adapter, &adapter_list, adapter_list) {
10624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		for_each_port(adapter, i) {
10634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			if (dev == adapter->port[i]) {
10644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				read_unlock_bh(&adapter_list_lock);
10654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				return 1;
10664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			}
10674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
10684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
10694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	read_unlock_bh(&adapter_list_lock);
10704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
10714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
10724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1073a5190b4eea1f1c53ee26b3d1176441cafa8e7f79stephen hemmingerstatic void cxgb_neigh_update(struct neighbour *neigh)
10744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
1075c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	struct net_device *dev;
10764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1077c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	if (!neigh)
1078c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller		return;
1079c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	dev = neigh->dev;
10804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (dev && (is_offloading(dev))) {
10815fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray		struct t3cdev *tdev = dev2t3cdev(dev);
10824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		BUG_ON(!tdev);
10844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t3_l2t_update(tdev, neigh);
10854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
10864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
10874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic void set_l2t_ix(struct t3cdev *tdev, u32 tid, struct l2t_entry *e)
10894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
10904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct sk_buff *skb;
10914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct cpl_set_tcb_field *req;
10924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
10934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	skb = alloc_skb(sizeof(*req), GFP_ATOMIC);
10944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!skb) {
1095b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison		printk(KERN_ERR "%s: cannot allocate skb!\n", __func__);
10964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return;
10974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
10984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	skb->priority = CPL_PRIORITY_CONTROL;
10994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req = (struct cpl_set_tcb_field *)skb_put(skb, sizeof(*req));
11004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
11014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
11024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->reply = 0;
11034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->cpu_idx = 0;
11044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->word = htons(W_TCB_L2T_IX);
11054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->mask = cpu_to_be64(V_TCB_L2T_IX(M_TCB_L2T_IX));
11064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	req->val = cpu_to_be64(V_TCB_L2T_IX(e->idx));
11074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	tdev->send(tdev, skb);
11084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
11094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1110a5190b4eea1f1c53ee26b3d1176441cafa8e7f79stephen hemmingerstatic void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
11114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
11124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct net_device *olddev, *newdev;
1113c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	struct neighbour *n;
11144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_info *ti;
11154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev;
11164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	u32 tid;
11174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int update_tcb;
11184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct l2t_entry *e;
11194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_tid_entry *te;
11204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1121c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	n = dst_get_neighbour_noref(old);
1122c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	if (!n)
1123c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller		return;
1124c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	olddev = n->dev;
1125c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller
1126c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	n = dst_get_neighbour_noref(new);
1127c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	if (!n)
1128c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller		return;
1129c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller	newdev = n->dev;
1130c4be62a4d27cf4170c2e0eca5a4f8d6fa84d85e4David Miller
11314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!is_offloading(olddev))
11324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return;
11334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!is_offloading(newdev)) {
1134f07b2e403b563d42693e02fd17956c31d3aeff1dJoe Perches		printk(KERN_WARNING "%s: Redirect to non-offload "
1135b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison		       "device ignored.\n", __func__);
11364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return;
11374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
11385fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray	tdev = dev2t3cdev(olddev);
11394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	BUG_ON(!tdev);
11405fbf816fe7d72bfdbf22bfec05b4ec3aa6849f72Divy Le Ray	if (tdev != dev2t3cdev(newdev)) {
11414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_WARNING "%s: Redirect to different "
1142b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison		       "offload device ignored.\n", __func__);
11434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return;
11444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
11454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
11464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	/* Add new L2T entry */
1147a4757123aeadf450b5b3c5f51f214660e20477f3David Miller	e = t3_l2t_get(tdev, new, newdev);
11484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!e) {
11494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
1150b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison		       __func__);
11514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return;
11524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
11534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
11544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	/* Walk tid table and notify clients of dst change. */
11554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	ti = &(T3C_DATA(tdev))->tid_maps;
11564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	for (tid = 0; tid < ti->ntids; tid++) {
11574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		te = lookup_tid(ti, tid);
11584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		BUG_ON(!te);
1159606fcd0b94f7531f52a9b07008a4461213cbcd27Divy Le Ray		if (te && te->ctx && te->client && te->client->redirect) {
11604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			update_tcb = te->client->redirect(te->ctx, old, new, e);
11614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			if (update_tcb) {
1162e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman				rcu_read_lock();
11634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				l2t_hold(L2DATA(tdev), e);
1164e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman				rcu_read_unlock();
11654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray				set_l2t_ix(tdev, tid, e);
11664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			}
11674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		}
11684d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
1169e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	l2t_release(tdev, e);
11704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
11714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
11724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
11734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
11744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * The allocated memory is cleared.
11754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
11764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid *cxgb_alloc_mem(unsigned long size)
11774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
117889bf67f1f080c947c92f8773482d9e57767ca292Eric Dumazet	void *p = kzalloc(size, GFP_KERNEL);
11794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
11804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!p)
118189bf67f1f080c947c92f8773482d9e57767ca292Eric Dumazet		p = vzalloc(size);
11824d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return p;
11834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
11844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
11854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
11864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Free memory allocated through t3_alloc_mem().
11874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
11884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb_free_mem(void *addr)
11894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
11909e2779fa281cfda13ac060753d674bbcaa23367eChristoph Lameter	if (is_vmalloc_addr(addr))
11914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		vfree(addr);
11924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	else
11934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		kfree(addr);
11944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
11954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
11964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray/*
11974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray * Allocate and initialize the TID tables.  Returns 0 on success.
11984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray */
11994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic int init_tid_tabs(struct tid_info *t, unsigned int ntids,
12004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			 unsigned int natids, unsigned int nstids,
12014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			 unsigned int atid_base, unsigned int stid_base)
12024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
12034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned long size = ntids * sizeof(*t->tid_tab) +
12044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    natids * sizeof(*t->atid_tab) + nstids * sizeof(*t->stid_tab);
12054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->tid_tab = cxgb_alloc_mem(size);
12074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!t->tid_tab)
12084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return -ENOMEM;
12094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->stid_tab = (union listen_entry *)&t->tid_tab[ntids];
12114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->atid_tab = (union active_open_entry *)&t->stid_tab[nstids];
12124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->ntids = ntids;
12134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->nstids = nstids;
12144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->stid_base = stid_base;
12154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->sfree = NULL;
12164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->natids = natids;
12174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->atid_base = atid_base;
12184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->afree = NULL;
12194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->stids_in_use = t->atids_in_use = 0;
12204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	atomic_set(&t->tids_in_use, 0);
12214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_init(&t->stid_lock);
12224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_init(&t->atid_lock);
12234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	/*
12254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	 * Setup the free lists for stid_tab and atid_tab.
12264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	 */
12274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (nstids) {
12284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		while (--nstids)
12294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			t->stid_tab[nstids - 1].next = &t->stid_tab[nstids];
12304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t->sfree = t->stid_tab;
12314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
12324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (natids) {
12334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		while (--natids)
12344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			t->atid_tab[natids - 1].next = &t->atid_tab[natids];
12354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		t->afree = t->atid_tab;
12364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	}
12374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
12384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
12394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic void free_tid_maps(struct tid_info *t)
12414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
12424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	cxgb_free_mem(t->tid_tab);
12434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
12444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12454d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void add_adapter(struct adapter *adap)
12464d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
12474d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	write_lock_bh(&adapter_list_lock);
12484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_add_tail(&adap->adapter_list, &adapter_list);
12494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	write_unlock_bh(&adapter_list_lock);
12504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
12514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void remove_adapter(struct adapter *adap)
12534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
12544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	write_lock_bh(&adapter_list_lock);
12554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_del(&adap->adapter_list);
12564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	write_unlock_bh(&adapter_list_lock);
12574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
12584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayint cxgb3_offload_activate(struct adapter *adapter)
12604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
12614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *dev = &adapter->tdev;
12624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int natids, err;
12634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_data *t;
12644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct tid_range stid_range, tid_range;
12654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct mtutab mtutab;
12664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unsigned int l2t_capacity;
12674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
126875ed0a897208c3273fd8dc0f71e1417dba5a049bJulia Lawall	t = kzalloc(sizeof(*t), GFP_KERNEL);
12694d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!t)
12704d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		return -ENOMEM;
12714d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12724d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	err = -EOPNOTSUPP;
12734d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (dev->ctl(dev, GET_TX_MAX_CHUNK, &t->tx_max_chunk) < 0 ||
12744d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    dev->ctl(dev, GET_MAX_OUTSTANDING_WR, &t->max_wrs) < 0 ||
12754d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    dev->ctl(dev, GET_L2T_CAPACITY, &l2t_capacity) < 0 ||
12764d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    dev->ctl(dev, GET_MTUS, &mtutab) < 0 ||
12774d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    dev->ctl(dev, GET_TID_RANGE, &tid_range) < 0 ||
12784d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	    dev->ctl(dev, GET_STID_RANGE, &stid_range) < 0)
12794d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		goto out_free;
12804d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12814d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	err = -ENOMEM;
1282e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity));
12834d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (!L2DATA(dev))
12844d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		goto out_free;
12854d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12864d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	natids = min(tid_range.num / 2, MAX_ATIDS);
12874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	err = init_tid_tabs(&t->tid_maps, tid_range.num, natids,
12884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray			    stid_range.num, ATID_BASE, stid_range.base);
12894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (err)
12904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		goto out_free_l2t;
12914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->mtus = mtutab.mtus;
12934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->nmtus = mtutab.size;
12944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
12954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	INIT_WORK(&t->tid_release_task, t3_process_tid_release_list);
12964d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	spin_lock_init(&t->tid_release_lock);
12974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	INIT_LIST_HEAD(&t->list_node);
12984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t->dev = dev;
12994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	T3C_DATA(dev) = t;
13014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	dev->recv = process_rx;
13024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	dev->neigh_update = t3_l2t_update;
13034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	/* Register netevent handler once */
13054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (list_empty(&adapter_list))
13064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		register_netevent_notifier(&nb);
13074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
130874b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray	t->nofail_skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_KERNEL);
130974b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray	t->release_list_incomplete = 0;
131074b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray
13114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	add_adapter(adapter);
13124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return 0;
13134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayout_free_l2t:
13154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_free_l2t(L2DATA(dev));
13162cfa5a0471fef43fda0b7bd87e3a5e4dbadb7809Eric Dumazet	RCU_INIT_POINTER(dev->l2opt, NULL);
13174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayout_free:
13184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	kfree(t);
13194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	return err;
13204d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
13214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
1322e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Hormanstatic void clean_l2_data(struct rcu_head *head)
1323e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman{
1324e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	struct l2t_data *d = container_of(head, struct l2t_data, rcu_head);
1325e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	t3_free_l2t(d);
1326e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman}
1327e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman
1328e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman
13294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid cxgb3_offload_deactivate(struct adapter *adapter)
13304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
13314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev = &adapter->tdev;
13324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3c_data *t = T3C_DATA(tdev);
1333e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	struct l2t_data *d;
13344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	remove_adapter(adapter);
13364d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	if (list_empty(&adapter_list))
13374d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		unregister_netevent_notifier(&nb);
13384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	free_tid_maps(&t->tid_maps);
13404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	T3C_DATA(tdev) = NULL;
1341e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	rcu_read_lock();
1342e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	d = L2DATA(tdev);
1343e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	rcu_read_unlock();
13442cfa5a0471fef43fda0b7bd87e3a5e4dbadb7809Eric Dumazet	RCU_INIT_POINTER(tdev->l2opt, NULL);
1345e48f129c2f200dde8899f6ea5c6e7173674fc482Neil Horman	call_rcu(&d->rcu_head, clean_l2_data);
134674b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray	if (t->nofail_skb)
134774b793e1ef79edc49bc031a88d62f1e93fc6b30fDivy Le Ray		kfree_skb(t->nofail_skb);
13484d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	kfree(t);
13494d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
13504d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13514d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void register_tdev(struct t3cdev *tdev)
13524d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
13534d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	static int unit;
13544d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13554d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_lock(&cxgb3_db_lock);
13564d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	snprintf(tdev->name, sizeof(tdev->name), "ofld_dev%d", unit++);
13574d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_add_tail(&tdev->ofld_dev_list, &ofld_dev_list);
13584d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
13594d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
13604d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13614d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Raystatic inline void unregister_tdev(struct t3cdev *tdev)
13624d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
13634d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_lock(&cxgb3_db_lock);
13644d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	list_del(&tdev->ofld_dev_list);
13654d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	mutex_unlock(&cxgb3_db_lock);
13664d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
13674d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13688f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Raystatic inline int adap2type(struct adapter *adapter)
13698f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray{
13708f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	int type = 0;
13718f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray
13728f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	switch (adapter->params.rev) {
13738f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	case T3_REV_A:
13748f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray		type = T3A;
13758f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray		break;
13768f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	case T3_REV_B:
13778f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	case T3_REV_B2:
13788f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray		type = T3B;
13798f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray		break;
13808f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	case T3_REV_C:
13818f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray		type = T3C;
13828f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray		break;
13838f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	}
13848f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	return type;
13858f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray}
13868f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray
13874d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid __devinit cxgb3_adapter_ofld(struct adapter *adapter)
13884d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
13894d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev = &adapter->tdev;
13904d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13914d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	INIT_LIST_HEAD(&tdev->ofld_dev_list);
13924d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13934d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	cxgb3_set_dummy_ops(tdev);
13944d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	tdev->send = t3_offload_tx;
13954d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	tdev->ctl = cxgb_offload_ctl;
13968f85cd7fefa3d01c4e05aac1cb198733336cf44bDivy Le Ray	tdev->type = adap2type(adapter);
13974d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
13984d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	register_tdev(tdev);
13994d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
14004d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
14014d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid __devexit cxgb3_adapter_unofld(struct adapter *adapter)
14024d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
14034d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	struct t3cdev *tdev = &adapter->tdev;
14044d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
14054d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	tdev->recv = NULL;
14064d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	tdev->neigh_update = NULL;
14074d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
14084d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	unregister_tdev(tdev);
14094d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
14104d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
14114d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Rayvoid __init cxgb3_offload_init(void)
14124d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray{
14134d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	int i;
14144d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
14154d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	for (i = 0; i < NUM_CPL_CMDS; ++i)
14164d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray		cpl_handlers[i] = do_bad_cpl;
14174d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray
14184d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_SMT_WRITE_RPL, do_smt_write_rpl);
14194d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_L2T_WRITE_RPL, do_l2t_write_rpl);
1420b881955b7d045e7486e9af08398242aeb7199f67Divy Le Ray	t3_register_cpl_handler(CPL_RTE_WRITE_RPL, do_rte_write_rpl);
14214d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_PASS_OPEN_RPL, do_stid_rpl);
14224d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_CLOSE_LISTSRV_RPL, do_stid_rpl);
14234d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_PASS_ACCEPT_REQ, do_cr);
14244d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_PASS_ESTABLISH, do_hwtid_rpl);
14254d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_ABORT_RPL_RSS, do_hwtid_rpl);
14264d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_ABORT_RPL, do_hwtid_rpl);
14274d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_RX_URG_NOTIFY, do_hwtid_rpl);
14284d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_RX_DATA, do_hwtid_rpl);
14294d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_TX_DATA_ACK, do_hwtid_rpl);
14304d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_TX_DMA_ACK, do_hwtid_rpl);
14314d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_ACT_OPEN_RPL, do_act_open_rpl);
14324d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_PEER_CLOSE, do_hwtid_rpl);
14334d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_CLOSE_CON_RPL, do_hwtid_rpl);
14344d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_ABORT_REQ_RSS, do_abort_req_rss);
14354d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_ACT_ESTABLISH, do_act_establish);
14366cdbd77e8883aac2e24f8b19b91e5b1c839213a0Divy Le Ray	t3_register_cpl_handler(CPL_SET_TCB_RPL, do_hwtid_rpl);
14376cdbd77e8883aac2e24f8b19b91e5b1c839213a0Divy Le Ray	t3_register_cpl_handler(CPL_GET_TCB_RPL, do_hwtid_rpl);
14384d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_RDMA_TERMINATE, do_term);
14394d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_RDMA_EC_STATUS, do_hwtid_rpl);
14404d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_TRACE_PKT, do_trace);
14414d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_RX_DATA_DDP, do_hwtid_rpl);
14424d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_RX_DDP_COMPLETE, do_hwtid_rpl);
14434d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray	t3_register_cpl_handler(CPL_ISCSI_HDR, do_hwtid_rpl);
14444d22de3e6cc4a09c369b504cd8bcde3385a974cdDivy Le Ray}
1445