1b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * This file is part of the Chelsio T4 Ethernet driver for Linux.
3b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
4b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Copyright (c) 2003-2010 Chelsio Communications, Inc. All rights reserved.
5b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
6b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * This software is available to you under a choice of one of two
7b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * licenses.  You may choose to be licensed under the terms of the GNU
8b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * General Public License (GPL) Version 2, available from the file
9b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * COPYING in the main directory of this source tree, or the
10b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * OpenIB.org BSD license below:
11b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
12b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *     Redistribution and use in source and binary forms, with or
13b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *     without modification, are permitted provided that the following
14b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *     conditions are met:
15b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
16b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *      - Redistributions of source code must retain the above
17b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *        copyright notice, this list of conditions and the following
18b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *        disclaimer.
19b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
20b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *      - Redistributions in binary form must reproduce the above
21b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *        copyright notice, this list of conditions and the following
22b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *        disclaimer in the documentation and/or other materials
23b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *        provided with the distribution.
24b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
25b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * SOFTWARE.
33b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
34b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
35b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
36b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
37b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/bitmap.h>
38b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/crc32.h>
39b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/ctype.h>
40b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/debugfs.h>
41b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/err.h>
42b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/etherdevice.h>
43b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/firmware.h>
4401789349ee52e4a3faf376f1485303d9723c4f1fJiri Pirko#include <linux/if.h>
45b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/if_vlan.h>
46b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/init.h>
47b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/log2.h>
48b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/mdio.h>
49b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/module.h>
50b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/moduleparam.h>
51b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/mutex.h>
52b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/netdevice.h>
53b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/pci.h>
54b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/aer.h>
55b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/rtnetlink.h>
56b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/sched.h>
57b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/seq_file.h>
58b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/sockios.h>
59b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/vmalloc.h>
60b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <linux/workqueue.h>
61b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <net/neighbour.h>
62b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <net/netevent.h>
63b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include <asm/uaccess.h>
64b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
65b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include "cxgb4.h"
66b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include "t4_regs.h"
67b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include "t4_msg.h"
68b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include "t4fw_api.h"
69b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#include "l2t.h"
70b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
7199e6d06521f2a522ff5aaa812552f68220507c67Dimitris Michailidis#define DRV_VERSION "1.3.0-ko"
72b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define DRV_DESC "Chelsio T4 Network Driver"
73b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
74b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
75b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Max interrupt hold-off timer value in us.  Queues fall back to this value
76b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * under extreme memory pressure so it's largish to give the system time to
77b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * recover.
78b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
79b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define MAX_SGE_TIMERVAL 200U
80b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
817ee9ff94857dd27144521118173786a03d490efbCasey Leedom#ifdef CONFIG_PCI_IOV
827ee9ff94857dd27144521118173786a03d490efbCasey Leedom/*
837ee9ff94857dd27144521118173786a03d490efbCasey Leedom * Virtual Function provisioning constants.  We need two extra Ingress Queues
847ee9ff94857dd27144521118173786a03d490efbCasey Leedom * with Interrupt capability to serve as the VF's Firmware Event Queue and
857ee9ff94857dd27144521118173786a03d490efbCasey Leedom * Forwarded Interrupt Queue (when using MSI mode) -- neither will have Free
867ee9ff94857dd27144521118173786a03d490efbCasey Leedom * Lists associated with them).  For each Ethernet/Control Egress Queue and
877ee9ff94857dd27144521118173786a03d490efbCasey Leedom * for each Free List, we need an Egress Context.
887ee9ff94857dd27144521118173786a03d490efbCasey Leedom */
897ee9ff94857dd27144521118173786a03d490efbCasey Leedomenum {
907ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NPORTS = 1,		/* # of "ports" per VF */
917ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NQSETS = 2,		/* # of "Queue Sets" per VF */
927ee9ff94857dd27144521118173786a03d490efbCasey Leedom
937ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NVI = VFRES_NPORTS,	/* # of Virtual Interfaces */
947ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NETHCTRL = VFRES_NQSETS,	/* # of EQs used for ETH or CTRL Qs */
957ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NIQFLINT = VFRES_NQSETS+2,/* # of ingress Qs/w Free List(s)/intr */
967ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NIQ = 0,			/* # of non-fl/int ingress queues */
977ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NEQ = VFRES_NQSETS*2,	/* # of egress queues */
987ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_TC = 0,			/* PCI-E traffic class */
997ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_NEXACTF = 16,		/* # of exact MPS filters */
1007ee9ff94857dd27144521118173786a03d490efbCasey Leedom
1017ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_R_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF|FW_CMD_CAP_PORT,
1027ee9ff94857dd27144521118173786a03d490efbCasey Leedom	VFRES_WX_CAPS = FW_CMD_CAP_DMAQ|FW_CMD_CAP_VF,
1037ee9ff94857dd27144521118173786a03d490efbCasey Leedom};
1047ee9ff94857dd27144521118173786a03d490efbCasey Leedom
1057ee9ff94857dd27144521118173786a03d490efbCasey Leedom/*
1067ee9ff94857dd27144521118173786a03d490efbCasey Leedom * Provide a Port Access Rights Mask for the specified PF/VF.  This is very
1077ee9ff94857dd27144521118173786a03d490efbCasey Leedom * static and likely not to be useful in the long run.  We really need to
1087ee9ff94857dd27144521118173786a03d490efbCasey Leedom * implement some form of persistent configuration which the firmware
1097ee9ff94857dd27144521118173786a03d490efbCasey Leedom * controls.
1107ee9ff94857dd27144521118173786a03d490efbCasey Leedom */
1117ee9ff94857dd27144521118173786a03d490efbCasey Leedomstatic unsigned int pfvfres_pmask(struct adapter *adapter,
1127ee9ff94857dd27144521118173786a03d490efbCasey Leedom				  unsigned int pf, unsigned int vf)
1137ee9ff94857dd27144521118173786a03d490efbCasey Leedom{
1147ee9ff94857dd27144521118173786a03d490efbCasey Leedom	unsigned int portn, portvec;
1157ee9ff94857dd27144521118173786a03d490efbCasey Leedom
1167ee9ff94857dd27144521118173786a03d490efbCasey Leedom	/*
1177ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * Give PF's access to all of the ports.
1187ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 */
1197ee9ff94857dd27144521118173786a03d490efbCasey Leedom	if (vf == 0)
1207ee9ff94857dd27144521118173786a03d490efbCasey Leedom		return FW_PFVF_CMD_PMASK_MASK;
1217ee9ff94857dd27144521118173786a03d490efbCasey Leedom
1227ee9ff94857dd27144521118173786a03d490efbCasey Leedom	/*
1237ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * For VFs, we'll assign them access to the ports based purely on the
1247ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * PF.  We assign active ports in order, wrapping around if there are
1257ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * fewer active ports than PFs: e.g. active port[pf % nports].
1267ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * Unfortunately the adapter's port_info structs haven't been
1277ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * initialized yet so we have to compute this.
1287ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 */
1297ee9ff94857dd27144521118173786a03d490efbCasey Leedom	if (adapter->params.nports == 0)
1307ee9ff94857dd27144521118173786a03d490efbCasey Leedom		return 0;
1317ee9ff94857dd27144521118173786a03d490efbCasey Leedom
1327ee9ff94857dd27144521118173786a03d490efbCasey Leedom	portn = pf % adapter->params.nports;
1337ee9ff94857dd27144521118173786a03d490efbCasey Leedom	portvec = adapter->params.portvec;
1347ee9ff94857dd27144521118173786a03d490efbCasey Leedom	for (;;) {
1357ee9ff94857dd27144521118173786a03d490efbCasey Leedom		/*
1367ee9ff94857dd27144521118173786a03d490efbCasey Leedom		 * Isolate the lowest set bit in the port vector.  If we're at
1377ee9ff94857dd27144521118173786a03d490efbCasey Leedom		 * the port number that we want, return that as the pmask.
1387ee9ff94857dd27144521118173786a03d490efbCasey Leedom		 * otherwise mask that bit out of the port vector and
1397ee9ff94857dd27144521118173786a03d490efbCasey Leedom		 * decrement our port number ...
1407ee9ff94857dd27144521118173786a03d490efbCasey Leedom		 */
1417ee9ff94857dd27144521118173786a03d490efbCasey Leedom		unsigned int pmask = portvec ^ (portvec & (portvec-1));
1427ee9ff94857dd27144521118173786a03d490efbCasey Leedom		if (portn == 0)
1437ee9ff94857dd27144521118173786a03d490efbCasey Leedom			return pmask;
1447ee9ff94857dd27144521118173786a03d490efbCasey Leedom		portn--;
1457ee9ff94857dd27144521118173786a03d490efbCasey Leedom		portvec &= ~pmask;
1467ee9ff94857dd27144521118173786a03d490efbCasey Leedom	}
1477ee9ff94857dd27144521118173786a03d490efbCasey Leedom	/*NOTREACHED*/
1487ee9ff94857dd27144521118173786a03d490efbCasey Leedom}
1497ee9ff94857dd27144521118173786a03d490efbCasey Leedom#endif
1507ee9ff94857dd27144521118173786a03d490efbCasey Leedom
151b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisenum {
152b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MEMWIN0_APERTURE = 65536,
153b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MEMWIN0_BASE     = 0x30000,
154b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MEMWIN1_APERTURE = 32768,
155b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MEMWIN1_BASE     = 0x28000,
156b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MEMWIN2_APERTURE = 2048,
157b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MEMWIN2_BASE     = 0x1b800,
158b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
159b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
160b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisenum {
161b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MAX_TXQ_ENTRIES      = 16384,
162b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MAX_CTRL_TXQ_ENTRIES = 1024,
163b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MAX_RSPQ_ENTRIES     = 16384,
164b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MAX_RX_BUFFERS       = 16384,
165b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MIN_TXQ_ENTRIES      = 32,
166b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MIN_CTRL_TXQ_ENTRIES = 32,
167b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MIN_RSPQ_ENTRIES     = 128,
168b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	MIN_FL_ENTRIES       = 16
169b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
170b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
171b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
172b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
173b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
174b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
175060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis#define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) }
176b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
177b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
178060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	CH_DEVICE(0xa000, 0),  /* PE10K */
179ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4001, -1),
180ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4002, -1),
181ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4003, -1),
182ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4004, -1),
183ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4005, -1),
184ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4006, -1),
185ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4007, -1),
186ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4008, -1),
187ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4009, -1),
188ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x400a, -1),
189ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4401, 4),
190ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4402, 4),
191ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4403, 4),
192ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4404, 4),
193ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4405, 4),
194ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4406, 4),
195ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4407, 4),
196ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4408, 4),
197ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x4409, 4),
198ccea790ef033cc890ca4b416a783e9f9dffe556eDimitris Michailidis	CH_DEVICE(0x440a, 4),
199f637d577cfe7b9fabf09a7e6a3c59f62b3225cd5Vipul Pandya	CH_DEVICE(0x440d, 4),
200f637d577cfe7b9fabf09a7e6a3c59f62b3225cd5Vipul Pandya	CH_DEVICE(0x440e, 4),
201b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	{ 0, }
202b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
203b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
204b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define FW_FNAME "cxgb4/t4fw.bin"
205b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
206b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_DESCRIPTION(DRV_DESC);
207b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_AUTHOR("Chelsio Communications");
208b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_LICENSE("Dual BSD/GPL");
209b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_VERSION(DRV_VERSION);
210b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
211b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_FIRMWARE(FW_FNAME);
212b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
213b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int dflt_msg_enable = DFLT_MSG_ENABLE;
214b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
215b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_param(dflt_msg_enable, int, 0644);
216b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_PARM_DESC(dflt_msg_enable, "Chelsio T4 default message enable bitmap");
217b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
218b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
219b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * The driver uses the best interrupt scheme available on a platform in the
220b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * order MSI-X, MSI, legacy INTx interrupts.  This parameter determines which
221b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * of these schemes the driver may consider as follows:
222b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
223b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * msi = 2: choose from among all three options
224b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * msi = 1: only consider MSI and INTx interrupts
225b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * msi = 0: force INTx interrupts
226b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
227b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int msi = 2;
228b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
229b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_param(msi, int, 0644);
230b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_PARM_DESC(msi, "whether to use INTx (0), MSI (1) or MSI-X (2)");
231b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
232b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
233b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Queue interrupt hold-off timer values.  Queues default to the first of these
234b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * upon creation.
235b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
236b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int intr_holdoff[SGE_NTIMERS - 1] = { 5, 10, 20, 50, 100 };
237b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
238b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_param_array(intr_holdoff, uint, NULL, 0644);
239b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_PARM_DESC(intr_holdoff, "values for queue interrupt hold-off timers "
240b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 "0..4 in microseconds");
241b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
242b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int intr_cnt[SGE_NCOUNTERS - 1] = { 4, 8, 16 };
243b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
244b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_param_array(intr_cnt, uint, NULL, 0644);
245b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_PARM_DESC(intr_cnt,
246b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 "thresholds 1..3 for queue interrupt packet counters");
247b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
248eb93992207dadb946a3b5cf4544957dc924a6f58Rusty Russellstatic bool vf_acls;
249b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
250b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#ifdef CONFIG_PCI_IOV
251b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_param(vf_acls, bool, 0644);
252b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_PARM_DESC(vf_acls, "if set enable virtualization L2 ACL enforcement");
253b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
254b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int num_vf[4];
255b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
256b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_param_array(num_vf, uint, NULL, 0644);
257b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisMODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
258b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#endif
259b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
260b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic struct dentry *cxgb4_debugfs_root;
261b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
262b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic LIST_HEAD(adapter_list);
263b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic DEFINE_MUTEX(uld_mutex);
264b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic struct cxgb4_uld_info ulds[CXGB4_ULD_MAX];
265b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic const char *uld_str[] = { "RDMA", "iSCSI" };
266b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
267b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void link_report(struct net_device *dev)
268b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
269b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!netif_carrier_ok(dev))
270b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev_info(dev, "link down\n");
271b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else {
272b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		static const char *fc[] = { "no", "Rx", "Tx", "Tx/Rx" };
273b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
274b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const char *s = "10Mbps";
275b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct port_info *p = netdev_priv(dev);
276b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
277b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		switch (p->link_cfg.speed) {
278b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		case SPEED_10000:
279b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s = "10Gbps";
280b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			break;
281b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		case SPEED_1000:
282b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s = "1000Mbps";
283b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			break;
284b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		case SPEED_100:
285b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s = "100Mbps";
286b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			break;
287b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
288b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
289b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
290b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			    fc[p->link_cfg.fc]);
291b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
292b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
293b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
294b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
295b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
296b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct net_device *dev = adapter->port[port_id];
297b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
298b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* Skip changes from disabled ports. */
299b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (netif_running(dev) && link_stat != netif_carrier_ok(dev)) {
300b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (link_stat)
301b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			netif_carrier_on(dev);
302b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		else
303b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			netif_carrier_off(dev);
304b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
305b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		link_report(dev);
306b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
307b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
308b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
309b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid t4_os_portmod_changed(const struct adapter *adap, int port_id)
310b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
311b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	static const char *mod_str[] = {
312a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM"
313b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	};
314b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
315b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct net_device *dev = adap->port[port_id];
316b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
317b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
318b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
319b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev_info(dev, "port module unplugged\n");
320a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	else if (pi->mod_type < ARRAY_SIZE(mod_str))
321b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev_info(dev, "%s module inserted\n", mod_str[pi->mod_type]);
322b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
323b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
324b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
325b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Configure the exact and hash address filters to handle a port's multicast
326b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * and secondary unicast MAC addresses.
327b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
328b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_addr_filters(const struct net_device *dev, bool sleep)
329b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
330b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 mhash = 0;
331b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 uhash = 0;
332b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	bool free = true;
333b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u16 filt_idx[7];
334b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const u8 *addr[7];
335b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret, naddr = 0;
336b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct netdev_hw_addr *ha;
337b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int uc_cnt = netdev_uc_count(dev);
3384a35ecf8bf1c4b039503fa554100fe85c761de76David S. Miller	int mc_cnt = netdev_mc_count(dev);
339b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
340060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	unsigned int mb = pi->adapter->fn;
341b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
342b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* first do the secondary unicast addresses */
343b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	netdev_for_each_uc_addr(ha, dev) {
344b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		addr[naddr++] = ha->addr;
345b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (--uc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) {
346060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free,
347b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					naddr, addr, filt_idx, &uhash, sleep);
348b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (ret < 0)
349b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				return ret;
350b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
351b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			free = false;
352b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			naddr = 0;
353b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
354b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
355b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
356b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* next set up the multicast addresses */
3574a35ecf8bf1c4b039503fa554100fe85c761de76David S. Miller	netdev_for_each_mc_addr(ha, dev) {
3584a35ecf8bf1c4b039503fa554100fe85c761de76David S. Miller		addr[naddr++] = ha->addr;
3594a35ecf8bf1c4b039503fa554100fe85c761de76David S. Miller		if (--mc_cnt == 0 || naddr >= ARRAY_SIZE(addr)) {
360060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			ret = t4_alloc_mac_filt(pi->adapter, mb, pi->viid, free,
361b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					naddr, addr, filt_idx, &mhash, sleep);
362b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (ret < 0)
363b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				return ret;
364b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
365b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			free = false;
366b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			naddr = 0;
367b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
368b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
369b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
370060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	return t4_set_addr_hash(pi->adapter, mb, pi->viid, uhash != 0,
371b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				uhash | mhash, sleep);
372b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
373b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
374b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
375b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Set Rx properties of a port, such as promiscruity, address filters, and MTU.
376b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * If @mtu is -1 it is left unchanged.
377b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
378b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
379b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
380b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
381b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
382b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
383b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ret = set_addr_filters(dev, sleep_ok);
384b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret == 0)
385060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, mtu,
386b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				    (dev->flags & IFF_PROMISC) ? 1 : 0,
387f8f5aafa960883bc3f1b8f85f1cf8199d0c85879Dimitris Michailidis				    (dev->flags & IFF_ALLMULTI) ? 1 : 0, 1, -1,
388b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				    sleep_ok);
389b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
390b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
391b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
392b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
393b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	link_start - enable a port
394b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@dev: the port to enable
395b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
396b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Performs the MAC and PHY actions needed to enable a port.
397b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
398b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int link_start(struct net_device *dev)
399b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
400b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
401b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
402060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	unsigned int mb = pi->adapter->fn;
403b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
404b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/*
405b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * We do not set address filters and promiscuity here, the stack does
406b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * that step explicitly.
407b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 */
408060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_set_rxmode(pi->adapter, mb, pi->viid, dev->mtu, -1, -1, -1,
40919ecae2c8fd5e54e40ace914a41d8e1beb41612cDimitris Michailidis			    !!(dev->features & NETIF_F_HW_VLAN_RX), true);
410b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret == 0) {
411060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_change_mac(pi->adapter, mb, pi->viid,
412b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				    pi->xact_addr_filt, dev->dev_addr, true,
413b6bd29e793c1747e0b4be8791d5738acea3a86dfDimitris Michailidis				    true);
414b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (ret >= 0) {
415b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			pi->xact_addr_filt = ret;
416b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ret = 0;
417b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
418b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
419b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret == 0)
420060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_link_start(pi->adapter, mb, pi->tx_chan,
421060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				    &pi->link_cfg);
422b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret == 0)
423060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_enable_vi(pi->adapter, mb, pi->viid, true, true);
424b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
425b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
426b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
427b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
428b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Response queue handler for the FW event queue.
429b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
430b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
431b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			  const struct pkt_gl *gl)
432b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
433b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u8 opcode = ((const struct rss_header *)rsp)->opcode;
434b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
435b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	rsp++;                                          /* skip RSS header */
436b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (likely(opcode == CPL_SGE_EGR_UPDATE)) {
437b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct cpl_sge_egr_update *p = (void *)rsp;
438b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		unsigned int qid = EGR_QID(ntohl(p->opcode_qid));
439e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis		struct sge_txq *txq;
440b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
441e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis		txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
442b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		txq->restarts++;
443e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis		if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
444b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			struct sge_eth_txq *eq;
445b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
446b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			eq = container_of(txq, struct sge_eth_txq, q);
447b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			netif_tx_wake_queue(eq->txq);
448b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		} else {
449b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			struct sge_ofld_txq *oq;
450b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
451b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			oq = container_of(txq, struct sge_ofld_txq, q);
452b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			tasklet_schedule(&oq->qresume_tsk);
453b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
454b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
455b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct cpl_fw6_msg *p = (void *)rsp;
456b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
457b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (p->type == 0)
458b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			t4_handle_fw_rpl(q->adap, p->data);
459b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (opcode == CPL_L2T_WRITE_RPL) {
460b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct cpl_l2t_write_rpl *p = (void *)rsp;
461b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
462b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		do_l2t_write_rpl(q->adap, p);
463b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else
464b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_err(q->adap->pdev_dev,
465b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			"unexpected CPL %#x on FW event queue\n", opcode);
466b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
467b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
468b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
469b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
470b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	uldrx_handler - response queue handler for ULD queues
471b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@q: the response queue that received the packet
472b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@rsp: the response queue descriptor holding the offload message
473b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@gl: the gather list of packet fragments
474b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
475b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Deliver an ingress offload packet to a ULD.  All processing is done by
476b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	the ULD, we just maintain statistics.
477b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
478b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int uldrx_handler(struct sge_rspq *q, const __be64 *rsp,
479b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 const struct pkt_gl *gl)
480b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
481b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge_ofld_rxq *rxq = container_of(q, struct sge_ofld_rxq, rspq);
482b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
483b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ulds[q->uld].rx_handler(q->adap->uld_handle[q->uld], rsp, gl)) {
484b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		rxq->stats.nomem++;
485b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -1;
486b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
487b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (gl == NULL)
488b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		rxq->stats.imm++;
489b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else if (gl == CXGB4_MSG_AN)
490b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		rxq->stats.an++;
491b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else
492b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		rxq->stats.pkts++;
493b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
494b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
495b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
496b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void disable_msi(struct adapter *adapter)
497b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
498b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adapter->flags & USING_MSIX) {
499b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_disable_msix(adapter->pdev);
500b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adapter->flags &= ~USING_MSIX;
501b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (adapter->flags & USING_MSI) {
502b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_disable_msi(adapter->pdev);
503b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adapter->flags &= ~USING_MSI;
504b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
505b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
506b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
507b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
508b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Interrupt handler for non-data events used with MSI-X.
509b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
510b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic irqreturn_t t4_nondata_intr(int irq, void *cookie)
511b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
512b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = cookie;
513b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
514b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 v = t4_read_reg(adap, MYPF_REG(PL_PF_INT_CAUSE));
515b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (v & PFSW) {
516b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->swintr = 1;
517b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_write_reg(adap, MYPF_REG(PL_PF_INT_CAUSE), v);
518b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
519b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_slow_intr_handler(adap);
520b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return IRQ_HANDLED;
521b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
522b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
523b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
524b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Name the MSI-X interrupts.
525b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
526b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void name_msix_vecs(struct adapter *adap)
527b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
528ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis	int i, j, msi_idx = 2, n = sizeof(adap->msix_info[0].desc);
529b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
530b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* non-data interrupts */
531b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis	snprintf(adap->msix_info[0].desc, n, "%s", adap->port[0]->name);
532b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
533b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* FW events */
534b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis	snprintf(adap->msix_info[1].desc, n, "%s-FWeventq",
535b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis		 adap->port[0]->name);
536b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
537b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* Ethernet queues */
538b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, j) {
539b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct net_device *d = adap->port[j];
540b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct port_info *pi = netdev_priv(d);
541b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
542ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis		for (i = 0; i < pi->nqsets; i++, msi_idx++)
543b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			snprintf(adap->msix_info[msi_idx].desc, n, "%s-Rx%d",
544b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				 d->name, i);
545b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
546b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
547b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* offload queues */
548ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis	for_each_ofldrxq(&adap->sge, i)
549ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis		snprintf(adap->msix_info[msi_idx++].desc, n, "%s-ofld%d",
550b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis			 adap->port[0]->name, i);
551ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis
552ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis	for_each_rdmarxq(&adap->sge, i)
553ba27816cd8167c64652406d86ca78bcc5989f20fDimitris Michailidis		snprintf(adap->msix_info[msi_idx++].desc, n, "%s-rdma%d",
554b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis			 adap->port[0]->name, i);
555b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
556b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
557b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int request_msix_queue_irqs(struct adapter *adap)
558b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
559b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge *s = &adap->sge;
560b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int err, ethqidx, ofldqidx = 0, rdmaqidx = 0, msi = 2;
561b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
562b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = request_irq(adap->msix_info[1].vec, t4_sge_intr_msix, 0,
563b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			  adap->msix_info[1].desc, &s->fw_evtq);
564b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err)
565b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return err;
566b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
567b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_ethrxq(s, ethqidx) {
568b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
569b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  adap->msix_info[msi].desc,
570b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  &s->ethrxq[ethqidx].rspq);
571b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
572b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto unwind;
573b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		msi++;
574b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
575b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_ofldrxq(s, ofldqidx) {
576b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
577b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  adap->msix_info[msi].desc,
578b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  &s->ofldrxq[ofldqidx].rspq);
579b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
580b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto unwind;
581b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		msi++;
582b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
583b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_rdmarxq(s, rdmaqidx) {
584b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = request_irq(adap->msix_info[msi].vec, t4_sge_intr_msix, 0,
585b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  adap->msix_info[msi].desc,
586b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  &s->rdmarxq[rdmaqidx].rspq);
587b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
588b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto unwind;
589b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		msi++;
590b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
591b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
592b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
593b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisunwind:
594b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (--rdmaqidx >= 0)
595b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adap->msix_info[--msi].vec,
596b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 &s->rdmarxq[rdmaqidx].rspq);
597b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (--ofldqidx >= 0)
598b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adap->msix_info[--msi].vec,
599b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 &s->ofldrxq[ofldqidx].rspq);
600b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (--ethqidx >= 0)
601b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adap->msix_info[--msi].vec, &s->ethrxq[ethqidx].rspq);
602b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	free_irq(adap->msix_info[1].vec, &s->fw_evtq);
603b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
604b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
605b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
606b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void free_msix_queue_irqs(struct adapter *adap)
607b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
608b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i, msi = 2;
609b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge *s = &adap->sge;
610b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
611b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	free_irq(adap->msix_info[1].vec, &s->fw_evtq);
612b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_ethrxq(s, i)
613b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adap->msix_info[msi++].vec, &s->ethrxq[i].rspq);
614b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_ofldrxq(s, i)
615b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adap->msix_info[msi++].vec, &s->ofldrxq[i].rspq);
616b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_rdmarxq(s, i)
617b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adap->msix_info[msi++].vec, &s->rdmarxq[i].rspq);
618b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
619b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
620b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
621671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *	write_rss - write the RSS table for a given port
622671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *	@pi: the port
623671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *	@queues: array of queue indices for RSS
624671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *
625671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *	Sets up the portion of the HW RSS table for the port's VI to distribute
626671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *	packets to the Rx queues in @queues.
627671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis */
628671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidisstatic int write_rss(const struct port_info *pi, const u16 *queues)
629671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis{
630671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	u16 *rss;
631671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	int i, err;
632671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	const struct sge_eth_rxq *q = &pi->adapter->sge.ethrxq[pi->first_qset];
633671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
634671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	rss = kmalloc(pi->rss_size * sizeof(u16), GFP_KERNEL);
635671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	if (!rss)
636671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		return -ENOMEM;
637671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
638671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	/* map the queue indices to queue ids */
639671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	for (i = 0; i < pi->rss_size; i++, queues++)
640671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		rss[i] = q[*queues].rspq.abs_id;
641671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
642060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	err = t4_config_rss_range(pi->adapter, pi->adapter->fn, pi->viid, 0,
643060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				  pi->rss_size, rss, pi->rss_size);
644671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	kfree(rss);
645671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	return err;
646671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis}
647671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
648671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis/**
649b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	setup_rss - configure RSS
650b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@adap: the adapter
651b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
652671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis *	Sets up RSS for each port.
653b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
654b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int setup_rss(struct adapter *adap)
655b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
656671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	int i, err;
657b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
658b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, i) {
659b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct port_info *pi = adap2pinfo(adap, i);
660b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
661671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		err = write_rss(pi, pi->rss);
662b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
663b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return err;
664b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
665b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
666b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
667b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
668b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
669e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis * Return the channel of the ingress queue with the given qid.
670e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis */
671e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidisstatic unsigned int rxq_to_chan(const struct sge *p, unsigned int qid)
672e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis{
673e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	qid -= p->ingr_start;
674e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	return netdev2pinfo(p->ingr_map[qid]->netdev)->tx_chan;
675e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis}
676e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis
677e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis/*
678b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Wait until all NAPI handlers are descheduled.
679b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
680b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void quiesce_rx(struct adapter *adap)
681b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
682b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
683b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
684b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(adap->sge.ingr_map); i++) {
685b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_rspq *q = adap->sge.ingr_map[i];
686b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
687b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (q && q->handler)
688b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			napi_disable(&q->napi);
689b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
690b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
691b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
692b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
693b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Enable NAPI scheduling and interrupt generation for all Rx queues.
694b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
695b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void enable_rx(struct adapter *adap)
696b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
697b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
698b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
699b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(adap->sge.ingr_map); i++) {
700b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_rspq *q = adap->sge.ingr_map[i];
701b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
702b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!q)
703b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			continue;
704b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (q->handler)
705b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			napi_enable(&q->napi);
706b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/* 0-increment GTS to start the timer and enable interrupts */
707b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_write_reg(adap, MYPF_REG(SGE_PF_GTS),
708b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			     SEINTARM(q->intr_params) |
709b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			     INGRESSQID(q->cntxt_id));
710b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
711b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
712b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
713b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
714b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	setup_sge_queues - configure SGE Tx/Rx/response queues
715b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@adap: the adapter
716b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
717b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Determines how many sets of SGE queues to use and initializes them.
718b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	We support multiple queue sets per port if we have MSI-X, otherwise
719b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	just one queue set per port.
720b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
721b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int setup_sge_queues(struct adapter *adap)
722b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
723b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int err, msi_idx, i, j;
724b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge *s = &adap->sge;
725b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
726b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	bitmap_zero(s->starving_fl, MAX_EGRQ);
727b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	bitmap_zero(s->txq_maperr, MAX_EGRQ);
728b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
729b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adap->flags & USING_MSIX)
730b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		msi_idx = 1;         /* vector 0 is for non-queue interrupts */
731b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else {
732b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0,
733b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				       NULL, NULL);
734b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
735b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return err;
736b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		msi_idx = -((int)s->intrq.abs_id + 1);
737b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
738b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
739b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = t4_sge_alloc_rxq(adap, &s->fw_evtq, true, adap->port[0],
740b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       msi_idx, NULL, fwevtq_handler);
741b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err) {
742b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisfreeout:	t4_free_sge_resources(adap);
743b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return err;
744b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
745b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
746b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, i) {
747b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct net_device *dev = adap->port[i];
748b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct port_info *pi = netdev_priv(dev);
749b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_eth_rxq *q = &s->ethrxq[pi->first_qset];
750b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_eth_txq *t = &s->ethtxq[pi->first_qset];
751b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
752b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		for (j = 0; j < pi->nqsets; j++, q++) {
753b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (msi_idx > 0)
754b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				msi_idx++;
755b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev,
756b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					       msi_idx, &q->fl,
757b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					       t4_ethrx_handler);
758b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (err)
759b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				goto freeout;
760b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			q->rspq.idx = j;
761b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			memset(&q->stats, 0, sizeof(q->stats));
762b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
763b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		for (j = 0; j < pi->nqsets; j++, t++) {
764b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			err = t4_sge_alloc_eth_txq(adap, t, dev,
765b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					netdev_get_tx_queue(dev, j),
766b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					s->fw_evtq.cntxt_id);
767b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (err)
768b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				goto freeout;
769b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
770b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
771b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
772b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	j = s->ofldqsets / adap->params.nports; /* ofld queues per channel */
773b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_ofldrxq(s, i) {
774b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_ofld_rxq *q = &s->ofldrxq[i];
775b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct net_device *dev = adap->port[i / j];
776b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
777b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (msi_idx > 0)
778b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			msi_idx++;
779b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_sge_alloc_rxq(adap, &q->rspq, false, dev, msi_idx,
780b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				       &q->fl, uldrx_handler);
781b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
782b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto freeout;
783b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		memset(&q->stats, 0, sizeof(q->stats));
784b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ofld_rxq[i] = q->rspq.abs_id;
785b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_sge_alloc_ofld_txq(adap, &s->ofldtxq[i], dev,
786b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					    s->fw_evtq.cntxt_id);
787b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
788b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto freeout;
789b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
790b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
791b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_rdmarxq(s, i) {
792b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_ofld_rxq *q = &s->rdmarxq[i];
793b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
794b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (msi_idx > 0)
795b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			msi_idx++;
796b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_sge_alloc_rxq(adap, &q->rspq, false, adap->port[i],
797b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				       msi_idx, &q->fl, uldrx_handler);
798b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
799b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto freeout;
800b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		memset(&q->stats, 0, sizeof(q->stats));
801b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->rdma_rxq[i] = q->rspq.abs_id;
802b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
803b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
804b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, i) {
805b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/*
806b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * Note that ->rdmarxq[i].rspq.cntxt_id below is 0 if we don't
807b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * have RDMA queues, and that's the right value.
808b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 */
809b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_sge_alloc_ctrl_txq(adap, &s->ctrlq[i], adap->port[i],
810b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					    s->fw_evtq.cntxt_id,
811b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					    s->rdmarxq[i].rspq.cntxt_id);
812b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
813b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto freeout;
814b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
815b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
816b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_write_reg(adap, MPS_TRC_RSS_CONTROL,
817b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     RSSCONTROL(netdev2pinfo(adap->port[0])->tx_chan) |
818b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     QUEUENUMBER(s->ethrxq[0].rspq.abs_id));
819b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
820b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
821b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
822b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
823b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Returns 0 if new FW was successfully loaded, a positive errno if a load was
824b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * started but failed, and a negative errno if flash load couldn't start.
825b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
826b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int upgrade_fw(struct adapter *adap)
827b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
828b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
829b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 vers;
830b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct fw_hdr *hdr;
831b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct firmware *fw;
832b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct device *dev = adap->pdev_dev;
833b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
834b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ret = request_firmware(&fw, FW_FNAME, dev);
835b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0) {
836b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_err(dev, "unable to load firmware image " FW_FNAME
837b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			", error %d\n", ret);
838b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return ret;
839b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
840b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
841b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	hdr = (const struct fw_hdr *)fw->data;
842b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	vers = ntohl(hdr->fw_ver);
843b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (FW_HDR_FW_VER_MAJOR_GET(vers) != FW_VERSION_MAJOR) {
844b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		ret = -EINVAL;              /* wrong major version, won't do */
845b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out;
846b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
847b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
848b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/*
849b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * If the flash FW is unusable or we found something newer, load it.
850b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 */
851b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (FW_HDR_FW_VER_MAJOR_GET(adap->params.fw_vers) != FW_VERSION_MAJOR ||
852b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	    vers > adap->params.fw_vers) {
853b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		ret = -t4_load_fw(adap, fw->data, fw->size);
854b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!ret)
855b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			dev_info(dev, "firmware upgraded to version %pI4 from "
856b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				 FW_FNAME "\n", &hdr->fw_ver);
857b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
858b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisout:	release_firmware(fw);
859b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
860b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
861b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
862b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
863b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
864b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * The allocated memory is cleared.
865b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
866b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid *t4_alloc_mem(size_t size)
867b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
86889bf67f1f080c947c92f8773482d9e57767ca292Eric Dumazet	void *p = kzalloc(size, GFP_KERNEL);
869b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
870b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!p)
87189bf67f1f080c947c92f8773482d9e57767ca292Eric Dumazet		p = vzalloc(size);
872b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return p;
873b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
874b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
875b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
876b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Free memory allocated through alloc_mem().
877b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
87831b9c19bfe32bed7fdf80cd0b1aa9d0f0569844astephen hemmingerstatic void t4_free_mem(void *addr)
879b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
880b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (is_vmalloc_addr(addr))
881b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		vfree(addr);
882b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else
883b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		kfree(addr);
884b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
885b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
886b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic inline int is_offload(const struct adapter *adap)
887b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
888b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return adap->params.offload;
889b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
890b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
891b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
892b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Implementation of ethtool operations.
893b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
894b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
895b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic u32 get_msglevel(struct net_device *dev)
896b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
897b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return netdev2adap(dev)->msg_enable;
898b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
899b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
900b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void set_msglevel(struct net_device *dev, u32 val)
901b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
902b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	netdev2adap(dev)->msg_enable = val;
903b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
904b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
905b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic char stats_strings[][ETH_GSTRING_LEN] = {
906b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxOctetsOK         ",
907b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFramesOK         ",
908b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxBroadcastFrames  ",
909b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxMulticastFrames  ",
910b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxUnicastFrames    ",
911b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxErrorFrames      ",
912b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
913b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames64         ",
914b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames65To127    ",
915b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames128To255   ",
916b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames256To511   ",
917b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames512To1023  ",
918b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames1024To1518 ",
919b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFrames1519ToMax  ",
920b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
921b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxFramesDropped    ",
922b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPauseFrames      ",
923b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP0Frames       ",
924b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP1Frames       ",
925b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP2Frames       ",
926b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP3Frames       ",
927b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP4Frames       ",
928b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP5Frames       ",
929b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP6Frames       ",
930b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxPPP7Frames       ",
931b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
932b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxOctetsOK         ",
933b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFramesOK         ",
934b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBroadcastFrames  ",
935b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxMulticastFrames  ",
936b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxUnicastFrames    ",
937b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
938b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFramesTooLong    ",
939b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxJabberErrors     ",
940b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFCSErrors        ",
941b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxLengthErrors     ",
942b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxSymbolErrors     ",
943b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxRuntFrames       ",
944b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
945b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames64         ",
946b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames65To127    ",
947b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames128To255   ",
948b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames256To511   ",
949b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames512To1023  ",
950b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames1024To1518 ",
951b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxFrames1519ToMax  ",
952b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
953b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPauseFrames      ",
954b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP0Frames       ",
955b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP1Frames       ",
956b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP2Frames       ",
957b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP3Frames       ",
958b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP4Frames       ",
959b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP5Frames       ",
960b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP6Frames       ",
961b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxPPP7Frames       ",
962b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
963b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG0FramesDropped ",
964b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG1FramesDropped ",
965b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG2FramesDropped ",
966b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG3FramesDropped ",
967b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG0FramesTrunc   ",
968b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG1FramesTrunc   ",
969b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG2FramesTrunc   ",
970b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxBG3FramesTrunc   ",
971b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
972b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TSO                ",
973b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"TxCsumOffload      ",
974b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"RxCsumGood         ",
975b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"VLANextractions    ",
976b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	"VLANinsertions     ",
9774a6346d4ea63b5e1390babf22f1cc0f113d8082bDimitris Michailidis	"GROpackets         ",
9784a6346d4ea63b5e1390babf22f1cc0f113d8082bDimitris Michailidis	"GROmerged          ",
979b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
980b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
981b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int get_sset_count(struct net_device *dev, int sset)
982b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
983b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	switch (sset) {
984b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	case ETH_SS_STATS:
985b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return ARRAY_SIZE(stats_strings);
986b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	default:
987b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EOPNOTSUPP;
988b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
989b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
990b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
991b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define T4_REGMAP_SIZE (160 * 1024)
992b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
993b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int get_regs_len(struct net_device *dev)
994b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
995b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return T4_REGMAP_SIZE;
996b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
997b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
998b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int get_eeprom_len(struct net_device *dev)
999b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1000b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return EEPROMSIZE;
1001b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1002b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1003b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1004b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1005b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = netdev2adap(dev);
1006b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
100723020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
100823020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
100923020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->bus_info, pci_name(adapter->pdev),
101023020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones		sizeof(info->bus_info));
1011b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
101284b405011166e663fe9ef56c29b1d76f59b35568Rick Jones	if (adapter->params.fw_vers)
1013b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		snprintf(info->fw_version, sizeof(info->fw_version),
1014b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			"%u.%u.%u.%u, TP %u.%u.%u.%u",
1015b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers),
1016b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers),
1017b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers),
1018b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_BUILD_GET(adapter->params.fw_vers),
1019b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_MAJOR_GET(adapter->params.tp_vers),
1020b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_MINOR_GET(adapter->params.tp_vers),
1021b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_MICRO_GET(adapter->params.tp_vers),
1022b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			FW_HDR_FW_VER_BUILD_GET(adapter->params.tp_vers));
1023b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1024b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1025b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_strings(struct net_device *dev, u32 stringset, u8 *data)
1026b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1027b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (stringset == ETH_SS_STATS)
1028b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		memcpy(data, stats_strings, sizeof(stats_strings));
1029b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1030b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1031b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
1032b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * port stats maintained per queue of the port.  They should be in the same
1033b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * order as in stats_strings above.
1034b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
1035b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstruct queue_port_stats {
1036b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 tso;
1037b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 tx_csum;
1038b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 rx_csum;
1039b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 vlan_ex;
1040b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u64 vlan_ins;
10414a6346d4ea63b5e1390babf22f1cc0f113d8082bDimitris Michailidis	u64 gro_pkts;
10424a6346d4ea63b5e1390babf22f1cc0f113d8082bDimitris Michailidis	u64 gro_merged;
1043b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
1044b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1045b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void collect_sge_port_stats(const struct adapter *adap,
1046b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		const struct port_info *p, struct queue_port_stats *s)
1047b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1048b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
1049b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct sge_eth_txq *tx = &adap->sge.ethtxq[p->first_qset];
1050b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct sge_eth_rxq *rx = &adap->sge.ethrxq[p->first_qset];
1051b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1052b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	memset(s, 0, sizeof(*s));
1053b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < p->nqsets; i++, rx++, tx++) {
1054b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->tso += tx->tso;
1055b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->tx_csum += tx->tx_cso;
1056b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->rx_csum += rx->stats.rx_cso;
1057b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->vlan_ex += rx->stats.vlan_ex;
1058b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->vlan_ins += tx->vlan_ins;
10594a6346d4ea63b5e1390babf22f1cc0f113d8082bDimitris Michailidis		s->gro_pkts += rx->stats.lro_pkts;
10604a6346d4ea63b5e1390babf22f1cc0f113d8082bDimitris Michailidis		s->gro_merged += rx->stats.lro_merged;
1061b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1062b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1063b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1064b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_stats(struct net_device *dev, struct ethtool_stats *stats,
1065b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		      u64 *data)
1066b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1067b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
1068b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = pi->adapter;
1069b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1070b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_get_port_stats(adapter, pi->tx_chan, (struct port_stats *)data);
1071b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1072b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	data += sizeof(struct port_stats) / sizeof(u64);
1073b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
1074b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1075b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1076b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
1077b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Return a version number to identify the type of adapter.  The scheme is:
1078b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * - bits 0..9: chip version
1079b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * - bits 10..15: chip revision
1080835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis * - bits 16..23: register dump version
1081b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
1082b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic inline unsigned int mk_adap_vers(const struct adapter *ap)
1083b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1084835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis	return 4 | (ap->params.rev << 10) | (1 << 16);
1085b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1086b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1087b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void reg_block_dump(struct adapter *ap, void *buf, unsigned int start,
1088b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			   unsigned int end)
1089b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1090b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 *p = buf + start;
1091b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1092b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for ( ; start <= end; start += sizeof(u32))
1093b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		*p++ = t4_read_reg(ap, start);
1094b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1095b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1096b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_regs(struct net_device *dev, struct ethtool_regs *regs,
1097b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     void *buf)
1098b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1099b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	static const unsigned int reg_ranges[] = {
1100b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1008, 0x1108,
1101b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1180, 0x11b4,
1102b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x11fc, 0x123c,
1103b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1300, 0x173c,
1104b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1800, 0x18fc,
1105b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x3000, 0x30d8,
1106b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x30e0, 0x5924,
1107b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x5960, 0x59d4,
1108b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x5a00, 0x5af8,
1109b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6000, 0x6098,
1110b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6100, 0x6150,
1111b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6200, 0x6208,
1112b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6240, 0x6248,
1113b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6280, 0x6338,
1114b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6370, 0x638c,
1115b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6400, 0x643c,
1116b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6500, 0x6524,
1117b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6a00, 0x6a38,
1118b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6a60, 0x6a78,
1119b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6b00, 0x6b84,
1120b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6bf0, 0x6c84,
1121b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6cf0, 0x6d84,
1122b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6df0, 0x6e84,
1123b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6ef0, 0x6f84,
1124b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x6ff0, 0x7084,
1125b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x70f0, 0x7184,
1126b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x71f0, 0x7284,
1127b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x72f0, 0x7384,
1128b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x73f0, 0x7450,
1129b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7500, 0x7530,
1130b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7600, 0x761c,
1131b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7680, 0x76cc,
1132b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7700, 0x7798,
1133b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x77c0, 0x77fc,
1134b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7900, 0x79fc,
1135b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7b00, 0x7c38,
1136b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x7d00, 0x7efc,
1137b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x8dc0, 0x8e1c,
1138b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x8e30, 0x8e78,
1139b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x8ea0, 0x8f6c,
1140b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x8fc0, 0x9074,
1141b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x90fc, 0x90fc,
1142b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9400, 0x9458,
1143b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9600, 0x96bc,
1144b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9800, 0x9808,
1145b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9820, 0x983c,
1146b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9850, 0x9864,
1147b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9c00, 0x9c6c,
1148b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9c80, 0x9cec,
1149b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9d00, 0x9d6c,
1150b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9d80, 0x9dec,
1151b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9e00, 0x9e6c,
1152b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9e80, 0x9eec,
1153b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9f00, 0x9f6c,
1154b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x9f80, 0x9fec,
1155b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0xd004, 0xd03c,
1156b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0xdfc0, 0xdfe0,
1157b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0xe000, 0xea7c,
1158b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0xf000, 0x11190,
1159835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x19040, 0x1906c,
1160835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x19078, 0x19080,
1161835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1908c, 0x19124,
1162b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x19150, 0x191b0,
1163b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x191d0, 0x191e8,
1164b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x19238, 0x1924c,
1165b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x193f8, 0x19474,
1166b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x19490, 0x194f8,
1167b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x19800, 0x19f30,
1168b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1a000, 0x1a06c,
1169b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1a0b0, 0x1a120,
1170b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1a128, 0x1a138,
1171b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1a190, 0x1a1c4,
1172b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1a1fc, 0x1a1fc,
1173b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e040, 0x1e04c,
1174835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1e284, 0x1e28c,
1175b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e2c0, 0x1e2c0,
1176b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e2e0, 0x1e2e0,
1177b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e300, 0x1e384,
1178b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e3c0, 0x1e3c8,
1179b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e440, 0x1e44c,
1180835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1e684, 0x1e68c,
1181b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e6c0, 0x1e6c0,
1182b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e6e0, 0x1e6e0,
1183b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e700, 0x1e784,
1184b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e7c0, 0x1e7c8,
1185b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1e840, 0x1e84c,
1186835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1ea84, 0x1ea8c,
1187b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1eac0, 0x1eac0,
1188b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1eae0, 0x1eae0,
1189b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1eb00, 0x1eb84,
1190b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1ebc0, 0x1ebc8,
1191b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1ec40, 0x1ec4c,
1192835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1ee84, 0x1ee8c,
1193b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1eec0, 0x1eec0,
1194b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1eee0, 0x1eee0,
1195b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1ef00, 0x1ef84,
1196b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1efc0, 0x1efc8,
1197b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f040, 0x1f04c,
1198835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1f284, 0x1f28c,
1199b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f2c0, 0x1f2c0,
1200b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f2e0, 0x1f2e0,
1201b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f300, 0x1f384,
1202b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f3c0, 0x1f3c8,
1203b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f440, 0x1f44c,
1204835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1f684, 0x1f68c,
1205b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f6c0, 0x1f6c0,
1206b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f6e0, 0x1f6e0,
1207b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f700, 0x1f784,
1208b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f7c0, 0x1f7c8,
1209b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1f840, 0x1f84c,
1210835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1fa84, 0x1fa8c,
1211b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fac0, 0x1fac0,
1212b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fae0, 0x1fae0,
1213b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fb00, 0x1fb84,
1214b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fbc0, 0x1fbc8,
1215b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fc40, 0x1fc4c,
1216835bb606faffcd761e7abbc6b5de89ea5c409123Dimitris Michailidis		0x1fe84, 0x1fe8c,
1217b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fec0, 0x1fec0,
1218b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1fee0, 0x1fee0,
1219b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1ff00, 0x1ff84,
1220b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x1ffc0, 0x1ffc8,
1221b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x20000, 0x2002c,
1222b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x20100, 0x2013c,
1223b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x20190, 0x201c8,
1224b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x20200, 0x20318,
1225b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x20400, 0x20528,
1226b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x20540, 0x20614,
1227b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21000, 0x21040,
1228b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2104c, 0x21060,
1229b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x210c0, 0x210ec,
1230b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21200, 0x21268,
1231b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21270, 0x21284,
1232b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x212fc, 0x21388,
1233b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21400, 0x21404,
1234b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21500, 0x21518,
1235b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2152c, 0x2153c,
1236b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21550, 0x21554,
1237b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21600, 0x21600,
1238b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21608, 0x21628,
1239b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21630, 0x2163c,
1240b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21700, 0x2171c,
1241b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21780, 0x2178c,
1242b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21800, 0x21c38,
1243b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21c80, 0x21d7c,
1244b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x21e00, 0x21e04,
1245b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x22000, 0x2202c,
1246b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x22100, 0x2213c,
1247b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x22190, 0x221c8,
1248b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x22200, 0x22318,
1249b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x22400, 0x22528,
1250b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x22540, 0x22614,
1251b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23000, 0x23040,
1252b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2304c, 0x23060,
1253b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x230c0, 0x230ec,
1254b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23200, 0x23268,
1255b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23270, 0x23284,
1256b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x232fc, 0x23388,
1257b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23400, 0x23404,
1258b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23500, 0x23518,
1259b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2352c, 0x2353c,
1260b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23550, 0x23554,
1261b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23600, 0x23600,
1262b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23608, 0x23628,
1263b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23630, 0x2363c,
1264b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23700, 0x2371c,
1265b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23780, 0x2378c,
1266b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23800, 0x23c38,
1267b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23c80, 0x23d7c,
1268b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x23e00, 0x23e04,
1269b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x24000, 0x2402c,
1270b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x24100, 0x2413c,
1271b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x24190, 0x241c8,
1272b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x24200, 0x24318,
1273b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x24400, 0x24528,
1274b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x24540, 0x24614,
1275b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25000, 0x25040,
1276b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2504c, 0x25060,
1277b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x250c0, 0x250ec,
1278b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25200, 0x25268,
1279b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25270, 0x25284,
1280b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x252fc, 0x25388,
1281b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25400, 0x25404,
1282b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25500, 0x25518,
1283b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2552c, 0x2553c,
1284b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25550, 0x25554,
1285b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25600, 0x25600,
1286b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25608, 0x25628,
1287b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25630, 0x2563c,
1288b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25700, 0x2571c,
1289b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25780, 0x2578c,
1290b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25800, 0x25c38,
1291b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25c80, 0x25d7c,
1292b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x25e00, 0x25e04,
1293b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x26000, 0x2602c,
1294b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x26100, 0x2613c,
1295b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x26190, 0x261c8,
1296b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x26200, 0x26318,
1297b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x26400, 0x26528,
1298b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x26540, 0x26614,
1299b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27000, 0x27040,
1300b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2704c, 0x27060,
1301b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x270c0, 0x270ec,
1302b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27200, 0x27268,
1303b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27270, 0x27284,
1304b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x272fc, 0x27388,
1305b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27400, 0x27404,
1306b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27500, 0x27518,
1307b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x2752c, 0x2753c,
1308b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27550, 0x27554,
1309b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27600, 0x27600,
1310b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27608, 0x27628,
1311b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27630, 0x2763c,
1312b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27700, 0x2771c,
1313b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27780, 0x2778c,
1314b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27800, 0x27c38,
1315b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27c80, 0x27d7c,
1316b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		0x27e00, 0x27e04
1317b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	};
1318b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1319b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
1320b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *ap = netdev2adap(dev);
1321b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1322b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	regs->version = mk_adap_vers(ap);
1323b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1324b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	memset(buf, 0, T4_REGMAP_SIZE);
1325b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(reg_ranges); i += 2)
1326b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		reg_block_dump(ap, buf, reg_ranges[i], reg_ranges[i + 1]);
1327b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1328b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1329b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int restart_autoneg(struct net_device *dev)
1330b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1331b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *p = netdev_priv(dev);
1332b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1333b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!netif_running(dev))
1334b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EAGAIN;
1335b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (p->link_cfg.autoneg != AUTONEG_ENABLE)
1336b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1337060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	t4_restart_aneg(p->adapter, p->adapter->fn, p->tx_chan);
1338b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1339b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1340b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1341c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidisstatic int identify_port(struct net_device *dev,
1342c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis			 enum ethtool_phys_id_state state)
1343b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1344c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis	unsigned int val;
1345060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	struct adapter *adap = netdev2adap(dev);
1346060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis
1347c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis	if (state == ETHTOOL_ID_ACTIVE)
1348c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis		val = 0xffff;
1349c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis	else if (state == ETHTOOL_ID_INACTIVE)
1350c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis		val = 0;
1351c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis	else
1352c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis		return -EINVAL;
1353b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1354c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis	return t4_identify_port(adap, adap->fn, netdev2pinfo(dev)->viid, val);
1355b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1356b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1357b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps)
1358b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1359b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int v = 0;
1360b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1361a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	if (type == FW_PORT_TYPE_BT_SGMII || type == FW_PORT_TYPE_BT_XFI ||
1362a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	    type == FW_PORT_TYPE_BT_XAUI) {
1363b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= SUPPORTED_TP;
1364b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (caps & FW_PORT_CAP_SPEED_100M)
1365b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			v |= SUPPORTED_100baseT_Full;
1366b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (caps & FW_PORT_CAP_SPEED_1G)
1367b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			v |= SUPPORTED_1000baseT_Full;
1368b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (caps & FW_PORT_CAP_SPEED_10G)
1369b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			v |= SUPPORTED_10000baseT_Full;
1370b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (type == FW_PORT_TYPE_KX4 || type == FW_PORT_TYPE_KX) {
1371b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= SUPPORTED_Backplane;
1372b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (caps & FW_PORT_CAP_SPEED_1G)
1373b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			v |= SUPPORTED_1000baseKX_Full;
1374b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (caps & FW_PORT_CAP_SPEED_10G)
1375b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			v |= SUPPORTED_10000baseKX4_Full;
1376b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (type == FW_PORT_TYPE_KR)
1377b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= SUPPORTED_Backplane | SUPPORTED_10000baseKR_Full;
1378a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	else if (type == FW_PORT_TYPE_BP_AP)
13797d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC |
13807d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis		     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full;
13817d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis	else if (type == FW_PORT_TYPE_BP4_AP)
13827d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis		v |= SUPPORTED_Backplane | SUPPORTED_10000baseR_FEC |
13837d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis		     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full |
13847d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis		     SUPPORTED_10000baseKX4_Full;
1385a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	else if (type == FW_PORT_TYPE_FIBER_XFI ||
1386a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		 type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
1387b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= SUPPORTED_FIBRE;
1388b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1389b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (caps & FW_PORT_CAP_ANEG)
1390b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= SUPPORTED_Autoneg;
1391b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return v;
1392b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1393b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1394b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int to_fw_linkcaps(unsigned int caps)
1395b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1396b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int v = 0;
1397b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1398b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (caps & ADVERTISED_100baseT_Full)
1399b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= FW_PORT_CAP_SPEED_100M;
1400b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (caps & ADVERTISED_1000baseT_Full)
1401b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= FW_PORT_CAP_SPEED_1G;
1402b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (caps & ADVERTISED_10000baseT_Full)
1403b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		v |= FW_PORT_CAP_SPEED_10G;
1404b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return v;
1405b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1406b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1407b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1408b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1409b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *p = netdev_priv(dev);
1410b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1411b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (p->port_type == FW_PORT_TYPE_BT_SGMII ||
1412a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	    p->port_type == FW_PORT_TYPE_BT_XFI ||
1413b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	    p->port_type == FW_PORT_TYPE_BT_XAUI)
1414b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->port = PORT_TP;
1415a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	else if (p->port_type == FW_PORT_TYPE_FIBER_XFI ||
1416a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		 p->port_type == FW_PORT_TYPE_FIBER_XAUI)
1417b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->port = PORT_FIBRE;
1418a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	else if (p->port_type == FW_PORT_TYPE_SFP) {
1419a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		if (p->mod_type == FW_PORT_MOD_TYPE_TWINAX_PASSIVE ||
1420a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		    p->mod_type == FW_PORT_MOD_TYPE_TWINAX_ACTIVE)
1421a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis			cmd->port = PORT_DA;
1422a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		else
1423a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis			cmd->port = PORT_FIBRE;
1424a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	} else
1425b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->port = PORT_OTHER;
1426b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1427b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (p->mdio_addr >= 0) {
1428b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->phy_address = p->mdio_addr;
1429b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->transceiver = XCVR_EXTERNAL;
1430b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->mdio_support = p->port_type == FW_PORT_TYPE_BT_SGMII ?
1431b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			MDIO_SUPPORTS_C22 : MDIO_SUPPORTS_C45;
1432b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else {
1433b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->phy_address = 0;  /* not really, but no better option */
1434b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->transceiver = XCVR_INTERNAL;
1435b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cmd->mdio_support = 0;
1436b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1437b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1438b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cmd->supported = from_fw_linkcaps(p->port_type, p->link_cfg.supported);
1439b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cmd->advertising = from_fw_linkcaps(p->port_type,
1440b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					    p->link_cfg.advertising);
1441707394972093e2056e1e8cc39be19cf9bcb3e7b3David Decotigny	ethtool_cmd_speed_set(cmd,
1442707394972093e2056e1e8cc39be19cf9bcb3e7b3David Decotigny			      netif_carrier_ok(dev) ? p->link_cfg.speed : 0);
1443b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cmd->duplex = DUPLEX_FULL;
1444b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cmd->autoneg = p->link_cfg.autoneg;
1445b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cmd->maxtxpkt = 0;
1446b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cmd->maxrxpkt = 0;
1447b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1448b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1449b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1450b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int speed_to_caps(int speed)
1451b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1452b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (speed == SPEED_100)
1453b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return FW_PORT_CAP_SPEED_100M;
1454b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (speed == SPEED_1000)
1455b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return FW_PORT_CAP_SPEED_1G;
1456b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (speed == SPEED_10000)
1457b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return FW_PORT_CAP_SPEED_10G;
1458b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1459b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1460b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1461b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1462b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1463b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int cap;
1464b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *p = netdev_priv(dev);
1465b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct link_config *lc = &p->link_cfg;
146625db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny	u32 speed = ethtool_cmd_speed(cmd);
1467b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1468b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (cmd->duplex != DUPLEX_FULL)     /* only full-duplex supported */
1469b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1470b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1471b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!(lc->supported & FW_PORT_CAP_ANEG)) {
1472b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/*
1473b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * PHY offers a single speed.  See if that's what's
1474b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * being requested.
1475b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 */
1476b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (cmd->autoneg == AUTONEG_DISABLE &&
147725db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		    (lc->supported & speed_to_caps(speed)))
147825db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny			return 0;
1479b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1480b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1481b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1482b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (cmd->autoneg == AUTONEG_DISABLE) {
148325db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		cap = speed_to_caps(speed);
1484b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
148525db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		if (!(lc->supported & cap) || (speed == SPEED_1000) ||
148625db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		    (speed == SPEED_10000))
1487b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return -EINVAL;
1488b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->requested_speed = cap;
1489b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->advertising = 0;
1490b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else {
1491b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cap = to_fw_linkcaps(cmd->advertising);
1492b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!(lc->supported & cap))
1493b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return -EINVAL;
1494b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->requested_speed = 0;
1495b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->advertising = cap | FW_PORT_CAP_ANEG;
1496b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1497b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lc->autoneg = cmd->autoneg;
1498b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1499b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (netif_running(dev))
1500060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		return t4_link_start(p->adapter, p->adapter->fn, p->tx_chan,
1501060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				     lc);
1502b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1503b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1504b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1505b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_pauseparam(struct net_device *dev,
1506b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			   struct ethtool_pauseparam *epause)
1507b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1508b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *p = netdev_priv(dev);
1509b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1510b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	epause->autoneg = (p->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
1511b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	epause->rx_pause = (p->link_cfg.fc & PAUSE_RX) != 0;
1512b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	epause->tx_pause = (p->link_cfg.fc & PAUSE_TX) != 0;
1513b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1514b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1515b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_pauseparam(struct net_device *dev,
1516b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			  struct ethtool_pauseparam *epause)
1517b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1518b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *p = netdev_priv(dev);
1519b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct link_config *lc = &p->link_cfg;
1520b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1521b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (epause->autoneg == AUTONEG_DISABLE)
1522b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->requested_fc = 0;
1523b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else if (lc->supported & FW_PORT_CAP_ANEG)
1524b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->requested_fc = PAUSE_AUTONEG;
1525b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else
1526b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1527b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1528b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (epause->rx_pause)
1529b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->requested_fc |= PAUSE_RX;
1530b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (epause->tx_pause)
1531b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lc->requested_fc |= PAUSE_TX;
1532b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (netif_running(dev))
1533060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		return t4_link_start(p->adapter, p->adapter->fn, p->tx_chan,
1534060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				     lc);
1535b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1536b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1537b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1538b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
1539b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1540b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
1541b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct sge *s = &pi->adapter->sge;
1542b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1543b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->rx_max_pending = MAX_RX_BUFFERS;
1544b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->rx_mini_max_pending = MAX_RSPQ_ENTRIES;
1545b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->rx_jumbo_max_pending = 0;
1546b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->tx_max_pending = MAX_TXQ_ENTRIES;
1547b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1548b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->rx_pending = s->ethrxq[pi->first_qset].fl.size - 8;
1549b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->rx_mini_pending = s->ethrxq[pi->first_qset].rspq.size;
1550b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->rx_jumbo_pending = 0;
1551b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->tx_pending = s->ethtxq[pi->first_qset].q.size;
1552b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1553b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1554b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
1555b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1556b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
1557b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
1558b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = pi->adapter;
1559b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge *s = &adapter->sge;
1560b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1561b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (e->rx_pending > MAX_RX_BUFFERS || e->rx_jumbo_pending ||
1562b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	    e->tx_pending > MAX_TXQ_ENTRIES ||
1563b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	    e->rx_mini_pending > MAX_RSPQ_ENTRIES ||
1564b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	    e->rx_mini_pending < MIN_RSPQ_ENTRIES ||
1565b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	    e->rx_pending < MIN_FL_ENTRIES || e->tx_pending < MIN_TXQ_ENTRIES)
1566b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1567b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1568b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adapter->flags & FULL_INIT_DONE)
1569b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EBUSY;
1570b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1571b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < pi->nqsets; ++i) {
1572b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ethtxq[pi->first_qset + i].q.size = e->tx_pending;
1573b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ethrxq[pi->first_qset + i].fl.size = e->rx_pending + 8;
1574b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ethrxq[pi->first_qset + i].rspq.size = e->rx_mini_pending;
1575b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1576b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1577b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1578b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1579b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int closest_timer(const struct sge *s, int time)
1580b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1581b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i, delta, match = 0, min_delta = INT_MAX;
1582b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1583b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->timer_val); i++) {
1584b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		delta = time - s->timer_val[i];
1585b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (delta < 0)
1586b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			delta = -delta;
1587b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (delta < min_delta) {
1588b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			min_delta = delta;
1589b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			match = i;
1590b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
1591b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1592b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return match;
1593b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1594b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1595b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int closest_thres(const struct sge *s, int thres)
1596b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1597b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i, delta, match = 0, min_delta = INT_MAX;
1598b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1599b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->counter_val); i++) {
1600b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		delta = thres - s->counter_val[i];
1601b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (delta < 0)
1602b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			delta = -delta;
1603b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (delta < min_delta) {
1604b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			min_delta = delta;
1605b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			match = i;
1606b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
1607b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1608b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return match;
1609b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1610b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1611b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
1612b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Return a queue's interrupt hold-off time in us.  0 means no timer.
1613b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
1614b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic unsigned int qtimer_val(const struct adapter *adap,
1615b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       const struct sge_rspq *q)
1616b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1617b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int idx = q->intr_params >> 1;
1618b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1619b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return idx < SGE_NTIMERS ? adap->sge.timer_val[idx] : 0;
1620b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1621b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1622b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
1623b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	set_rxq_intr_params - set a queue's interrupt holdoff parameters
1624b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@adap: the adapter
1625b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@q: the Rx queue
1626b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@us: the hold-off time in us, or 0 to disable timer
1627b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@cnt: the hold-off packet count, or 0 to disable counter
1628b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
1629b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Sets an Rx queue's interrupt hold-off time and packet count.  At least
1630b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	one of the two needs to be enabled for the queue to generate interrupts.
1631b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
1632b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_rxq_intr_params(struct adapter *adap, struct sge_rspq *q,
1633b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       unsigned int us, unsigned int cnt)
1634b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1635b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if ((us | cnt) == 0)
1636b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cnt = 1;
1637b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1638b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (cnt) {
1639b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		int err;
1640b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		u32 v, new_idx;
1641b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1642b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		new_idx = closest_thres(&adap->sge, cnt);
1643b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (q->desc && q->pktcnt_idx != new_idx) {
1644b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			/* the queue has already been created, update it */
1645b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			v = FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
1646b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			    FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) |
1647b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			    FW_PARAMS_PARAM_YZ(q->cntxt_id);
1648060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			err = t4_set_params(adap, adap->fn, adap->fn, 0, 1, &v,
1649060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis					    &new_idx);
1650b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (err)
1651b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				return err;
1652b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
1653b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		q->pktcnt_idx = new_idx;
1654b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1655b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1656b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	us = us == 0 ? 6 : closest_timer(&adap->sge, us);
1657b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	q->intr_params = QINTR_TIMER_IDX(us) | (cnt > 0 ? QINTR_CNT_EN : 0);
1658b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1659b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1660b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1661b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
1662b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1663b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
1664b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = pi->adapter;
1665b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1666b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq,
1667b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			c->rx_coalesce_usecs, c->rx_max_coalesced_frames);
1668b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1669b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1670b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
1671b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1672b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
1673b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct adapter *adap = pi->adapter;
1674b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct sge_rspq *rq = &adap->sge.ethrxq[pi->first_qset].rspq;
1675b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1676b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	c->rx_coalesce_usecs = qtimer_val(adap, rq);
1677b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	c->rx_max_coalesced_frames = (rq->intr_params & QINTR_CNT_EN) ?
1678b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->sge.counter_val[rq->pktcnt_idx] : 0;
1679b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
1680b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1681b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
16821478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis/**
16831478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	eeprom_ptov - translate a physical EEPROM address to virtual
16841478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	@phys_addr: the physical EEPROM address
16851478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	@fn: the PCI function number
16861478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	@sz: size of function-specific area
16871478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *
16881478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	Translate a physical EEPROM address to virtual.  The first 1K is
16891478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	accessed through virtual addresses starting at 31K, the rest is
16901478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	accessed through virtual addresses starting at 0.
16911478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *
16921478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	The mapping is as follows:
16931478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	[0..1K) -> [31K..32K)
16941478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	[1K..1K+A) -> [31K-A..31K)
16951478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	[1K+A..ES) -> [0..ES-A-1K)
16961478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *
16971478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis *	where A = @fn * @sz, and ES = EEPROM size.
1698b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
16991478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidisstatic int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
1700b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
17011478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis	fn *= sz;
1702b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (phys_addr < 1024)
1703b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return phys_addr + (31 << 10);
17041478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis	if (phys_addr < 1024 + fn)
17051478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis		return 31744 - fn + phys_addr - 1024;
1706b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (phys_addr < EEPROMSIZE)
17071478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis		return phys_addr - 1024 - fn;
1708b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return -EINVAL;
1709b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1710b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1711b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
1712b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * The next two routines implement eeprom read/write from physical addresses.
1713b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
1714b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
1715b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
17161478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis	int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
1717b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1718b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (vaddr >= 0)
1719b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v);
1720b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return vaddr < 0 ? vaddr : 0;
1721b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1722b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1723b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
1724b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
17251478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis	int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
1726b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1727b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (vaddr >= 0)
1728b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v);
1729b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return vaddr < 0 ? vaddr : 0;
1730b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1731b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1732b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define EEPROM_MAGIC 0x38E2F10C
1733b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1734b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
1735b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		      u8 *data)
1736b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1737b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i, err = 0;
1738b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = netdev2adap(dev);
1739b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1740b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL);
1741b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!buf)
1742b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -ENOMEM;
1743b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1744b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	e->magic = EEPROM_MAGIC;
1745b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = e->offset & ~3; !err && i < e->offset + e->len; i += 4)
1746b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = eeprom_rd_phys(adapter, i, (u32 *)&buf[i]);
1747b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1748b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!err)
1749b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		memcpy(data, buf + e->offset, e->len);
1750b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	kfree(buf);
1751b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
1752b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1753b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1754b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
1755b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		      u8 *data)
1756b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1757b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u8 *buf;
1758b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int err = 0;
1759b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 aligned_offset, aligned_len, *p;
1760b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = netdev2adap(dev);
1761b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1762b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (eeprom->magic != EEPROM_MAGIC)
1763b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1764b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1765b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	aligned_offset = eeprom->offset & ~3;
1766b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
1767b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
17681478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis	if (adapter->fn > 0) {
17691478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis		u32 start = 1024 + adapter->fn * EEPROMPFSIZE;
17701478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis
17711478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis		if (aligned_offset < start ||
17721478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis		    aligned_offset + aligned_len > start + EEPROMPFSIZE)
17731478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis			return -EPERM;
17741478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis	}
17751478b3ee931e83c7a94f61376e962574b28d23d6Dimitris Michailidis
1776b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
1777b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/*
1778b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * RMW possibly needed for first or last words.
1779b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 */
1780b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		buf = kmalloc(aligned_len, GFP_KERNEL);
1781b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!buf)
1782b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return -ENOMEM;
1783b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = eeprom_rd_phys(adapter, aligned_offset, (u32 *)buf);
1784b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!err && aligned_len > 4)
1785b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			err = eeprom_rd_phys(adapter,
1786b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					     aligned_offset + aligned_len - 4,
1787b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					     (u32 *)&buf[aligned_len - 4]);
1788b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
1789b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto out;
1790b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		memcpy(buf + (eeprom->offset & 3), data, eeprom->len);
1791b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else
1792b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		buf = data;
1793b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1794b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = t4_seeprom_wp(adapter, false);
1795b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err)
1796b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out;
1797b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1798b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (p = (u32 *)buf; !err && aligned_len; aligned_len -= 4, p++) {
1799b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = eeprom_wr_phys(adapter, aligned_offset, *p);
1800b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		aligned_offset += 4;
1801b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
1802b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1803b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!err)
1804b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_seeprom_wp(adapter, true);
1805b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisout:
1806b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (buf != data)
1807b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		kfree(buf);
1808b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
1809b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1810b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1811b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
1812b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1813b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
1814b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct firmware *fw;
1815b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = netdev2adap(netdev);
1816b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1817b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ef->data[sizeof(ef->data) - 1] = '\0';
1818b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ret = request_firmware(&fw, ef->data, adap->pdev_dev);
1819b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0)
1820b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return ret;
1821b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1822b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ret = t4_load_fw(adap, fw->data, fw->size);
1823b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	release_firmware(fw);
1824b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!ret)
1825b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_info(adap->pdev_dev, "loaded firmware %s\n", ef->data);
1826b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
1827b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1828b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1829b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define WOL_SUPPORTED (WAKE_BCAST | WAKE_MAGIC)
1830b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define BCAST_CRC 0xa0ccc1a6
1831b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1832b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1833b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1834b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	wol->supported = WAKE_BCAST | WAKE_MAGIC;
1835b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	wol->wolopts = netdev2adap(dev)->wol;
1836b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	memset(&wol->sopass, 0, sizeof(wol->sopass));
1837b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1838b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1839b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1840b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
1841b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int err = 0;
1842b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
1843b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1844b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (wol->wolopts & ~WOL_SUPPORTED)
1845b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
1846b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_wol_magic_enable(pi->adapter, pi->tx_chan,
1847b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			    (wol->wolopts & WAKE_MAGIC) ? dev->dev_addr : NULL);
1848b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (wol->wolopts & WAKE_BCAST) {
1849b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = t4_wol_pat_enable(pi->adapter, pi->tx_chan, 0xfe, ~0ULL,
1850b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					~0ULL, 0, false);
1851b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!err)
1852b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			err = t4_wol_pat_enable(pi->adapter, pi->tx_chan, 1,
1853b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis						~6ULL, ~0ULL, BCAST_CRC, true);
1854b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else
1855b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_wol_pat_enable(pi->adapter, pi->tx_chan, 0, 0, 0, 0, false);
1856b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
1857b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
1858b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
1859c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosławstatic int cxgb_set_features(struct net_device *dev, netdev_features_t features)
186087b6cf51acb4999fff7e6841986874b108679cb4Dimitris Michailidis{
18612ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław	const struct port_info *pi = netdev_priv(dev);
1862c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław	netdev_features_t changed = dev->features ^ features;
186319ecae2c8fd5e54e40ace914a41d8e1beb41612cDimitris Michailidis	int err;
186419ecae2c8fd5e54e40ace914a41d8e1beb41612cDimitris Michailidis
18652ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław	if (!(changed & NETIF_F_HW_VLAN_RX))
18662ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław		return 0;
186719ecae2c8fd5e54e40ace914a41d8e1beb41612cDimitris Michailidis
18682ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław	err = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, -1,
18692ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław			    -1, -1, -1,
18702ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław			    !!(features & NETIF_F_HW_VLAN_RX), true);
18712ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław	if (unlikely(err))
18722ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław		dev->features = features ^ NETIF_F_HW_VLAN_RX;
187319ecae2c8fd5e54e40ace914a41d8e1beb41612cDimitris Michailidis	return err;
187487b6cf51acb4999fff7e6841986874b108679cb4Dimitris Michailidis}
187587b6cf51acb4999fff7e6841986874b108679cb4Dimitris Michailidis
18767850f63f1620512631445b901ae11cd149e7375cBen Hutchingsstatic u32 get_rss_table_size(struct net_device *dev)
1877671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis{
1878671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
1879671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
18807850f63f1620512631445b901ae11cd149e7375cBen Hutchings	return pi->rss_size;
18817850f63f1620512631445b901ae11cd149e7375cBen Hutchings}
18827850f63f1620512631445b901ae11cd149e7375cBen Hutchings
18837850f63f1620512631445b901ae11cd149e7375cBen Hutchingsstatic int get_rss_table(struct net_device *dev, u32 *p)
18847850f63f1620512631445b901ae11cd149e7375cBen Hutchings{
18857850f63f1620512631445b901ae11cd149e7375cBen Hutchings	const struct port_info *pi = netdev_priv(dev);
18867850f63f1620512631445b901ae11cd149e7375cBen Hutchings	unsigned int n = pi->rss_size;
18877850f63f1620512631445b901ae11cd149e7375cBen Hutchings
1888671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	while (n--)
18897850f63f1620512631445b901ae11cd149e7375cBen Hutchings		p[n] = pi->rss[n];
1890671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	return 0;
1891671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis}
1892671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
18937850f63f1620512631445b901ae11cd149e7375cBen Hutchingsstatic int set_rss_table(struct net_device *dev, const u32 *p)
1894671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis{
1895671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	unsigned int i;
1896671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	struct port_info *pi = netdev_priv(dev);
1897671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
18987850f63f1620512631445b901ae11cd149e7375cBen Hutchings	for (i = 0; i < pi->rss_size; i++)
18997850f63f1620512631445b901ae11cd149e7375cBen Hutchings		pi->rss[i] = p[i];
1900671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	if (pi->adapter->flags & FULL_INIT_DONE)
1901671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		return write_rss(pi, pi->rss);
1902671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	return 0;
1903671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis}
1904671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
1905671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidisstatic int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
1906815c7db5c809ea3d5735de3131ecdf758b0e14ffBen Hutchings		     u32 *rules)
1907671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis{
1908f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
1909f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis
1910671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	switch (info->cmd) {
1911f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis	case ETHTOOL_GRXFH: {
1912f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		unsigned int v = pi->rss_mode;
1913f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis
1914f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		info->data = 0;
1915f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		switch (info->flow_type) {
1916f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case TCP_V4_FLOW:
1917f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN)
1918f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST |
1919f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
1920f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
1921f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST;
1922f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			break;
1923f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case UDP_V4_FLOW:
1924f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) &&
1925f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			    (v & FW_RSS_VI_CONFIG_CMD_UDPEN))
1926f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST |
1927f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
1928f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
1929f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST;
1930f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			break;
1931f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case SCTP_V4_FLOW:
1932f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case AH_ESP_V4_FLOW:
1933f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case IPV4_FLOW:
1934f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
1935f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST;
1936f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			break;
1937f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case TCP_V6_FLOW:
1938f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)
1939f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST |
1940f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
1941f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
1942f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST;
1943f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			break;
1944f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case UDP_V6_FLOW:
1945f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) &&
1946f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			    (v & FW_RSS_VI_CONFIG_CMD_UDPEN))
1947f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST |
1948f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis					     RXH_L4_B_0_1 | RXH_L4_B_2_3;
1949f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
1950f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST;
1951f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			break;
1952f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case SCTP_V6_FLOW:
1953f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case AH_ESP_V6_FLOW:
1954f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		case IPV6_FLOW:
1955f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
1956f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis				info->data = RXH_IP_SRC | RXH_IP_DST;
1957f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis			break;
1958f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		}
1959f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		return 0;
1960f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis	}
1961671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	case ETHTOOL_GRXRINGS:
1962f796564a5fd7be1a4597b66e2a516c18685641dfDimitris Michailidis		info->data = pi->nqsets;
1963671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		return 0;
1964671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	}
1965671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	return -EOPNOTSUPP;
1966671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis}
1967671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
19689b07be4b2a78166bc54c8eedf18da8a8aafacfabstephen hemmingerstatic const struct ethtool_ops cxgb_ethtool_ops = {
1969b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_settings      = get_settings,
1970b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_settings      = set_settings,
1971b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_drvinfo       = get_drvinfo,
1972b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_msglevel      = get_msglevel,
1973b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_msglevel      = set_msglevel,
1974b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_ringparam     = get_sge_param,
1975b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_ringparam     = set_sge_param,
1976b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_coalesce      = get_coalesce,
1977b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_coalesce      = set_coalesce,
1978b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_eeprom_len    = get_eeprom_len,
1979b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_eeprom        = get_eeprom,
1980b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_eeprom        = set_eeprom,
1981b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_pauseparam    = get_pauseparam,
1982b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_pauseparam    = set_pauseparam,
1983b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_link          = ethtool_op_get_link,
1984b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_strings       = get_strings,
1985c5e06360317d9c7a91de983749d136c4089e5379Dimitris Michailidis	.set_phys_id       = identify_port,
1986b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.nway_reset        = restart_autoneg,
1987b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_sset_count    = get_sset_count,
1988b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_ethtool_stats = get_stats,
1989b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_regs_len      = get_regs_len,
1990b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_regs          = get_regs,
1991b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.get_wol           = get_wol,
1992b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.set_wol           = set_wol,
1993671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	.get_rxnfc         = get_rxnfc,
19947850f63f1620512631445b901ae11cd149e7375cBen Hutchings	.get_rxfh_indir_size = get_rss_table_size,
1995671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	.get_rxfh_indir    = get_rss_table,
1996671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	.set_rxfh_indir    = set_rss_table,
1997b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.flash_device      = set_flash,
1998b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
1999b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2000b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2001b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * debugfs support
2002b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2003b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic ssize_t mem_read(struct file *file, char __user *buf, size_t count,
2004b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			loff_t *ppos)
2005b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2006b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	loff_t pos = *ppos;
2007b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	loff_t avail = file->f_path.dentry->d_inode->i_size;
2008b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int mem = (uintptr_t)file->private_data & 3;
2009b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = file->private_data - mem;
2010b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2011b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (pos < 0)
2012b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
2013b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (pos >= avail)
2014b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return 0;
2015b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (count > avail - pos)
2016b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		count = avail - pos;
2017b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2018b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (count) {
2019b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		size_t len;
2020b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		int ret, ofst;
2021b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		__be32 data[16];
2022b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2023b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (mem == MEM_MC)
2024b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ret = t4_mc_read(adap, pos, data, NULL);
2025b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		else
2026b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ret = t4_edc_read(adap, mem, pos, data, NULL);
2027b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (ret)
2028b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return ret;
2029b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2030b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		ofst = pos % sizeof(data);
2031b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		len = min(count, sizeof(data) - ofst);
2032b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (copy_to_user(buf, (u8 *)data + ofst, len))
2033b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return -EFAULT;
2034b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2035b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		buf += len;
2036b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pos += len;
2037b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		count -= len;
2038b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2039b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	count = pos - *ppos;
2040b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	*ppos = pos;
2041b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return count;
2042b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2043b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2044b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic const struct file_operations mem_debugfs_fops = {
2045b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.owner   = THIS_MODULE,
2046234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd	.open    = simple_open,
2047b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.read    = mem_read,
20486038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek  = default_llseek,
2049b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
2050b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2051b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
2052b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				      unsigned int idx, unsigned int size_mb)
2053b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2054b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct dentry *de;
2055b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2056b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root,
2057b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				 (void *)adap + idx, &mem_debugfs_fops);
2058b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (de && de->d_inode)
2059b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		de->d_inode->i_size = size_mb << 20;
2060b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2061b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2062b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int __devinit setup_debugfs(struct adapter *adap)
2063b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2064b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
2065b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2066b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (IS_ERR_OR_NULL(adap->debugfs_root))
2067b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -1;
2068b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2069b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE);
2070b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (i & EDRAM0_ENABLE)
2071b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		add_debugfs_mem(adap, "edc0", MEM_EDC0, 5);
2072b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (i & EDRAM1_ENABLE)
2073b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		add_debugfs_mem(adap, "edc1", MEM_EDC1, 5);
2074b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (i & EXT_MEM_ENABLE)
2075b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		add_debugfs_mem(adap, "mc", MEM_MC,
2076b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)));
2077b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adap->l2t)
2078b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		debugfs_create_file("l2t", S_IRUSR, adap->debugfs_root, adap,
2079b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				    &t4_l2t_fops);
2080b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
2081b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2082b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2083b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2084b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * upper-layer driver support
2085b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2086b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2087b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2088b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Allocate an active-open TID and set it to the supplied value.
2089b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2090b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisint cxgb4_alloc_atid(struct tid_info *t, void *data)
2091b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2092b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int atid = -1;
2093b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2094b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_bh(&t->atid_lock);
2095b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (t->afree) {
2096b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		union aopen_entry *p = t->afree;
2097b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2098b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		atid = p - t->atid_tab;
2099b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t->afree = p->next;
2100b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		p->data = data;
2101b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t->atids_in_use++;
2102b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2103b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock_bh(&t->atid_lock);
2104b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return atid;
2105b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2106b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_alloc_atid);
2107b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2108b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2109b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Release an active-open TID.
2110b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2111b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid cxgb4_free_atid(struct tid_info *t, unsigned int atid)
2112b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2113b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	union aopen_entry *p = &t->atid_tab[atid];
2114b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2115b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_bh(&t->atid_lock);
2116b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	p->next = t->afree;
2117b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->afree = p;
2118b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->atids_in_use--;
2119b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock_bh(&t->atid_lock);
2120b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2121b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_free_atid);
2122b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2123b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2124b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Allocate a server TID and set it to the supplied value.
2125b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2126b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisint cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
2127b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2128b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int stid;
2129b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2130b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_bh(&t->stid_lock);
2131b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (family == PF_INET) {
2132b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		stid = find_first_zero_bit(t->stid_bmap, t->nstids);
2133b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (stid < t->nstids)
2134b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			__set_bit(stid, t->stid_bmap);
2135b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		else
2136b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			stid = -1;
2137b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else {
2138b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		stid = bitmap_find_free_region(t->stid_bmap, t->nstids, 2);
2139b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (stid < 0)
2140b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			stid = -1;
2141b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2142b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (stid >= 0) {
2143b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t->stid_tab[stid].data = data;
2144b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		stid += t->stid_base;
2145b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t->stids_in_use++;
2146b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2147b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock_bh(&t->stid_lock);
2148b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return stid;
2149b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2150b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_alloc_stid);
2151b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2152b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2153b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Release a server TID.
2154b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2155b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
2156b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2157b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	stid -= t->stid_base;
2158b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_bh(&t->stid_lock);
2159b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (family == PF_INET)
2160b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		__clear_bit(stid, t->stid_bmap);
2161b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	else
2162b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		bitmap_release_region(t->stid_bmap, stid, 2);
2163b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->stid_tab[stid].data = NULL;
2164b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->stids_in_use--;
2165b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock_bh(&t->stid_lock);
2166b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2167b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_free_stid);
2168b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2169b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2170b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Populate a TID_RELEASE WR.  Caller must properly size the skb.
2171b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2172b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void mk_tid_release(struct sk_buff *skb, unsigned int chan,
2173b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			   unsigned int tid)
2174b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2175b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct cpl_tid_release *req;
2176b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2177b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	set_wr_txq(skb, CPL_PRIORITY_SETUP, chan);
2178b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req = (struct cpl_tid_release *)__skb_put(skb, sizeof(*req));
2179b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	INIT_TP_WR(req, tid);
2180b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_TID_RELEASE, tid));
2181b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2182b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2183b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2184b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Queue a TID release request and if necessary schedule a work queue to
2185b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * process it.
2186b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
218731b9c19bfe32bed7fdf80cd0b1aa9d0f0569844astephen hemmingerstatic void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
218831b9c19bfe32bed7fdf80cd0b1aa9d0f0569844astephen hemminger				    unsigned int tid)
2189b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2190b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	void **p = &t->tid_tab[tid];
2191b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = container_of(t, struct adapter, tids);
2192b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2193b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_bh(&adap->tid_release_lock);
2194b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	*p = adap->tid_release_head;
2195b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* Low 2 bits encode the Tx channel number */
2196b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->tid_release_head = (void **)((uintptr_t)p | chan);
2197b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!adap->tid_release_task_busy) {
2198b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->tid_release_task_busy = true;
2199b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		schedule_work(&adap->tid_release_task);
2200b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2201b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock_bh(&adap->tid_release_lock);
2202b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2203b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2204b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2205b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Process the list of pending TID release requests.
2206b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2207b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void process_tid_release_list(struct work_struct *work)
2208b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2209b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sk_buff *skb;
2210b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap;
2211b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2212b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap = container_of(work, struct adapter, tid_release_task);
2213b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2214b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_bh(&adap->tid_release_lock);
2215b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (adap->tid_release_head) {
2216b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		void **p = adap->tid_release_head;
2217b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		unsigned int chan = (uintptr_t)p & 3;
2218b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		p = (void *)p - chan;
2219b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2220b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->tid_release_head = *p;
2221b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		*p = NULL;
2222b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		spin_unlock_bh(&adap->tid_release_lock);
2223b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2224b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		while (!(skb = alloc_skb(sizeof(struct cpl_tid_release),
2225b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					 GFP_KERNEL)))
2226b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			schedule_timeout_uninterruptible(1);
2227b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2228b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		mk_tid_release(skb, chan, p - adap->tids.tid_tab);
2229b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_ofld_send(adap, skb);
2230b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		spin_lock_bh(&adap->tid_release_lock);
2231b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2232b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->tid_release_task_busy = false;
2233b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock_bh(&adap->tid_release_lock);
2234b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2235b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2236b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2237b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Release a TID and inform HW.  If we are unable to allocate the release
2238b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * message we defer to a work queue.
2239b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2240b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid)
2241b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2242b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	void *old;
2243b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sk_buff *skb;
2244b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = container_of(t, struct adapter, tids);
2245b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2246b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	old = t->tid_tab[tid];
2247b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	skb = alloc_skb(sizeof(struct cpl_tid_release), GFP_ATOMIC);
2248b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (likely(skb)) {
2249b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t->tid_tab[tid] = NULL;
2250b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		mk_tid_release(skb, chan, tid);
2251b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_ofld_send(adap, skb);
2252b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else
2253b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		cxgb4_queue_tid_release(t, chan, tid);
2254b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (old)
2255b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		atomic_dec(&t->tids_in_use);
2256b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2257b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_remove_tid);
2258b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2259b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2260b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Allocate and initialize the TID tables.  Returns 0 on success.
2261b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2262b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int tid_init(struct tid_info *t)
2263b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2264b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	size_t size;
2265b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int natids = t->natids;
2266b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2267b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	size = t->ntids * sizeof(*t->tid_tab) + natids * sizeof(*t->atid_tab) +
2268b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	       t->nstids * sizeof(*t->stid_tab) +
2269b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	       BITS_TO_LONGS(t->nstids) * sizeof(long);
2270b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->tid_tab = t4_alloc_mem(size);
2271b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!t->tid_tab)
2272b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -ENOMEM;
2273b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2274b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids];
2275b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
2276b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids];
2277b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_init(&t->stid_lock);
2278b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_init(&t->atid_lock);
2279b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2280b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->stids_in_use = 0;
2281b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->afree = NULL;
2282b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t->atids_in_use = 0;
2283b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	atomic_set(&t->tids_in_use, 0);
2284b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2285b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* Setup the free list for atid_tab and clear the stid bitmap. */
2286b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (natids) {
2287b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		while (--natids)
2288b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			t->atid_tab[natids - 1].next = &t->atid_tab[natids];
2289b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t->afree = t->atid_tab;
2290b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2291b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	bitmap_zero(t->stid_bmap, t->nstids);
2292b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
2293b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2294b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2295b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2296b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_create_server - create an IP server
2297b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@dev: the device
2298b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@stid: the server TID
2299b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@sip: local IP address to bind server to
2300b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@sport: the server's TCP port
2301b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@queue: queue to direct messages from this server to
2302b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2303b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Create an IP server for the given port and address.
2304b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Returns <0 on error and one of the %NET_XMIT_* values on success.
2305b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2306b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisint cxgb4_create_server(const struct net_device *dev, unsigned int stid,
2307b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			__be32 sip, __be16 sport, unsigned int queue)
2308b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2309b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int chan;
2310b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sk_buff *skb;
2311b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap;
2312b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct cpl_pass_open_req *req;
2313b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2314b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	skb = alloc_skb(sizeof(*req), GFP_KERNEL);
2315b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!skb)
2316b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -ENOMEM;
2317b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2318b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap = netdev2adap(dev);
2319b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req = (struct cpl_pass_open_req *)__skb_put(skb, sizeof(*req));
2320b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	INIT_TP_WR(req, 0);
2321b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, stid));
2322b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req->local_port = sport;
2323b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req->peer_port = htons(0);
2324b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req->local_ip = sip;
2325b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req->peer_ip = htonl(0);
2326e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	chan = rxq_to_chan(&adap->sge, queue);
2327b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req->opt0 = cpu_to_be64(TX_CHAN(chan));
2328b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
2329b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
2330b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return t4_mgmt_tx(adap, skb);
2331b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2332b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_create_server);
2333b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2334b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2335b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_best_mtu - find the entry in the MTU table closest to an MTU
2336b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@mtus: the HW MTU table
2337b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@mtu: the target MTU
2338b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@idx: index of selected entry in the MTU table
2339b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2340b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Returns the index and the value in the HW MTU table that is closest to
2341b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	but does not exceed @mtu, unless @mtu is smaller than any value in the
2342b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	table, in which case that smallest available value is selected.
2343b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2344b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisunsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu,
2345b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			    unsigned int *idx)
2346b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2347b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int i = 0;
2348b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2349b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (i < NMTUS - 1 && mtus[i + 1] <= mtu)
2350b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		++i;
2351b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (idx)
2352b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		*idx = i;
2353b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return mtus[i];
2354b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2355b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_best_mtu);
2356b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2357b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2358b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_port_chan - get the HW channel of a port
2359b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@dev: the net device for the port
2360b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2361b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Return the HW Tx channel of the given port.
2362b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2363b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisunsigned int cxgb4_port_chan(const struct net_device *dev)
2364b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2365b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return netdev2pinfo(dev)->tx_chan;
2366b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2367b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_port_chan);
2368b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2369b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2370b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_port_viid - get the VI id of a port
2371b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@dev: the net device for the port
2372b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2373b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Return the VI id of the given port.
2374b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2375b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisunsigned int cxgb4_port_viid(const struct net_device *dev)
2376b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2377b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return netdev2pinfo(dev)->viid;
2378b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2379b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_port_viid);
2380b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2381b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2382b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_port_idx - get the index of a port
2383b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@dev: the net device for the port
2384b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2385b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Return the index of the given port.
2386b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2387b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisunsigned int cxgb4_port_idx(const struct net_device *dev)
2388b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2389b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return netdev2pinfo(dev)->port_id;
2390b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2391b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_port_idx);
2392b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2393b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid cxgb4_get_tcp_stats(struct pci_dev *pdev, struct tp_tcp_stats *v4,
2394b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 struct tp_tcp_stats *v6)
2395b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2396b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = pci_get_drvdata(pdev);
2397b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2398b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock(&adap->stats_lock);
2399b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_tp_get_tcp_stats(adap, v4, v6);
2400b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock(&adap->stats_lock);
2401b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2402b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_get_tcp_stats);
2403b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2404b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
2405b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		      const unsigned int *pgsz_order)
2406b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2407b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = netdev2adap(dev);
2408b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2409b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_write_reg(adap, ULP_RX_ISCSI_TAGMASK, tag_mask);
2410b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_write_reg(adap, ULP_RX_ISCSI_PSZ, HPZ0(pgsz_order[0]) |
2411b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     HPZ1(pgsz_order[1]) | HPZ2(pgsz_order[2]) |
2412b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     HPZ3(pgsz_order[3]));
2413b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2414b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_iscsi_init);
2415b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2416b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic struct pci_driver cxgb4_driver;
2417b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2418b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void check_neigh_update(struct neighbour *neigh)
2419b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2420b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct device *parent;
2421b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	const struct net_device *netdev = neigh->dev;
2422b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2423b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (netdev->priv_flags & IFF_802_1Q_VLAN)
2424b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev = vlan_dev_real_dev(netdev);
2425b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	parent = netdev->dev.parent;
2426b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (parent && parent->driver == &cxgb4_driver.driver)
2427b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_l2t_update(dev_get_drvdata(parent), neigh);
2428b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2429b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2430b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int netevent_cb(struct notifier_block *nb, unsigned long event,
2431b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		       void *data)
2432b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2433b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	switch (event) {
2434b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	case NETEVENT_NEIGH_UPDATE:
2435b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		check_neigh_update(data);
2436b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		break;
2437b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	case NETEVENT_REDIRECT:
2438b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	default:
2439b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		break;
2440b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2441b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
2442b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2443b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2444b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic bool netevent_registered;
2445b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic struct notifier_block cxgb4_netevent_nb = {
2446b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.notifier_call = netevent_cb
2447b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
2448b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2449b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void uld_attach(struct adapter *adap, unsigned int uld)
2450b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2451b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	void *handle;
2452b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct cxgb4_lld_info lli;
2453b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2454b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.pdev = adap->pdev;
2455b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.l2t = adap->l2t;
2456b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.tids = &adap->tids;
2457b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.ports = adap->port;
2458b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.vr = &adap->vres;
2459b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.mtus = adap->params.mtus;
2460b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (uld == CXGB4_ULD_RDMA) {
2461b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lli.rxq_ids = adap->sge.rdma_rxq;
2462b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lli.nrxq = adap->sge.rdmaqs;
2463b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (uld == CXGB4_ULD_ISCSI) {
2464b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lli.rxq_ids = adap->sge.ofld_rxq;
2465b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		lli.nrxq = adap->sge.ofldqsets;
2466b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2467b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.ntxq = adap->sge.ofldqsets;
2468b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.nchan = adap->params.nports;
2469b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.nports = adap->params.nports;
2470b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.wr_cred = adap->params.ofldq_wr_cred;
2471b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.adapter_type = adap->params.rev;
2472b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
2473b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
2474060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
2475060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			(adap->fn * 4));
2476b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
2477060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
2478060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			(adap->fn * 4));
2479b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
2480b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
2481b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	lli.fw_vers = adap->params.fw_vers;
2482b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2483b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	handle = ulds[uld].add(&lli);
2484b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (IS_ERR(handle)) {
2485b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_warn(adap->pdev_dev,
2486b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 "could not attach to the %s driver, error %ld\n",
2487b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 uld_str[uld], PTR_ERR(handle));
2488b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return;
2489b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2490b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2491b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->uld_handle[uld] = handle;
2492b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2493b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!netevent_registered) {
2494b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		register_netevent_notifier(&cxgb4_netevent_nb);
2495b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netevent_registered = true;
2496b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2497e29f5dbc9e9719af158a960e5c1d16f32740ebc3Dimitris Michailidis
2498e29f5dbc9e9719af158a960e5c1d16f32740ebc3Dimitris Michailidis	if (adap->flags & FULL_INIT_DONE)
2499e29f5dbc9e9719af158a960e5c1d16f32740ebc3Dimitris Michailidis		ulds[uld].state_change(handle, CXGB4_STATE_UP);
2500b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2501b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2502b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void attach_ulds(struct adapter *adap)
2503b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2504b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int i;
2505b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2506b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_lock(&uld_mutex);
2507b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	list_add_tail(&adap->list_node, &adapter_list);
2508b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < CXGB4_ULD_MAX; i++)
2509b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (ulds[i].add)
2510b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			uld_attach(adap, i);
2511b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_unlock(&uld_mutex);
2512b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2513b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2514b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void detach_ulds(struct adapter *adap)
2515b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2516b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int i;
2517b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2518b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_lock(&uld_mutex);
2519b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	list_del(&adap->list_node);
2520b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < CXGB4_ULD_MAX; i++)
2521b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (adap->uld_handle[i]) {
2522b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ulds[i].state_change(adap->uld_handle[i],
2523b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					     CXGB4_STATE_DETACH);
2524b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			adap->uld_handle[i] = NULL;
2525b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
2526b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (netevent_registered && list_empty(&adapter_list)) {
2527b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		unregister_netevent_notifier(&cxgb4_netevent_nb);
2528b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netevent_registered = false;
2529b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2530b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_unlock(&uld_mutex);
2531b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2532b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2533b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void notify_ulds(struct adapter *adap, enum cxgb4_state new_state)
2534b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2535b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int i;
2536b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2537b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_lock(&uld_mutex);
2538b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < CXGB4_ULD_MAX; i++)
2539b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (adap->uld_handle[i])
2540b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ulds[i].state_change(adap->uld_handle[i], new_state);
2541b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_unlock(&uld_mutex);
2542b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2543b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2544b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2545b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_register_uld - register an upper-layer driver
2546b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@type: the ULD type
2547b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@p: the ULD methods
2548b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2549b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Registers an upper-layer driver with this driver and notifies the ULD
2550b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	about any presently available devices that support its type.  Returns
2551b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	%-EBUSY if a ULD of the same type is already registered.
2552b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2553b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisint cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p)
2554b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2555b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret = 0;
2556b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap;
2557b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2558b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (type >= CXGB4_ULD_MAX)
2559b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
2560b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_lock(&uld_mutex);
2561b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ulds[type].add) {
2562b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		ret = -EBUSY;
2563b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out;
2564b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2565b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ulds[type] = *p;
2566b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	list_for_each_entry(adap, &adapter_list, list_node)
2567b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		uld_attach(adap, type);
2568b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisout:	mutex_unlock(&uld_mutex);
2569b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
2570b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2571b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_register_uld);
2572b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2573b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2574b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb4_unregister_uld - unregister an upper-layer driver
2575b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@type: the ULD type
2576b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2577b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Unregisters an existing upper-layer driver.
2578b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2579b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisint cxgb4_unregister_uld(enum cxgb4_uld type)
2580b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2581b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap;
2582b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2583b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (type >= CXGB4_ULD_MAX)
2584b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
2585b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_lock(&uld_mutex);
2586b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	list_for_each_entry(adap, &adapter_list, list_node)
2587b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->uld_handle[type] = NULL;
2588b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ulds[type].add = NULL;
2589b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	mutex_unlock(&uld_mutex);
2590b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
2591b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2592b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris MichailidisEXPORT_SYMBOL(cxgb4_unregister_uld);
2593b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2594b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/**
2595b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	cxgb_up - enable the adapter
2596b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	@adap: adapter being enabled
2597b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2598b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Called when the first port is enabled, this function performs the
2599b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	actions necessary to make an adapter operational, such as completing
2600b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	the initialization of HW modules, and enabling interrupts.
2601b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *
2602b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis *	Must be called with the rtnl lock held.
2603b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2604b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int cxgb_up(struct adapter *adap)
2605b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2606aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	int err;
2607b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2608aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	err = setup_sge_queues(adap);
2609aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	if (err)
2610aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis		goto out;
2611aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	err = setup_rss(adap);
2612aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	if (err)
2613aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis		goto freeq;
2614b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2615b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adap->flags & USING_MSIX) {
2616aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis		name_msix_vecs(adap);
2617b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = request_irq(adap->msix_info[0].vec, t4_nondata_intr, 0,
2618b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  adap->msix_info[0].desc, adap);
2619b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
2620b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto irq_err;
2621b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2622b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = request_msix_queue_irqs(adap);
2623b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err) {
2624b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			free_irq(adap->msix_info[0].vec, adap);
2625b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto irq_err;
2626b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
2627b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else {
2628b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = request_irq(adap->pdev->irq, t4_intr_handler(adap),
2629b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  (adap->flags & USING_MSI) ? 0 : IRQF_SHARED,
2630b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis				  adap->port[0]->name, adap);
2631b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
2632b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto irq_err;
2633b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2634b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	enable_rx(adap);
2635b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_sge_start(adap);
2636b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_intr_enable(adap);
2637aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	adap->flags |= FULL_INIT_DONE;
2638b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	notify_ulds(adap, CXGB4_STATE_UP);
2639b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis out:
2640b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
2641b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis irq_err:
2642b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	dev_err(adap->pdev_dev, "request_irq failed, err %d\n", err);
2643aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis freeq:
2644aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	t4_free_sge_resources(adap);
2645b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	goto out;
2646b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2647b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2648b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void cxgb_down(struct adapter *adapter)
2649b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2650b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_intr_disable(adapter);
2651b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cancel_work_sync(&adapter->tid_release_task);
2652b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter->tid_release_task_busy = false;
2653204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	adapter->tid_release_head = NULL;
2654b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2655b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adapter->flags & USING_MSIX) {
2656b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_msix_queue_irqs(adapter);
2657b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adapter->msix_info[0].vec, adapter);
2658b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else
2659b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		free_irq(adapter->pdev->irq, adapter);
2660b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	quiesce_rx(adapter);
2661aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	t4_sge_stop(adapter);
2662aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	t4_free_sge_resources(adapter);
2663aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	adapter->flags &= ~FULL_INIT_DONE;
2664b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2665b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2666b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2667b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * net_device operations
2668b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2669b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int cxgb_open(struct net_device *dev)
2670b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2671b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int err;
2672b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
2673b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = pi->adapter;
2674b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
26756a3c869a6021f4abcd69aa5fbb15c63f69eb36feDimitris Michailidis	netif_carrier_off(dev);
26766a3c869a6021f4abcd69aa5fbb15c63f69eb36feDimitris Michailidis
2677aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	if (!(adapter->flags & FULL_INIT_DONE)) {
2678aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis		err = cxgb_up(adapter);
2679aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis		if (err < 0)
2680aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis			return err;
2681aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis	}
2682b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2683f68707b805b7794bb7b208e327fbe0473c470d0bDimitris Michailidis	err = link_start(dev);
2684f68707b805b7794bb7b208e327fbe0473c470d0bDimitris Michailidis	if (!err)
2685f68707b805b7794bb7b208e327fbe0473c470d0bDimitris Michailidis		netif_tx_start_all_queues(dev);
2686f68707b805b7794bb7b208e327fbe0473c470d0bDimitris Michailidis	return err;
2687b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2688b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2689b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int cxgb_close(struct net_device *dev)
2690b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2691b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
2692b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = pi->adapter;
2693b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2694b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	netif_tx_stop_all_queues(dev);
2695b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	netif_carrier_off(dev);
2696060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	return t4_enable_vi(adapter, adapter->fn, pi->viid, false, false);
2697b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2698b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2699f5152c908a5b0be48ec9a58d0de8bdadd9385854Dimitris Michailidisstatic struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
2700f5152c908a5b0be48ec9a58d0de8bdadd9385854Dimitris Michailidis						struct rtnl_link_stats64 *ns)
2701b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2702b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_stats stats;
2703b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *p = netdev_priv(dev);
2704b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = p->adapter;
2705b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2706b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock(&adapter->stats_lock);
2707b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_get_port_stats(adapter, p->tx_chan, &stats);
2708b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_unlock(&adapter->stats_lock);
2709b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2710b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_bytes   = stats.tx_octets;
2711b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_packets = stats.tx_frames;
2712b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_bytes   = stats.rx_octets;
2713b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_packets = stats.rx_frames;
2714b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->multicast  = stats.rx_mcast_frames;
2715b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2716b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* detailed rx_errors */
2717b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_length_errors = stats.rx_jabber + stats.rx_too_long +
2718b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       stats.rx_runt;
2719b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_over_errors   = 0;
2720b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_crc_errors    = stats.rx_fcs_err;
2721b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_frame_errors  = stats.rx_symbol_err;
2722b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_fifo_errors   = stats.rx_ovflow0 + stats.rx_ovflow1 +
2723b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       stats.rx_ovflow2 + stats.rx_ovflow3 +
2724b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       stats.rx_trunc0 + stats.rx_trunc1 +
2725b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			       stats.rx_trunc2 + stats.rx_trunc3;
2726b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_missed_errors = 0;
2727b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2728b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* detailed tx_errors */
2729b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_aborted_errors   = 0;
2730b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_carrier_errors   = 0;
2731b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_fifo_errors      = 0;
2732b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_heartbeat_errors = 0;
2733b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_window_errors    = 0;
2734b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2735b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->tx_errors = stats.tx_error_frames;
2736b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ns->rx_errors = stats.rx_symbol_err + stats.rx_fcs_err +
2737b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		ns->rx_length_errors + stats.rx_len_err + ns->rx_fifo_errors;
2738b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ns;
2739b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2740b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2741b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
2742b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2743060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	unsigned int mbox;
2744b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret = 0, prtad, devad;
2745b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
2746b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&req->ifr_data;
2747b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2748b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	switch (cmd) {
2749b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	case SIOCGMIIPHY:
2750b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (pi->mdio_addr < 0)
2751b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return -EOPNOTSUPP;
2752b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		data->phy_id = pi->mdio_addr;
2753b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		break;
2754b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	case SIOCGMIIREG:
2755b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	case SIOCSMIIREG:
2756b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (mdio_phy_id_is_c45(data->phy_id)) {
2757b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			prtad = mdio_phy_id_prtad(data->phy_id);
2758b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			devad = mdio_phy_id_devad(data->phy_id);
2759b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		} else if (data->phy_id < 32) {
2760b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			prtad = data->phy_id;
2761b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			devad = 0;
2762b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			data->reg_num &= 0x1f;
2763b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		} else
2764b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			return -EINVAL;
2765b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2766060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		mbox = pi->adapter->fn;
2767b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (cmd == SIOCGMIIREG)
2768060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			ret = t4_mdio_rd(pi->adapter, mbox, prtad, devad,
2769b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					 data->reg_num, &data->val_out);
2770b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		else
2771060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			ret = t4_mdio_wr(pi->adapter, mbox, prtad, devad,
2772b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					 data->reg_num, data->val_in);
2773b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		break;
2774b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	default:
2775b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EOPNOTSUPP;
2776b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2777b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
2778b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2779b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2780b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void cxgb_set_rxmode(struct net_device *dev)
2781b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2782b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* unfortunately we can't return errors to the stack */
2783b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	set_rxmode(dev, -1, false);
2784b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2785b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2786b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int cxgb_change_mtu(struct net_device *dev, int new_mtu)
2787b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2788b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
2789b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
2790b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2791b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (new_mtu < 81 || new_mtu > MAX_MTU)         /* accommodate SACK */
2792b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return -EINVAL;
2793060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_set_rxmode(pi->adapter, pi->adapter->fn, pi->viid, new_mtu, -1,
2794060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			    -1, -1, -1, true);
2795b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!ret)
2796b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev->mtu = new_mtu;
2797b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
2798b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2799b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2800b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int cxgb_set_mac_addr(struct net_device *dev, void *p)
2801b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2802b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
2803b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sockaddr *addr = p;
2804b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
2805b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2806b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!is_valid_ether_addr(addr->sa_data))
2807504f9b5a6bb5336ad434438d0cdd61a16db80129Danny Kukawka		return -EADDRNOTAVAIL;
2808b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2809060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_change_mac(pi->adapter, pi->adapter->fn, pi->viid,
2810060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			    pi->xact_addr_filt, addr->sa_data, true, true);
2811b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0)
2812b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return ret;
2813b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2814b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
2815b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pi->xact_addr_filt = ret;
2816b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
2817b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2818b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2819b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#ifdef CONFIG_NET_POLL_CONTROLLER
2820b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void cxgb_netpoll(struct net_device *dev)
2821b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2822b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi = netdev_priv(dev);
2823b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adap = pi->adapter;
2824b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2825b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adap->flags & USING_MSIX) {
2826b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		int i;
2827b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_eth_rxq *rx = &adap->sge.ethrxq[pi->first_qset];
2828b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2829b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		for (i = pi->nqsets; i; i--, rx++)
2830b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			t4_sge_intr_msix(0, &rx->rspq);
2831b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else
2832b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		t4_intr_handler(adap)(0, adap);
2833b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2834b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#endif
2835b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2836b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic const struct net_device_ops cxgb4_netdev_ops = {
2837b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_open             = cxgb_open,
2838b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_stop             = cxgb_close,
2839b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_start_xmit       = t4_eth_xmit,
28409be793bfa38436f9142de219b6eef4d8dfa96606Dimitris Michailidis	.ndo_get_stats64      = cxgb_get_stats,
2841b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_set_rx_mode      = cxgb_set_rxmode,
2842b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_set_mac_address  = cxgb_set_mac_addr,
28432ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław	.ndo_set_features     = cxgb_set_features,
2844b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_validate_addr    = eth_validate_addr,
2845b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_do_ioctl         = cxgb_ioctl,
2846b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_change_mtu       = cxgb_change_mtu,
2847b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#ifdef CONFIG_NET_POLL_CONTROLLER
2848b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.ndo_poll_controller  = cxgb_netpoll,
2849b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#endif
2850b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
2851b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2852b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisvoid t4_fatal_err(struct adapter *adap)
2853b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2854b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_set_reg_field(adap, SGE_CONTROL, GLOBALENABLE, 0);
2855b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_intr_disable(adap);
2856b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
2857b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2858b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2859b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void setup_memwin(struct adapter *adap)
2860b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2861b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 bar0;
2862b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2863b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	bar0 = pci_resource_start(adap->pdev, 0);  /* truncation intentional */
2864b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 0),
2865b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     (bar0 + MEMWIN0_BASE) | BIR(0) |
2866b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     WINDOW(ilog2(MEMWIN0_APERTURE) - 10));
2867b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 1),
2868b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     (bar0 + MEMWIN1_BASE) | BIR(0) |
2869b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     WINDOW(ilog2(MEMWIN1_APERTURE) - 10));
2870b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_write_reg(adap, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 2),
2871b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     (bar0 + MEMWIN2_BASE) | BIR(0) |
2872b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     WINDOW(ilog2(MEMWIN2_APERTURE) - 10));
28731ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis	if (adap->vres.ocq.size) {
28741ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		unsigned int start, sz_kb;
28751ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis
28761ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		start = pci_resource_start(adap->pdev, 2) +
28771ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis			OCQ_WIN_OFFSET(adap->pdev, &adap->vres);
28781ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		sz_kb = roundup_pow_of_two(adap->vres.ocq.size) >> 10;
28791ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		t4_write_reg(adap,
28801ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis			     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, 3),
28811ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis			     start | BIR(1) | WINDOW(ilog2(sz_kb)));
28821ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		t4_write_reg(adap,
28831ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis			     PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, 3),
28841ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis			     adap->vres.ocq.start);
28851ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		t4_read_reg(adap,
28861ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis			    PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, 3));
28871ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis	}
2888b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
2889b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
289002b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidisstatic int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
289102b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis{
289202b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	u32 v;
289302b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	int ret;
289402b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
289502b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	/* get device capabilities */
289602b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	memset(c, 0, sizeof(*c));
289702b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
289802b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis			       FW_CMD_REQUEST | FW_CMD_READ);
289902b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	c->retval_len16 = htonl(FW_LEN16(*c));
2900060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c);
290102b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	if (ret < 0)
290202b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		return ret;
290302b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
290402b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	/* select capabilities we'll be using */
290502b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	if (c->niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {
290602b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		if (!vf_acls)
290702b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis			c->niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM);
290802b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		else
290902b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis			c->niccaps = htons(FW_CAPS_CONFIG_NIC_VM);
291002b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	} else if (vf_acls) {
291102b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		dev_err(adap->pdev_dev, "virtualization ACLs not supported");
291202b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		return ret;
291302b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	}
291402b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
291502b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis			       FW_CMD_REQUEST | FW_CMD_WRITE);
2916060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), NULL);
291702b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	if (ret < 0)
291802b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		return ret;
291902b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
2920060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_config_glbl_rss(adap, adap->fn,
292102b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis				 FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
292202b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis				 FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
292302b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis				 FW_RSS_GLB_CONFIG_CMD_TNLALLLKP);
292402b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	if (ret < 0)
292502b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		return ret;
292602b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
2927060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_cfg_pfvf(adap, adap->fn, adap->fn, 0, MAX_EGRQ, 64, MAX_INGQ,
2928060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis			  0, 0, 4, 0xf, 0xf, 16, FW_CMD_CAP_PF, FW_CMD_CAP_PF);
292902b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	if (ret < 0)
293002b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis		return ret;
293102b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
293202b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	t4_sge_init(adap);
293302b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
293402b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	/* tweak some settings */
293502b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	t4_write_reg(adap, TP_SHIFT_CNT, 0x64f8849);
293602b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	t4_write_reg(adap, ULP_RX_TDDP_PSZ, HPZ0(PAGE_SHIFT - 12));
293702b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	t4_write_reg(adap, TP_PIO_ADDR, TP_INGRESS_CONFIG);
293802b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	v = t4_read_reg(adap, TP_PIO_DATA);
293902b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis	t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR);
2940060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis
2941060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	/* get basic stuff going */
2942060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	return t4_early_init(adap, adap->fn);
294302b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis}
294402b5fb8e14923ff9111de1a00004ccd593adaedbDimitris Michailidis
2945b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2946b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Max # of ATIDs.  The absolute HW max is 16K but we keep it lower.
2947b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2948b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define MAX_ATIDS 8192U
2949b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2950b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
2951b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Phase 0 of initialization: contact FW, obtain config, perform basic init.
2952b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
2953b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int adap_init0(struct adapter *adap)
2954b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
2955b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
2956b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 v, port_vec;
2957b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	enum dev_state state;
2958b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	u32 params[7], val[7];
2959b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct fw_caps_config_cmd c;
2960b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2961b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ret = t4_check_fw_version(adap);
2962b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret == -EINVAL || ret > 0) {
2963b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (upgrade_fw(adap) >= 0)             /* recache FW version */
2964b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ret = t4_check_fw_version(adap);
2965b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2966b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0)
2967b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return ret;
2968b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2969b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* contact FW, request master */
2970060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, &state);
2971b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0) {
2972b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_err(adap->pdev_dev, "could not connect to FW, error %d\n",
2973b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			ret);
2974b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return ret;
2975b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
2976b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2977b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* reset device */
2978060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_fw_reset(adap, adap->fn, PIORSTMODE | PIORST);
2979b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0)
2980b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto bye;
2981b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2982b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (v = 0; v < SGE_NTIMERS - 1; v++)
2983b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->sge.timer_val[v] = min(intr_holdoff[v], MAX_SGE_TIMERVAL);
2984b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->sge.timer_val[SGE_NTIMERS - 1] = MAX_SGE_TIMERVAL;
2985b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->sge.counter_val[0] = 1;
2986b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (v = 1; v < SGE_NCOUNTERS; v++)
2987b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->sge.counter_val[v] = min(intr_cnt[v - 1],
2988b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					       THRESHOLD_3_MASK);
2989b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define FW_PARAM_DEV(param) \
2990b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
2991b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
2992b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
2993a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	params[0] = FW_PARAM_DEV(CCLK);
2994060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 1, params, val);
2995a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	if (ret < 0)
2996a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		goto bye;
2997a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	adap->params.vpd.cclk = val[0];
2998a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis
2999a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	ret = adap_init1(adap, &c);
3000a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis	if (ret < 0)
3001a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		goto bye;
3002a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis
3003b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define FW_PARAM_PFVF(param) \
3004b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	(FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
3005060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	 FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \
3006060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	 FW_PARAMS_PARAM_Y(adap->fn))
3007b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3008b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	params[0] = FW_PARAM_DEV(PORTVEC);
3009b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	params[1] = FW_PARAM_PFVF(L2T_START);
3010b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	params[2] = FW_PARAM_PFVF(L2T_END);
3011b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	params[3] = FW_PARAM_PFVF(FILTER_START);
3012b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	params[4] = FW_PARAM_PFVF(FILTER_END);
3013e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	params[5] = FW_PARAM_PFVF(IQFLINT_START);
3014e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	params[6] = FW_PARAM_PFVF(EQ_START);
3015e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	ret = t4_query_params(adap, adap->fn, adap->fn, 0, 7, params, val);
3016b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0)
3017b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto bye;
3018b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	port_vec = val[0];
3019b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->tids.ftid_base = val[3];
3020b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->tids.nftids = val[4] - val[3] + 1;
3021e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	adap->sge.ingr_start = val[5];
3022e46dab4d4be87769b09404135bc34f89e2e155d8Dimitris Michailidis	adap->sge.egr_start = val[6];
3023b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3024b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (c.ofldcaps) {
3025b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/* query offload-related parameters */
3026b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[0] = FW_PARAM_DEV(NTID);
3027b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[1] = FW_PARAM_PFVF(SERVER_START);
3028b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[2] = FW_PARAM_PFVF(SERVER_END);
3029b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[3] = FW_PARAM_PFVF(TDDP_START);
3030b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[4] = FW_PARAM_PFVF(TDDP_END);
3031b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[5] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ);
3032060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
3033060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				      val);
3034b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (ret < 0)
3035b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto bye;
3036b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->tids.ntids = val[0];
3037b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS);
3038b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->tids.stid_base = val[1];
3039b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->tids.nstids = val[2] - val[1] + 1;
3040b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.ddp.start = val[3];
3041b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.ddp.size = val[4] - val[3] + 1;
3042b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->params.ofldq_wr_cred = val[5];
3043b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->params.offload = 1;
3044b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3045b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (c.rdmacaps) {
3046b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[0] = FW_PARAM_PFVF(STAG_START);
3047b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[1] = FW_PARAM_PFVF(STAG_END);
3048b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[2] = FW_PARAM_PFVF(RQ_START);
3049b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[3] = FW_PARAM_PFVF(RQ_END);
3050b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[4] = FW_PARAM_PFVF(PBL_START);
3051b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[5] = FW_PARAM_PFVF(PBL_END);
3052060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
3053060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				      val);
3054b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (ret < 0)
3055b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto bye;
3056b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.stag.start = val[0];
3057b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.stag.size = val[1] - val[0] + 1;
3058b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.rq.start = val[2];
3059b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.rq.size = val[3] - val[2] + 1;
3060b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.pbl.start = val[4];
3061b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.pbl.size = val[5] - val[4] + 1;
3062a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis
3063a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		params[0] = FW_PARAM_PFVF(SQRQ_START);
3064a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		params[1] = FW_PARAM_PFVF(SQRQ_END);
3065a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		params[2] = FW_PARAM_PFVF(CQ_START);
3066a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		params[3] = FW_PARAM_PFVF(CQ_END);
30671ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		params[4] = FW_PARAM_PFVF(OCQ_START);
30681ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		params[5] = FW_PARAM_PFVF(OCQ_END);
3069060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 6, params,
3070060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				      val);
3071a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		if (ret < 0)
3072a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis			goto bye;
3073a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		adap->vres.qp.start = val[0];
3074a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		adap->vres.qp.size = val[1] - val[0] + 1;
3075a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		adap->vres.cq.start = val[2];
3076a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		adap->vres.cq.size = val[3] - val[2] + 1;
30771ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		adap->vres.ocq.start = val[4];
30781ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis		adap->vres.ocq.size = val[5] - val[4] + 1;
3079b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3080b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (c.iscsicaps) {
3081b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[0] = FW_PARAM_PFVF(ISCSI_START);
3082b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		params[1] = FW_PARAM_PFVF(ISCSI_END);
3083060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_query_params(adap, adap->fn, adap->fn, 0, 2, params,
3084060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				      val);
3085b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (ret < 0)
3086b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto bye;
3087b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.iscsi.start = val[0];
3088b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adap->vres.iscsi.size = val[1] - val[0] + 1;
3089b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3090b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#undef FW_PARAM_PFVF
3091b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#undef FW_PARAM_DEV
3092b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3093b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->params.nports = hweight32(port_vec);
3094b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->params.portvec = port_vec;
3095b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->flags |= FW_OK;
3096b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3097b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* These are finalized by FW initialization, load their values now */
3098b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	v = t4_read_reg(adap, TP_TIMER_RESOLUTION);
3099b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adap->params.tp.tre = TIMERRESOLUTION_GET(v);
3100b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_read_mtu_tbl(adap, adap->params.mtus, NULL);
3101b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
3102b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		     adap->params.b_wnd);
31037ee9ff94857dd27144521118173786a03d490efbCasey Leedom
31047ee9ff94857dd27144521118173786a03d490efbCasey Leedom#ifdef CONFIG_PCI_IOV
31057ee9ff94857dd27144521118173786a03d490efbCasey Leedom	/*
31067ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * Provision resource limits for Virtual Functions.  We currently
31077ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * grant them all the same static resource limits except for the Port
31087ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * Access Rights Mask which we're assigning based on the PF.  All of
31097ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * the static provisioning stuff for both the PF and VF really needs
31107ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * to be managed in a persistent manner for each device which the
31117ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 * firmware controls.
31127ee9ff94857dd27144521118173786a03d490efbCasey Leedom	 */
31137ee9ff94857dd27144521118173786a03d490efbCasey Leedom	{
31147ee9ff94857dd27144521118173786a03d490efbCasey Leedom		int pf, vf;
31157ee9ff94857dd27144521118173786a03d490efbCasey Leedom
31167ee9ff94857dd27144521118173786a03d490efbCasey Leedom		for (pf = 0; pf < ARRAY_SIZE(num_vf); pf++) {
31177ee9ff94857dd27144521118173786a03d490efbCasey Leedom			if (num_vf[pf] <= 0)
31187ee9ff94857dd27144521118173786a03d490efbCasey Leedom				continue;
31197ee9ff94857dd27144521118173786a03d490efbCasey Leedom
31207ee9ff94857dd27144521118173786a03d490efbCasey Leedom			/* VF numbering starts at 1! */
31217ee9ff94857dd27144521118173786a03d490efbCasey Leedom			for (vf = 1; vf <= num_vf[pf]; vf++) {
3122060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				ret = t4_cfg_pfvf(adap, adap->fn, pf, vf,
31237ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  VFRES_NEQ, VFRES_NETHCTRL,
31247ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  VFRES_NIQFLINT, VFRES_NIQ,
31257ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  VFRES_TC, VFRES_NVI,
31267ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  FW_PFVF_CMD_CMASK_MASK,
31277ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  pfvfres_pmask(adap, pf, vf),
31287ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  VFRES_NEXACTF,
31297ee9ff94857dd27144521118173786a03d490efbCasey Leedom						  VFRES_R_CAPS, VFRES_WX_CAPS);
31307ee9ff94857dd27144521118173786a03d490efbCasey Leedom				if (ret < 0)
31317ee9ff94857dd27144521118173786a03d490efbCasey Leedom					dev_warn(adap->pdev_dev, "failed to "
31327ee9ff94857dd27144521118173786a03d490efbCasey Leedom						 "provision pf/vf=%d/%d; "
31337ee9ff94857dd27144521118173786a03d490efbCasey Leedom						 "err=%d\n", pf, vf, ret);
31347ee9ff94857dd27144521118173786a03d490efbCasey Leedom			}
31357ee9ff94857dd27144521118173786a03d490efbCasey Leedom		}
31367ee9ff94857dd27144521118173786a03d490efbCasey Leedom	}
31377ee9ff94857dd27144521118173786a03d490efbCasey Leedom#endif
31387ee9ff94857dd27144521118173786a03d490efbCasey Leedom
31391ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis	setup_memwin(adap);
3140b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
3141b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3142b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/*
3143b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * If a command timed out or failed with EIO FW does not operate within
3144b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * its spec or something catastrophic happened to HW/FW, stop issuing
3145b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * commands.
3146b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 */
3147b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisbye:	if (ret != -ETIMEDOUT && ret != -EIO)
3148060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		t4_fw_bye(adap, adap->fn);
3149b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
3150b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3151b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3152204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis/* EEH callbacks */
3153204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3154204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidisstatic pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
3155204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis					 pci_channel_state_t state)
3156204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis{
3157204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	int i;
3158204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	struct adapter *adap = pci_get_drvdata(pdev);
3159204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3160204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (!adap)
3161204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		goto out;
3162204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3163204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	rtnl_lock();
3164204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	adap->flags &= ~FW_OK;
3165204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	notify_ulds(adap, CXGB4_STATE_START_RECOVERY);
3166204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	for_each_port(adap, i) {
3167204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		struct net_device *dev = adap->port[i];
3168204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3169204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		netif_device_detach(dev);
3170204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		netif_carrier_off(dev);
3171204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	}
3172204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (adap->flags & FULL_INIT_DONE)
3173204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		cxgb_down(adap);
3174204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	rtnl_unlock();
3175204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	pci_disable_device(pdev);
3176204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidisout:	return state == pci_channel_io_perm_failure ?
3177204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET;
3178204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis}
3179204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3180204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidisstatic pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev)
3181204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis{
3182204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	int i, ret;
3183204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	struct fw_caps_config_cmd c;
3184204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	struct adapter *adap = pci_get_drvdata(pdev);
3185204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3186204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (!adap) {
3187204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		pci_restore_state(pdev);
3188204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		pci_save_state(pdev);
3189204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return PCI_ERS_RESULT_RECOVERED;
3190204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	}
3191204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3192204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (pci_enable_device(pdev)) {
3193204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		dev_err(&pdev->dev, "cannot reenable PCI device after reset\n");
3194204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return PCI_ERS_RESULT_DISCONNECT;
3195204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	}
3196204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3197204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	pci_set_master(pdev);
3198204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	pci_restore_state(pdev);
3199204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	pci_save_state(pdev);
3200204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	pci_cleanup_aer_uncorrect_error_status(pdev);
3201204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3202204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (t4_wait_dev_ready(adap) < 0)
3203204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return PCI_ERS_RESULT_DISCONNECT;
3204060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	if (t4_fw_hello(adap, adap->fn, adap->fn, MASTER_MUST, NULL))
3205204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return PCI_ERS_RESULT_DISCONNECT;
3206204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	adap->flags |= FW_OK;
3207204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (adap_init1(adap, &c))
3208204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return PCI_ERS_RESULT_DISCONNECT;
3209204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3210204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	for_each_port(adap, i) {
3211204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		struct port_info *p = adap2pinfo(adap, i);
3212204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3213060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		ret = t4_alloc_vi(adap, adap->fn, p->tx_chan, adap->fn, 0, 1,
3214060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis				  NULL, NULL);
3215204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		if (ret < 0)
3216204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis			return PCI_ERS_RESULT_DISCONNECT;
3217204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		p->viid = ret;
3218204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		p->xact_addr_filt = -1;
3219204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	}
3220204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3221204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
3222204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		     adap->params.b_wnd);
32231ae970e0c047fbb1050865c6cf3ac68c7ca67dbaDimitris Michailidis	setup_memwin(adap);
3224204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (cxgb_up(adap))
3225204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return PCI_ERS_RESULT_DISCONNECT;
3226204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	return PCI_ERS_RESULT_RECOVERED;
3227204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis}
3228204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3229204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidisstatic void eeh_resume(struct pci_dev *pdev)
3230204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis{
3231204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	int i;
3232204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	struct adapter *adap = pci_get_drvdata(pdev);
3233204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3234204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	if (!adap)
3235204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		return;
3236204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3237204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	rtnl_lock();
3238204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	for_each_port(adap, i) {
3239204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		struct net_device *dev = adap->port[i];
3240204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3241204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		if (netif_running(dev)) {
3242204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis			link_start(dev);
3243204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis			cxgb_set_rxmode(dev);
3244204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		}
3245204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		netif_device_attach(dev);
3246204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	}
3247204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	rtnl_unlock();
3248204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis}
3249204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3250204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidisstatic struct pci_error_handlers cxgb4_eeh = {
3251204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	.error_detected = eeh_err_detected,
3252204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	.slot_reset     = eeh_slot_reset,
3253204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	.resume         = eeh_resume,
3254204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis};
3255204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis
3256b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic inline bool is_10g_port(const struct link_config *lc)
3257b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3258b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0;
3259b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3260b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3261b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
3262b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			     unsigned int size, unsigned int iqe_size)
3263b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3264b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	q->intr_params = QINTR_TIMER_IDX(timer_idx) |
3265b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 (pkt_cnt_idx < SGE_NCOUNTERS ? QINTR_CNT_EN : 0);
3266b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	q->pktcnt_idx = pkt_cnt_idx < SGE_NCOUNTERS ? pkt_cnt_idx : 0;
3267b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	q->iqe_len = iqe_size;
3268b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	q->size = size;
3269b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3270b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3271b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
3272b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Perform default configuration of DMA queues depending on the number and type
3273b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * of ports we found and the number of available CPUs.  Most settings can be
3274b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * modified by the admin prior to actual use.
3275b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
3276b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void __devinit cfg_queues(struct adapter *adap)
3277b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3278b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge *s = &adap->sge;
3279b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i, q10g = 0, n10g = 0, qidx = 0;
3280b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3281b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, i)
3282b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		n10g += is_10g_port(&adap2pinfo(adap, i)->link_cfg);
3283b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3284b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/*
3285b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * We default to 1 queue per non-10G port and up to # of cores queues
3286b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * per 10G port.
3287b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 */
3288b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (n10g)
3289b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		q10g = (MAX_ETH_QSETS - (adap->params.nports - n10g)) / n10g;
3290b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (q10g > num_online_cpus())
3291b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		q10g = num_online_cpus();
3292b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3293b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, i) {
3294b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct port_info *pi = adap2pinfo(adap, i);
3295b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3296b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi->first_qset = qidx;
3297b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1;
3298b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		qidx += pi->nqsets;
3299b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3300b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3301b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	s->ethqsets = qidx;
3302b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	s->max_ethqsets = qidx;   /* MSI-X may lower it later */
3303b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3304b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (is_offload(adap)) {
3305b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/*
3306b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * For offload we use 1 queue/channel if all ports are up to 1G,
3307b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * otherwise we divide all available queues amongst the channels
3308b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * capped by the number of available cores.
3309b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 */
3310b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (n10g) {
3311b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			i = min_t(int, ARRAY_SIZE(s->ofldrxq),
3312b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				  num_online_cpus());
3313b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s->ofldqsets = roundup(i, adap->params.nports);
3314b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		} else
3315b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s->ofldqsets = adap->params.nports;
3316b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/* For RDMA one Rx queue per channel suffices */
3317b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->rdmaqs = adap->params.nports;
3318b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3319b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3320b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->ethrxq); i++) {
3321b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_eth_rxq *r = &s->ethrxq[i];
3322b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3323b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		init_rspq(&r->rspq, 0, 0, 1024, 64);
3324b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		r->fl.size = 72;
3325b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3326b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3327b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->ethtxq); i++)
3328b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ethtxq[i].q.size = 1024;
3329b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3330b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++)
3331b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ctrlq[i].q.size = 512;
3332b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3333b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++)
3334b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		s->ofldtxq[i].q.size = 1024;
3335b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3336b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->ofldrxq); i++) {
3337b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_ofld_rxq *r = &s->ofldrxq[i];
3338b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3339b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		init_rspq(&r->rspq, 0, 0, 1024, 64);
3340b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		r->rspq.uld = CXGB4_ULD_ISCSI;
3341b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		r->fl.size = 72;
3342b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3343b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3344b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(s->rdmarxq); i++) {
3345b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct sge_ofld_rxq *r = &s->rdmarxq[i];
3346b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3347b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		init_rspq(&r->rspq, 0, 0, 511, 64);
3348b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		r->rspq.uld = CXGB4_ULD_RDMA;
3349b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		r->fl.size = 72;
3350b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3351b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3352b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	init_rspq(&s->fw_evtq, 6, 0, 512, 64);
3353b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	init_rspq(&s->intrq, 6, 0, 2 * MAX_INGQ, 64);
3354b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3355b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3356b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/*
3357b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * Reduce the number of Ethernet queues across all ports to at most n.
3358b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis * n provides at least one queue per port.
3359b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis */
3360b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void __devinit reduce_ethqs(struct adapter *adap, int n)
3361b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3362b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i;
3363b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi;
3364b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3365b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while (n < adap->sge.ethqsets)
3366b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		for_each_port(adap, i) {
3367b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			pi = adap2pinfo(adap, i);
3368b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (pi->nqsets > 1) {
3369b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				pi->nqsets--;
3370b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				adap->sge.ethqsets--;
3371b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				if (adap->sge.ethqsets <= n)
3372b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					break;
3373b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			}
3374b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
3375b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3376b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	n = 0;
3377b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adap, i) {
3378b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi = adap2pinfo(adap, i);
3379b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi->first_qset = n;
3380b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		n += pi->nqsets;
3381b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3382b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3383b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3384b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis/* 2 MSI-X vectors needed for the FW queue and non-data interrupts */
3385b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#define EXTRA_VECS 2
3386b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3387b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int __devinit enable_msix(struct adapter *adap)
3388b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3389b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ofld_need = 0;
3390b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int i, err, want, need;
3391b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct sge *s = &adap->sge;
3392b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	unsigned int nchan = adap->params.nports;
3393b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct msix_entry entries[MAX_INGQ + 1];
3394b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3395b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for (i = 0; i < ARRAY_SIZE(entries); ++i)
3396b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		entries[i].entry = i;
3397b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3398b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	want = s->max_ethqsets + EXTRA_VECS;
3399b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (is_offload(adap)) {
3400b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		want += s->rdmaqs + s->ofldqsets;
3401b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/* need nchan for each possible ULD */
3402b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		ofld_need = 2 * nchan;
3403b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3404b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	need = adap->params.nports + EXTRA_VECS + ofld_need;
3405b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3406b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	while ((err = pci_enable_msix(adap->pdev, entries, want)) >= need)
3407b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		want = err;
3408b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3409b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!err) {
3410b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/*
3411b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * Distribute available vectors to the various queue groups.
3412b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * Every group gets its minimum requirement and NIC gets top
3413b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 * priority for leftovers.
3414b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		 */
3415b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		i = want - EXTRA_VECS - ofld_need;
3416b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (i < s->max_ethqsets) {
3417b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s->max_ethqsets = i;
3418b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			if (i < s->ethqsets)
3419b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				reduce_ethqs(adap, i);
3420b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
3421b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (is_offload(adap)) {
3422b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			i = want - EXTRA_VECS - s->max_ethqsets;
3423b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			i -= ofld_need - nchan;
3424b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			s->ofldqsets = (i / nchan) * nchan;  /* round down */
3425b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
3426b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		for (i = 0; i < want; ++i)
3427b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			adap->msix_info[i].vec = entries[i].vector;
3428b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else if (err > 0)
3429b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_info(adap->pdev_dev,
3430b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 "only %d MSI-X vectors left, not using MSI-X\n", err);
3431b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
3432b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3433b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3434b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#undef EXTRA_VECS
3435b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3436671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidisstatic int __devinit init_rss(struct adapter *adap)
3437671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis{
3438671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	unsigned int i, j;
3439671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
3440671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	for_each_port(adap, i) {
3441671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		struct port_info *pi = adap2pinfo(adap, i);
3442671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
3443671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		pi->rss = kcalloc(pi->rss_size, sizeof(u16), GFP_KERNEL);
3444671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		if (!pi->rss)
3445671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis			return -ENOMEM;
3446671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		for (j = 0; j < pi->rss_size; j++)
3447278bc4296bd64ffd1d3913b487dc8a520e423a7aBen Hutchings			pi->rss[j] = ethtool_rxfh_indir_default(j, pi->nqsets);
3448671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	}
3449671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	return 0;
3450671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis}
3451671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
3452118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidisstatic void __devinit print_port_info(const struct net_device *dev)
3453b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3454b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	static const char *base[] = {
3455a0881cab6c0a1c8ad48a4ab0b971c8e786dadf1cDimitris Michailidis		"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
34567d5e77aafa39f3210b6273a44fe07508e837c3cbDimitris Michailidis		"KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4"
3457b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	};
3458b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3459b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	char buf[80];
3460118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	char *bufp = buf;
3461f1a051b93090ad920e88748023ab0dea3a6e2ad7Dimitris Michailidis	const char *spd = "";
3462118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	const struct port_info *pi = netdev_priv(dev);
3463118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	const struct adapter *adap = pi->adapter;
3464f1a051b93090ad920e88748023ab0dea3a6e2ad7Dimitris Michailidis
3465f1a051b93090ad920e88748023ab0dea3a6e2ad7Dimitris Michailidis	if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_2_5GB)
3466f1a051b93090ad920e88748023ab0dea3a6e2ad7Dimitris Michailidis		spd = " 2.5 GT/s";
3467f1a051b93090ad920e88748023ab0dea3a6e2ad7Dimitris Michailidis	else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
3468f1a051b93090ad920e88748023ab0dea3a6e2ad7Dimitris Michailidis		spd = " 5 GT/s";
3469b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3470118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M)
3471118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		bufp += sprintf(bufp, "100/");
3472118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G)
3473118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		bufp += sprintf(bufp, "1000/");
3474118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
3475118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		bufp += sprintf(bufp, "10G/");
3476118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	if (bufp != buf)
3477118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		--bufp;
3478118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	sprintf(bufp, "BASE-%s", base[pi->port_type]);
3479118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis
3480118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
3481118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		    adap->params.vpd.id, adap->params.rev, buf,
3482118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		    is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
3483118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		    (adap->flags & USING_MSIX) ? " MSI-X" :
3484118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		    (adap->flags & USING_MSI) ? " MSI" : "");
3485118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis	netdev_info(dev, "S/N: %s, E/C: %s\n",
3486118969ed21b6895045b0a5a8a32feac1c9341096Dimitris Michailidis		    adap->params.vpd.sn, adap->params.vpd.ec);
3487b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3488b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3489ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidisstatic void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
3490ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis{
3491ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis	u16 v;
3492ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis	int pos;
3493ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis
3494ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis	pos = pci_pcie_cap(dev);
3495ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis	if (pos > 0) {
3496ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis		pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &v);
3497ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis		v |= PCI_EXP_DEVCTL_RELAX_EN;
3498ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis		pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, v);
3499ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis	}
3500ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis}
3501ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis
3502065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis/*
3503065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis * Free the following resources:
3504065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis * - memory used for tables
3505065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis * - MSI/MSI-X
3506065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis * - net devices
3507065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis * - resources FW is holding for us
3508065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis */
3509065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidisstatic void free_some_resources(struct adapter *adapter)
3510065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis{
3511065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	unsigned int i;
3512065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis
3513065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	t4_free_mem(adapter->l2t);
3514065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	t4_free_mem(adapter->tids.tid_tab);
3515065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	disable_msi(adapter);
3516065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis
3517065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	for_each_port(adapter, i)
3518671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		if (adapter->port[i]) {
3519671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis			kfree(adap2pinfo(adapter, i)->rss);
3520065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis			free_netdev(adapter->port[i]);
3521671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		}
3522065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	if (adapter->flags & FW_OK)
3523060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		t4_fw_bye(adapter, adapter->fn);
3524065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis}
3525065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis
35262ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław#define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
352735d35682041686572d5158993dede90bc73dc1d9Dimitris Michailidis#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
3528b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		   NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
3529b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3530b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int __devinit init_one(struct pci_dev *pdev,
3531b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			      const struct pci_device_id *ent)
3532b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3533b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int func, i, err;
3534b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct port_info *pi;
3535c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław	bool highdma = false;
3536b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = NULL;
3537b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3538b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
3539b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3540b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = pci_request_regions(pdev, KBUILD_MODNAME);
3541b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err) {
3542b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/* Just info, some other driver may have claimed the device. */
3543b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_info(&pdev->dev, "cannot obtain PCI resources\n");
3544b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		return err;
3545b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3546b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3547060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	/* We control everything through one PF */
3548b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	func = PCI_FUNC(pdev->devfn);
3549060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	if (func != ent->driver_data) {
3550204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis		pci_save_state(pdev);        /* to restore SR-IOV later */
3551b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto sriov;
3552204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	}
3553b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3554b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = pci_enable_device(pdev);
3555b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err) {
3556b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_err(&pdev->dev, "cannot enable PCI device\n");
3557b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out_release_regions;
3558b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3559b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3560b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
3561c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław		highdma = true;
3562b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
3563b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err) {
3564b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			dev_err(&pdev->dev, "unable to obtain 64-bit DMA for "
3565b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				"coherent allocations\n");
3566b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto out_disable_device;
3567b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
3568b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	} else {
3569b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
3570b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err) {
3571b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			dev_err(&pdev->dev, "no usable DMA configuration\n");
3572b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto out_disable_device;
3573b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
3574b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3575b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3576b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_enable_pcie_error_reporting(pdev);
3577ef306b50b983be4873aed453c1feeaab22f3a098Dimitris Michailidis	enable_pcie_relaxed_ordering(pdev);
3578b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_set_master(pdev);
3579b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_save_state(pdev);
3580b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3581b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
3582b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!adapter) {
3583b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = -ENOMEM;
3584b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out_disable_device;
3585b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3586b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3587b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter->regs = pci_ioremap_bar(pdev, 0);
3588b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!adapter->regs) {
3589b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_err(&pdev->dev, "cannot map device registers\n");
3590b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = -ENOMEM;
3591b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out_free_adapter;
3592b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3593b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3594b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter->pdev = pdev;
3595b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter->pdev_dev = &pdev->dev;
3596060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis	adapter->fn = func;
3597b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter->msg_enable = dflt_msg_enable;
3598b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
3599b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3600b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_init(&adapter->stats_lock);
3601b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	spin_lock_init(&adapter->tid_release_lock);
3602b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3603b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
3604b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3605b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = t4_prep_adapter(adapter);
3606b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err)
3607b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out_unmap_bar;
3608b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	err = adap_init0(adapter);
3609b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (err)
3610b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out_unmap_bar;
3611b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3612b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adapter, i) {
3613b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		struct net_device *netdev;
3614b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3615b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev = alloc_etherdev_mq(sizeof(struct port_info),
3616b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis					   MAX_ETH_QSETS);
3617b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (!netdev) {
3618b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			err = -ENOMEM;
3619b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto out_free_dev;
3620b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		}
3621b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3622b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		SET_NETDEV_DEV(netdev, &pdev->dev);
3623b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3624b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adapter->port[i] = netdev;
3625b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi = netdev_priv(netdev);
3626b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi->adapter = adapter;
3627b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi->xact_addr_filt = -1;
3628b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pi->port_id = i;
3629b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev->irq = pdev->irq;
3630b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
36312ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław		netdev->hw_features = NETIF_F_SG | TSO_FLAGS |
36322ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
36332ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław			NETIF_F_RXCSUM | NETIF_F_RXHASH |
36342ed28baa7076083b56c1e70ccd927b7870117c59Michał Mirosław			NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
3635c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław		if (highdma)
3636c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław			netdev->hw_features |= NETIF_F_HIGHDMA;
3637c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław		netdev->features |= netdev->hw_features;
3638b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev->vlan_features = netdev->features & VLAN_FEAT;
3639b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
364001789349ee52e4a3faf376f1485303d9723c4f1fJiri Pirko		netdev->priv_flags |= IFF_UNICAST_FLT;
364101789349ee52e4a3faf376f1485303d9723c4f1fJiri Pirko
3642b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		netdev->netdev_ops = &cxgb4_netdev_ops;
3643b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
3644b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3645b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3646b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_set_drvdata(pdev, adapter);
3647b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3648b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adapter->flags & FW_OK) {
3649060e0c752b5047ee691120b75df4c16743981e50Dimitris Michailidis		err = t4_port_init(adapter, func, func, 0);
3650b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
3651b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			goto out_free_dev;
3652b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3653b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3654b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/*
3655b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * Configure queues and allocate tables now, they can be needed as
3656b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * soon as the first register_netdev completes.
3657b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 */
3658b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cfg_queues(adapter);
3659b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3660b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	adapter->l2t = t4_init_l2t();
3661b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!adapter->l2t) {
3662b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		/* We tolerate a lack of L2T, giving up some functionality */
3663b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_warn(&pdev->dev, "could not allocate L2T, continuing\n");
3664b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adapter->params.offload = 0;
3665b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3666b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3667b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (is_offload(adapter) && tid_init(&adapter->tids) < 0) {
3668b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_warn(&pdev->dev, "could not allocate TID table, "
3669b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			 "continuing\n");
3670b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adapter->params.offload = 0;
3671b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3672b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3673f7cabcdd51480282b58c09e5fe1c4835aaf98a66Dimitris Michailidis	/* See what interrupts we'll be using */
3674f7cabcdd51480282b58c09e5fe1c4835aaf98a66Dimitris Michailidis	if (msi > 1 && enable_msix(adapter) == 0)
3675f7cabcdd51480282b58c09e5fe1c4835aaf98a66Dimitris Michailidis		adapter->flags |= USING_MSIX;
3676f7cabcdd51480282b58c09e5fe1c4835aaf98a66Dimitris Michailidis	else if (msi > 0 && pci_enable_msi(pdev) == 0)
3677f7cabcdd51480282b58c09e5fe1c4835aaf98a66Dimitris Michailidis		adapter->flags |= USING_MSI;
3678f7cabcdd51480282b58c09e5fe1c4835aaf98a66Dimitris Michailidis
3679671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	err = init_rss(adapter);
3680671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis	if (err)
3681671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis		goto out_free_dev;
3682671b0060d82984a566f2e75ffd166a9b61c6da7dDimitris Michailidis
3683b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/*
3684b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * The card is now ready to go.  If any errors occur during device
3685b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * registration we do not fail the whole card but rather proceed only
3686b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * with the ports we manage to register successfully.  However we must
3687b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 * register at least one net device.
3688b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	 */
3689b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	for_each_port(adapter, i) {
3690a57cabe09f843a3f71277c485494496b3b9ee84aDimitris Michailidis		pi = adap2pinfo(adapter, i);
3691a57cabe09f843a3f71277c485494496b3b9ee84aDimitris Michailidis		netif_set_real_num_tx_queues(adapter->port[i], pi->nqsets);
3692a57cabe09f843a3f71277c485494496b3b9ee84aDimitris Michailidis		netif_set_real_num_rx_queues(adapter->port[i], pi->nqsets);
3693a57cabe09f843a3f71277c485494496b3b9ee84aDimitris Michailidis
3694b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		err = register_netdev(adapter->port[i]);
3695b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (err)
3696b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis			break;
3697b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis		adapter->chan_map[pi->tx_chan] = i;
3698b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis		print_port_info(adapter->port[i]);
3699b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3700b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis	if (i == 0) {
3701b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		dev_err(&pdev->dev, "could not register any net devices\n");
3702b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		goto out_free_dev;
3703b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3704b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis	if (err) {
3705b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis		dev_warn(&pdev->dev, "only %d net devices registered\n", i);
3706b1a3c2b698ec333edc86bf8b5a636162ca309870Dimitris Michailidis		err = 0;
37076403eab143205a45a5493166ff8bf7e3646f4a77Joe Perches	}
3708b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3709b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (cxgb4_debugfs_root) {
3710b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		adapter->debugfs_root = debugfs_create_dir(pci_name(pdev),
3711b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis							   cxgb4_debugfs_root);
3712b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		setup_debugfs(adapter);
3713b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	}
3714b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
37156482aa7c120447858da1869197b48eff66435a31Divy Le Ray	/* PCIe EEH recovery on powerpc platforms needs fundamental reset */
37166482aa7c120447858da1869197b48eff66435a31Divy Le Ray	pdev->needs_freset = 1;
37176482aa7c120447858da1869197b48eff66435a31Divy Le Ray
3718b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (is_offload(adapter))
3719b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		attach_ulds(adapter);
3720b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3721b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidissriov:
3722b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#ifdef CONFIG_PCI_IOV
3723b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0)
3724b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (pci_enable_sriov(pdev, num_vf[func]) == 0)
3725b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			dev_info(&pdev->dev,
3726b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				 "instantiated %u virtual functions\n",
3727b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				 num_vf[func]);
3728b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis#endif
3729b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return 0;
3730b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3731b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis out_free_dev:
3732065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis	free_some_resources(adapter);
3733b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis out_unmap_bar:
3734b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	iounmap(adapter->regs);
3735b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis out_free_adapter:
3736b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	kfree(adapter);
3737b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis out_disable_device:
3738b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_disable_pcie_error_reporting(pdev);
3739b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_disable_device(pdev);
3740b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis out_release_regions:
3741b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_release_regions(pdev);
3742b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_set_drvdata(pdev, NULL);
3743b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return err;
3744b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3745b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3746b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void __devexit remove_one(struct pci_dev *pdev)
3747b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3748b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	struct adapter *adapter = pci_get_drvdata(pdev);
3749b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3750b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_disable_sriov(pdev);
3751b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3752b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (adapter) {
3753b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		int i;
3754b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3755b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (is_offload(adapter))
3756b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			detach_ulds(adapter);
3757b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3758b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		for_each_port(adapter, i)
37598f3a76769ee50a839282f70d07d5f3429524b68aDimitris Michailidis			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
3760b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis				unregister_netdev(adapter->port[i]);
3761b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3762b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		if (adapter->debugfs_root)
3763b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis			debugfs_remove_recursive(adapter->debugfs_root);
3764b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3765aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis		if (adapter->flags & FULL_INIT_DONE)
3766aaefae9b32b2cba7350a4d524357168119372e51Dimitris Michailidis			cxgb_down(adapter);
3767b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3768065463915c3a2a2ce142f64ed3ed591d72ad88b1Dimitris Michailidis		free_some_resources(adapter);
3769b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		iounmap(adapter->regs);
3770b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		kfree(adapter);
3771b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_disable_pcie_error_reporting(pdev);
3772b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_disable_device(pdev);
3773b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_release_regions(pdev);
3774b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_set_drvdata(pdev, NULL);
3775a069ec917457e44e214fc34e50acd185110fa81bDimitris Michailidis	} else
3776b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pci_release_regions(pdev);
3777b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3778b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3779b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic struct pci_driver cxgb4_driver = {
3780b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.name     = KBUILD_MODNAME,
3781b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.id_table = cxgb4_pci_tbl,
3782b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.probe    = init_one,
3783b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	.remove   = __devexit_p(remove_one),
3784204dc3c0b1bea10a7d811970fd41ceabaef31267Dimitris Michailidis	.err_handler = &cxgb4_eeh,
3785b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis};
3786b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3787b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic int __init cxgb4_init_module(void)
3788b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3789b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	int ret;
3790b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3791b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	/* Debugfs support is optional, just warn if this fails */
3792b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
3793b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (!cxgb4_debugfs_root)
3794b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		pr_warning("could not create debugfs entry, continuing\n");
3795b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3796b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	ret = pci_register_driver(&cxgb4_driver);
3797b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	if (ret < 0)
3798b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis		debugfs_remove(cxgb4_debugfs_root);
3799b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	return ret;
3800b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3801b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3802b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidisstatic void __exit cxgb4_cleanup_module(void)
3803b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis{
3804b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	pci_unregister_driver(&cxgb4_driver);
3805b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis	debugfs_remove(cxgb4_debugfs_root);  /* NULL ok */
3806b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis}
3807b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidis
3808b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_init(cxgb4_init_module);
3809b8ff05a9c3237f694a1c3bf8ceec3bf6c3c14b15Dimitris Michailidismodule_exit(cxgb4_cleanup_module);
3810