1f7917c00SJeff Kirsher /*****************************************************************************
2f7917c00SJeff Kirsher  *                                                                           *
3f7917c00SJeff Kirsher  * File: cxgb2.c                                                             *
4f7917c00SJeff Kirsher  * $Revision: 1.25 $                                                         *
5f7917c00SJeff Kirsher  * $Date: 2005/06/22 00:43:25 $                                              *
6f7917c00SJeff Kirsher  * Description:                                                              *
7f7917c00SJeff Kirsher  *  Chelsio 10Gb Ethernet Driver.                                            *
8f7917c00SJeff Kirsher  *                                                                           *
9f7917c00SJeff Kirsher  * This program is free software; you can redistribute it and/or modify      *
10f7917c00SJeff Kirsher  * it under the terms of the GNU General Public License, version 2, as       *
11f7917c00SJeff Kirsher  * published by the Free Software Foundation.                                *
12f7917c00SJeff Kirsher  *                                                                           *
13f7917c00SJeff Kirsher  * You should have received a copy of the GNU General Public License along   *
140ab75ae8SJeff Kirsher  * with this program; if not, see <http://www.gnu.org/licenses/>.            *
15f7917c00SJeff Kirsher  *                                                                           *
16f7917c00SJeff Kirsher  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
17f7917c00SJeff Kirsher  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
18f7917c00SJeff Kirsher  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
19f7917c00SJeff Kirsher  *                                                                           *
20f7917c00SJeff Kirsher  * http://www.chelsio.com                                                    *
21f7917c00SJeff Kirsher  *                                                                           *
22f7917c00SJeff Kirsher  * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
23f7917c00SJeff Kirsher  * All rights reserved.                                                      *
24f7917c00SJeff Kirsher  *                                                                           *
25f7917c00SJeff Kirsher  * Maintainers: maintainers@chelsio.com                                      *
26f7917c00SJeff Kirsher  *                                                                           *
27f7917c00SJeff Kirsher  * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
28f7917c00SJeff Kirsher  *          Tina Yang               <tainay@chelsio.com>                     *
29f7917c00SJeff Kirsher  *          Felix Marti             <felix@chelsio.com>                      *
30f7917c00SJeff Kirsher  *          Scott Bardone           <sbardone@chelsio.com>                   *
31f7917c00SJeff Kirsher  *          Kurt Ottaway            <kottaway@chelsio.com>                   *
32f7917c00SJeff Kirsher  *          Frank DiMambro          <frank@chelsio.com>                      *
33f7917c00SJeff Kirsher  *                                                                           *
34f7917c00SJeff Kirsher  * History:                                                                  *
35f7917c00SJeff Kirsher  *                                                                           *
36f7917c00SJeff Kirsher  ****************************************************************************/
37f7917c00SJeff Kirsher 
38f7917c00SJeff Kirsher #include "common.h"
39f7917c00SJeff Kirsher #include <linux/module.h>
40f7917c00SJeff Kirsher #include <linux/pci.h>
41f7917c00SJeff Kirsher #include <linux/netdevice.h>
42f7917c00SJeff Kirsher #include <linux/etherdevice.h>
43f7917c00SJeff Kirsher #include <linux/if_vlan.h>
44f7917c00SJeff Kirsher #include <linux/mii.h>
45f7917c00SJeff Kirsher #include <linux/sockios.h>
46f7917c00SJeff Kirsher #include <linux/dma-mapping.h>
477c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
48f7917c00SJeff Kirsher 
49f7917c00SJeff Kirsher #include "cpl5_cmd.h"
50f7917c00SJeff Kirsher #include "regs.h"
51f7917c00SJeff Kirsher #include "gmac.h"
52f7917c00SJeff Kirsher #include "cphy.h"
53f7917c00SJeff Kirsher #include "sge.h"
54f7917c00SJeff Kirsher #include "tp.h"
55f7917c00SJeff Kirsher #include "espi.h"
56f7917c00SJeff Kirsher #include "elmer0.h"
57f7917c00SJeff Kirsher 
58f7917c00SJeff Kirsher #include <linux/workqueue.h>
59f7917c00SJeff Kirsher 
schedule_mac_stats_update(struct adapter * ap,int secs)60f7917c00SJeff Kirsher static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
61f7917c00SJeff Kirsher {
62f7917c00SJeff Kirsher 	schedule_delayed_work(&ap->stats_update_task, secs * HZ);
63f7917c00SJeff Kirsher }
64f7917c00SJeff Kirsher 
cancel_mac_stats_update(struct adapter * ap)65f7917c00SJeff Kirsher static inline void cancel_mac_stats_update(struct adapter *ap)
66f7917c00SJeff Kirsher {
67f7917c00SJeff Kirsher 	cancel_delayed_work(&ap->stats_update_task);
68f7917c00SJeff Kirsher }
69f7917c00SJeff Kirsher 
70f7917c00SJeff Kirsher #define MAX_CMDQ_ENTRIES	16384
71f7917c00SJeff Kirsher #define MAX_CMDQ1_ENTRIES	1024
72f7917c00SJeff Kirsher #define MAX_RX_BUFFERS		16384
73f7917c00SJeff Kirsher #define MAX_RX_JUMBO_BUFFERS	16384
74f7917c00SJeff Kirsher #define MAX_TX_BUFFERS_HIGH	16384U
75f7917c00SJeff Kirsher #define MAX_TX_BUFFERS_LOW	1536U
76f7917c00SJeff Kirsher #define MAX_TX_BUFFERS		1460U
77f7917c00SJeff Kirsher #define MIN_FL_ENTRIES		32
78f7917c00SJeff Kirsher 
79f7917c00SJeff Kirsher #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
80f7917c00SJeff Kirsher 			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
81f7917c00SJeff Kirsher 			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
82f7917c00SJeff Kirsher 
83f7917c00SJeff Kirsher /*
84f7917c00SJeff Kirsher  * The EEPROM is actually bigger but only the first few bytes are used so we
85f7917c00SJeff Kirsher  * only report those.
86f7917c00SJeff Kirsher  */
87f7917c00SJeff Kirsher #define EEPROM_SIZE 32
88f7917c00SJeff Kirsher 
89f7917c00SJeff Kirsher MODULE_DESCRIPTION(DRV_DESCRIPTION);
90f7917c00SJeff Kirsher MODULE_AUTHOR("Chelsio Communications");
91f7917c00SJeff Kirsher MODULE_LICENSE("GPL");
92f7917c00SJeff Kirsher 
93f7917c00SJeff Kirsher static int dflt_msg_enable = DFLT_MSG_ENABLE;
94f7917c00SJeff Kirsher 
95f7917c00SJeff Kirsher module_param(dflt_msg_enable, int, 0);
96f7917c00SJeff Kirsher MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap");
97f7917c00SJeff Kirsher 
98f7917c00SJeff Kirsher #define HCLOCK 0x0
99f7917c00SJeff Kirsher #define LCLOCK 0x1
100f7917c00SJeff Kirsher 
101f7917c00SJeff Kirsher /* T1 cards powersave mode */
102f7917c00SJeff Kirsher static int t1_clock(struct adapter *adapter, int mode);
103f7917c00SJeff Kirsher static int t1powersave = 1;	/* HW default is powersave mode. */
104f7917c00SJeff Kirsher 
105f7917c00SJeff Kirsher module_param(t1powersave, int, 0);
106f7917c00SJeff Kirsher MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode");
107f7917c00SJeff Kirsher 
108f7917c00SJeff Kirsher static int disable_msi = 0;
109f7917c00SJeff Kirsher module_param(disable_msi, int, 0);
110f7917c00SJeff Kirsher MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
111f7917c00SJeff Kirsher 
112f7917c00SJeff Kirsher /*
113f7917c00SJeff Kirsher  * Setup MAC to receive the types of packets we want.
114f7917c00SJeff Kirsher  */
t1_set_rxmode(struct net_device * dev)115f7917c00SJeff Kirsher static void t1_set_rxmode(struct net_device *dev)
116f7917c00SJeff Kirsher {
117f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
118f7917c00SJeff Kirsher 	struct cmac *mac = adapter->port[dev->if_port].mac;
119f7917c00SJeff Kirsher 	struct t1_rx_mode rm;
120f7917c00SJeff Kirsher 
121f7917c00SJeff Kirsher 	rm.dev = dev;
122f7917c00SJeff Kirsher 	mac->ops->set_rx_mode(mac, &rm);
123f7917c00SJeff Kirsher }
124f7917c00SJeff Kirsher 
link_report(struct port_info * p)125f7917c00SJeff Kirsher static void link_report(struct port_info *p)
126f7917c00SJeff Kirsher {
127f7917c00SJeff Kirsher 	if (!netif_carrier_ok(p->dev))
128428ac43fSJoe Perches 		netdev_info(p->dev, "link down\n");
129f7917c00SJeff Kirsher 	else {
130f7917c00SJeff Kirsher 		const char *s = "10Mbps";
131f7917c00SJeff Kirsher 
132f7917c00SJeff Kirsher 		switch (p->link_config.speed) {
133f7917c00SJeff Kirsher 			case SPEED_10000: s = "10Gbps"; break;
134f7917c00SJeff Kirsher 			case SPEED_1000:  s = "1000Mbps"; break;
135f7917c00SJeff Kirsher 			case SPEED_100:   s = "100Mbps"; break;
136f7917c00SJeff Kirsher 		}
137f7917c00SJeff Kirsher 
138428ac43fSJoe Perches 		netdev_info(p->dev, "link up, %s, %s-duplex\n",
139428ac43fSJoe Perches 			    s, p->link_config.duplex == DUPLEX_FULL
140428ac43fSJoe Perches 			    ? "full" : "half");
141f7917c00SJeff Kirsher 	}
142f7917c00SJeff Kirsher }
143f7917c00SJeff Kirsher 
t1_link_negotiated(struct adapter * adapter,int port_id,int link_stat,int speed,int duplex,int pause)144f7917c00SJeff Kirsher void t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat,
145f7917c00SJeff Kirsher 			int speed, int duplex, int pause)
146f7917c00SJeff Kirsher {
147f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[port_id];
148f7917c00SJeff Kirsher 
149f7917c00SJeff Kirsher 	if (link_stat != netif_carrier_ok(p->dev)) {
150f7917c00SJeff Kirsher 		if (link_stat)
151f7917c00SJeff Kirsher 			netif_carrier_on(p->dev);
152f7917c00SJeff Kirsher 		else
153f7917c00SJeff Kirsher 			netif_carrier_off(p->dev);
154f7917c00SJeff Kirsher 		link_report(p);
155f7917c00SJeff Kirsher 
156f7917c00SJeff Kirsher 		/* multi-ports: inform toe */
157f7917c00SJeff Kirsher 		if ((speed > 0) && (adapter->params.nports > 1)) {
158f7917c00SJeff Kirsher 			unsigned int sched_speed = 10;
159f7917c00SJeff Kirsher 			switch (speed) {
160f7917c00SJeff Kirsher 			case SPEED_1000:
161f7917c00SJeff Kirsher 				sched_speed = 1000;
162f7917c00SJeff Kirsher 				break;
163f7917c00SJeff Kirsher 			case SPEED_100:
164f7917c00SJeff Kirsher 				sched_speed = 100;
165f7917c00SJeff Kirsher 				break;
166f7917c00SJeff Kirsher 			case SPEED_10:
167f7917c00SJeff Kirsher 				sched_speed = 10;
168f7917c00SJeff Kirsher 				break;
169f7917c00SJeff Kirsher 			}
170f7917c00SJeff Kirsher 			t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed);
171f7917c00SJeff Kirsher 		}
172f7917c00SJeff Kirsher 	}
173f7917c00SJeff Kirsher }
174f7917c00SJeff Kirsher 
link_start(struct port_info * p)175f7917c00SJeff Kirsher static void link_start(struct port_info *p)
176f7917c00SJeff Kirsher {
177f7917c00SJeff Kirsher 	struct cmac *mac = p->mac;
178f7917c00SJeff Kirsher 
179f7917c00SJeff Kirsher 	mac->ops->reset(mac);
180f7917c00SJeff Kirsher 	if (mac->ops->macaddress_set)
181f7917c00SJeff Kirsher 		mac->ops->macaddress_set(mac, p->dev->dev_addr);
182f7917c00SJeff Kirsher 	t1_set_rxmode(p->dev);
183f7917c00SJeff Kirsher 	t1_link_start(p->phy, mac, &p->link_config);
184f7917c00SJeff Kirsher 	mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
185f7917c00SJeff Kirsher }
186f7917c00SJeff Kirsher 
enable_hw_csum(struct adapter * adapter)187f7917c00SJeff Kirsher static void enable_hw_csum(struct adapter *adapter)
188f7917c00SJeff Kirsher {
189f7917c00SJeff Kirsher 	if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
190f7917c00SJeff Kirsher 		t1_tp_set_ip_checksum_offload(adapter->tp, 1);	/* for TSO only */
191f7917c00SJeff Kirsher 	t1_tp_set_tcp_checksum_offload(adapter->tp, 1);
192f7917c00SJeff Kirsher }
193f7917c00SJeff Kirsher 
194f7917c00SJeff Kirsher /*
195f7917c00SJeff Kirsher  * Things to do upon first use of a card.
196f7917c00SJeff Kirsher  * This must run with the rtnl lock held.
197f7917c00SJeff Kirsher  */
cxgb_up(struct adapter * adapter)198f7917c00SJeff Kirsher static int cxgb_up(struct adapter *adapter)
199f7917c00SJeff Kirsher {
200f7917c00SJeff Kirsher 	int err = 0;
201f7917c00SJeff Kirsher 
202f7917c00SJeff Kirsher 	if (!(adapter->flags & FULL_INIT_DONE)) {
203f7917c00SJeff Kirsher 		err = t1_init_hw_modules(adapter);
204f7917c00SJeff Kirsher 		if (err)
205f7917c00SJeff Kirsher 			goto out_err;
206f7917c00SJeff Kirsher 
207f7917c00SJeff Kirsher 		enable_hw_csum(adapter);
208f7917c00SJeff Kirsher 		adapter->flags |= FULL_INIT_DONE;
209f7917c00SJeff Kirsher 	}
210f7917c00SJeff Kirsher 
211f7917c00SJeff Kirsher 	t1_interrupts_clear(adapter);
212f7917c00SJeff Kirsher 
213f7917c00SJeff Kirsher 	adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
214fec7fa0aSSebastian Andrzej Siewior 	err = request_threaded_irq(adapter->pdev->irq, t1_interrupt,
215fec7fa0aSSebastian Andrzej Siewior 				   t1_interrupt_thread,
216f7917c00SJeff Kirsher 				   adapter->params.has_msi ? 0 : IRQF_SHARED,
217f7917c00SJeff Kirsher 				   adapter->name, adapter);
218f7917c00SJeff Kirsher 	if (err) {
219f7917c00SJeff Kirsher 		if (adapter->params.has_msi)
220f7917c00SJeff Kirsher 			pci_disable_msi(adapter->pdev);
221f7917c00SJeff Kirsher 
222f7917c00SJeff Kirsher 		goto out_err;
223f7917c00SJeff Kirsher 	}
224f7917c00SJeff Kirsher 
225f7917c00SJeff Kirsher 	t1_sge_start(adapter->sge);
226f7917c00SJeff Kirsher 	t1_interrupts_enable(adapter);
227f7917c00SJeff Kirsher out_err:
228f7917c00SJeff Kirsher 	return err;
229f7917c00SJeff Kirsher }
230f7917c00SJeff Kirsher 
231f7917c00SJeff Kirsher /*
232f7917c00SJeff Kirsher  * Release resources when all the ports have been stopped.
233f7917c00SJeff Kirsher  */
cxgb_down(struct adapter * adapter)234f7917c00SJeff Kirsher static void cxgb_down(struct adapter *adapter)
235f7917c00SJeff Kirsher {
236f7917c00SJeff Kirsher 	t1_sge_stop(adapter->sge);
237f7917c00SJeff Kirsher 	t1_interrupts_disable(adapter);
238f7917c00SJeff Kirsher 	free_irq(adapter->pdev->irq, adapter);
239f7917c00SJeff Kirsher 	if (adapter->params.has_msi)
240f7917c00SJeff Kirsher 		pci_disable_msi(adapter->pdev);
241f7917c00SJeff Kirsher }
242f7917c00SJeff Kirsher 
cxgb_open(struct net_device * dev)243f7917c00SJeff Kirsher static int cxgb_open(struct net_device *dev)
244f7917c00SJeff Kirsher {
245f7917c00SJeff Kirsher 	int err;
246f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
247f7917c00SJeff Kirsher 	int other_ports = adapter->open_device_map & PORT_MASK;
248f7917c00SJeff Kirsher 
249f7917c00SJeff Kirsher 	napi_enable(&adapter->napi);
250f7917c00SJeff Kirsher 	if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
251f7917c00SJeff Kirsher 		napi_disable(&adapter->napi);
252f7917c00SJeff Kirsher 		return err;
253f7917c00SJeff Kirsher 	}
254f7917c00SJeff Kirsher 
255f7917c00SJeff Kirsher 	__set_bit(dev->if_port, &adapter->open_device_map);
256f7917c00SJeff Kirsher 	link_start(&adapter->port[dev->if_port]);
257f7917c00SJeff Kirsher 	netif_start_queue(dev);
258f7917c00SJeff Kirsher 	if (!other_ports && adapter->params.stats_update_period)
259f7917c00SJeff Kirsher 		schedule_mac_stats_update(adapter,
260f7917c00SJeff Kirsher 					  adapter->params.stats_update_period);
261f7917c00SJeff Kirsher 
262f7917c00SJeff Kirsher 	t1_vlan_mode(adapter, dev->features);
263f7917c00SJeff Kirsher 	return 0;
264f7917c00SJeff Kirsher }
265f7917c00SJeff Kirsher 
cxgb_close(struct net_device * dev)266f7917c00SJeff Kirsher static int cxgb_close(struct net_device *dev)
267f7917c00SJeff Kirsher {
268f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
269f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[dev->if_port];
270f7917c00SJeff Kirsher 	struct cmac *mac = p->mac;
271f7917c00SJeff Kirsher 
272f7917c00SJeff Kirsher 	netif_stop_queue(dev);
273f7917c00SJeff Kirsher 	napi_disable(&adapter->napi);
274f7917c00SJeff Kirsher 	mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
275f7917c00SJeff Kirsher 	netif_carrier_off(dev);
276f7917c00SJeff Kirsher 
277f7917c00SJeff Kirsher 	clear_bit(dev->if_port, &adapter->open_device_map);
278f7917c00SJeff Kirsher 	if (adapter->params.stats_update_period &&
279f7917c00SJeff Kirsher 	    !(adapter->open_device_map & PORT_MASK)) {
280f7917c00SJeff Kirsher 		/* Stop statistics accumulation. */
2814e857c58SPeter Zijlstra 		smp_mb__after_atomic();
282f7917c00SJeff Kirsher 		spin_lock(&adapter->work_lock);   /* sync with update task */
283f7917c00SJeff Kirsher 		spin_unlock(&adapter->work_lock);
284f7917c00SJeff Kirsher 		cancel_mac_stats_update(adapter);
285f7917c00SJeff Kirsher 	}
286f7917c00SJeff Kirsher 
287f7917c00SJeff Kirsher 	if (!adapter->open_device_map)
288f7917c00SJeff Kirsher 		cxgb_down(adapter);
289f7917c00SJeff Kirsher 	return 0;
290f7917c00SJeff Kirsher }
291f7917c00SJeff Kirsher 
t1_get_stats(struct net_device * dev)292f7917c00SJeff Kirsher static struct net_device_stats *t1_get_stats(struct net_device *dev)
293f7917c00SJeff Kirsher {
294f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
295f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[dev->if_port];
296a3bb4560STobias Klauser 	struct net_device_stats *ns = &dev->stats;
297f7917c00SJeff Kirsher 	const struct cmac_statistics *pstats;
298f7917c00SJeff Kirsher 
299f7917c00SJeff Kirsher 	/* Do a full update of the MAC stats */
300f7917c00SJeff Kirsher 	pstats = p->mac->ops->statistics_update(p->mac,
301f7917c00SJeff Kirsher 						MAC_STATS_UPDATE_FULL);
302f7917c00SJeff Kirsher 
303f7917c00SJeff Kirsher 	ns->tx_packets = pstats->TxUnicastFramesOK +
304f7917c00SJeff Kirsher 		pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
305f7917c00SJeff Kirsher 
306f7917c00SJeff Kirsher 	ns->rx_packets = pstats->RxUnicastFramesOK +
307f7917c00SJeff Kirsher 		pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
308f7917c00SJeff Kirsher 
309f7917c00SJeff Kirsher 	ns->tx_bytes = pstats->TxOctetsOK;
310f7917c00SJeff Kirsher 	ns->rx_bytes = pstats->RxOctetsOK;
311f7917c00SJeff Kirsher 
312f7917c00SJeff Kirsher 	ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
313f7917c00SJeff Kirsher 		pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
314f7917c00SJeff Kirsher 	ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
315f7917c00SJeff Kirsher 		pstats->RxFCSErrors + pstats->RxAlignErrors +
316f7917c00SJeff Kirsher 		pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
317f7917c00SJeff Kirsher 		pstats->RxSymbolErrors + pstats->RxRuntErrors;
318f7917c00SJeff Kirsher 
319f7917c00SJeff Kirsher 	ns->multicast  = pstats->RxMulticastFramesOK;
320f7917c00SJeff Kirsher 	ns->collisions = pstats->TxTotalCollisions;
321f7917c00SJeff Kirsher 
322f7917c00SJeff Kirsher 	/* detailed rx_errors */
323f7917c00SJeff Kirsher 	ns->rx_length_errors = pstats->RxFrameTooLongErrors +
324f7917c00SJeff Kirsher 		pstats->RxJabberErrors;
325f7917c00SJeff Kirsher 	ns->rx_over_errors   = 0;
326f7917c00SJeff Kirsher 	ns->rx_crc_errors    = pstats->RxFCSErrors;
327f7917c00SJeff Kirsher 	ns->rx_frame_errors  = pstats->RxAlignErrors;
328f7917c00SJeff Kirsher 	ns->rx_fifo_errors   = 0;
329f7917c00SJeff Kirsher 	ns->rx_missed_errors = 0;
330f7917c00SJeff Kirsher 
331f7917c00SJeff Kirsher 	/* detailed tx_errors */
332f7917c00SJeff Kirsher 	ns->tx_aborted_errors   = pstats->TxFramesAbortedDueToXSCollisions;
333f7917c00SJeff Kirsher 	ns->tx_carrier_errors   = 0;
334f7917c00SJeff Kirsher 	ns->tx_fifo_errors      = pstats->TxUnderrun;
335f7917c00SJeff Kirsher 	ns->tx_heartbeat_errors = 0;
336f7917c00SJeff Kirsher 	ns->tx_window_errors    = pstats->TxLateCollisions;
337f7917c00SJeff Kirsher 	return ns;
338f7917c00SJeff Kirsher }
339f7917c00SJeff Kirsher 
get_msglevel(struct net_device * dev)340f7917c00SJeff Kirsher static u32 get_msglevel(struct net_device *dev)
341f7917c00SJeff Kirsher {
342f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
343f7917c00SJeff Kirsher 
344f7917c00SJeff Kirsher 	return adapter->msg_enable;
345f7917c00SJeff Kirsher }
346f7917c00SJeff Kirsher 
set_msglevel(struct net_device * dev,u32 val)347f7917c00SJeff Kirsher static void set_msglevel(struct net_device *dev, u32 val)
348f7917c00SJeff Kirsher {
349f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
350f7917c00SJeff Kirsher 
351f7917c00SJeff Kirsher 	adapter->msg_enable = val;
352f7917c00SJeff Kirsher }
353f7917c00SJeff Kirsher 
3549ca683c6SJoe Perches static const char stats_strings[][ETH_GSTRING_LEN] = {
355f7917c00SJeff Kirsher 	"TxOctetsOK",
356f7917c00SJeff Kirsher 	"TxOctetsBad",
357f7917c00SJeff Kirsher 	"TxUnicastFramesOK",
358f7917c00SJeff Kirsher 	"TxMulticastFramesOK",
359f7917c00SJeff Kirsher 	"TxBroadcastFramesOK",
360f7917c00SJeff Kirsher 	"TxPauseFrames",
361f7917c00SJeff Kirsher 	"TxFramesWithDeferredXmissions",
362f7917c00SJeff Kirsher 	"TxLateCollisions",
363f7917c00SJeff Kirsher 	"TxTotalCollisions",
364f7917c00SJeff Kirsher 	"TxFramesAbortedDueToXSCollisions",
365f7917c00SJeff Kirsher 	"TxUnderrun",
366f7917c00SJeff Kirsher 	"TxLengthErrors",
367f7917c00SJeff Kirsher 	"TxInternalMACXmitError",
368f7917c00SJeff Kirsher 	"TxFramesWithExcessiveDeferral",
369f7917c00SJeff Kirsher 	"TxFCSErrors",
370f7917c00SJeff Kirsher 	"TxJumboFramesOk",
371f7917c00SJeff Kirsher 	"TxJumboOctetsOk",
372f7917c00SJeff Kirsher 
373f7917c00SJeff Kirsher 	"RxOctetsOK",
374f7917c00SJeff Kirsher 	"RxOctetsBad",
375f7917c00SJeff Kirsher 	"RxUnicastFramesOK",
376f7917c00SJeff Kirsher 	"RxMulticastFramesOK",
377f7917c00SJeff Kirsher 	"RxBroadcastFramesOK",
378f7917c00SJeff Kirsher 	"RxPauseFrames",
379f7917c00SJeff Kirsher 	"RxFCSErrors",
380f7917c00SJeff Kirsher 	"RxAlignErrors",
381f7917c00SJeff Kirsher 	"RxSymbolErrors",
382f7917c00SJeff Kirsher 	"RxDataErrors",
383f7917c00SJeff Kirsher 	"RxSequenceErrors",
384f7917c00SJeff Kirsher 	"RxRuntErrors",
385f7917c00SJeff Kirsher 	"RxJabberErrors",
386f7917c00SJeff Kirsher 	"RxInternalMACRcvError",
387f7917c00SJeff Kirsher 	"RxInRangeLengthErrors",
388f7917c00SJeff Kirsher 	"RxOutOfRangeLengthField",
389f7917c00SJeff Kirsher 	"RxFrameTooLongErrors",
390f7917c00SJeff Kirsher 	"RxJumboFramesOk",
391f7917c00SJeff Kirsher 	"RxJumboOctetsOk",
392f7917c00SJeff Kirsher 
393f7917c00SJeff Kirsher 	/* Port stats */
394f7917c00SJeff Kirsher 	"RxCsumGood",
395f7917c00SJeff Kirsher 	"TxCsumOffload",
396f7917c00SJeff Kirsher 	"TxTso",
397f7917c00SJeff Kirsher 	"RxVlan",
398f7917c00SJeff Kirsher 	"TxVlan",
399f7917c00SJeff Kirsher 	"TxNeedHeadroom",
400f7917c00SJeff Kirsher 
401f7917c00SJeff Kirsher 	/* Interrupt stats */
402f7917c00SJeff Kirsher 	"rx drops",
403f7917c00SJeff Kirsher 	"pure_rsps",
404f7917c00SJeff Kirsher 	"unhandled irqs",
405f7917c00SJeff Kirsher 	"respQ_empty",
406f7917c00SJeff Kirsher 	"respQ_overflow",
407f7917c00SJeff Kirsher 	"freelistQ_empty",
408f7917c00SJeff Kirsher 	"pkt_too_big",
409f7917c00SJeff Kirsher 	"pkt_mismatch",
410f7917c00SJeff Kirsher 	"cmdQ_full0",
411f7917c00SJeff Kirsher 	"cmdQ_full1",
412f7917c00SJeff Kirsher 
413f7917c00SJeff Kirsher 	"espi_DIP2ParityErr",
414f7917c00SJeff Kirsher 	"espi_DIP4Err",
415f7917c00SJeff Kirsher 	"espi_RxDrops",
416f7917c00SJeff Kirsher 	"espi_TxDrops",
417f7917c00SJeff Kirsher 	"espi_RxOvfl",
418f7917c00SJeff Kirsher 	"espi_ParityErr"
419f7917c00SJeff Kirsher };
420f7917c00SJeff Kirsher 
421f7917c00SJeff Kirsher #define T2_REGMAP_SIZE (3 * 1024)
422f7917c00SJeff Kirsher 
get_regs_len(struct net_device * dev)423f7917c00SJeff Kirsher static int get_regs_len(struct net_device *dev)
424f7917c00SJeff Kirsher {
425f7917c00SJeff Kirsher 	return T2_REGMAP_SIZE;
426f7917c00SJeff Kirsher }
427f7917c00SJeff Kirsher 
get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)428f7917c00SJeff Kirsher static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
429f7917c00SJeff Kirsher {
430f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
431f7917c00SJeff Kirsher 
432f029c781SWolfram Sang 	strscpy(info->driver, DRV_NAME, sizeof(info->driver));
433f029c781SWolfram Sang 	strscpy(info->bus_info, pci_name(adapter->pdev),
43423020ab3SRick Jones 		sizeof(info->bus_info));
435f7917c00SJeff Kirsher }
436f7917c00SJeff Kirsher 
get_sset_count(struct net_device * dev,int sset)437f7917c00SJeff Kirsher static int get_sset_count(struct net_device *dev, int sset)
438f7917c00SJeff Kirsher {
439f7917c00SJeff Kirsher 	switch (sset) {
440f7917c00SJeff Kirsher 	case ETH_SS_STATS:
441f7917c00SJeff Kirsher 		return ARRAY_SIZE(stats_strings);
442f7917c00SJeff Kirsher 	default:
443f7917c00SJeff Kirsher 		return -EOPNOTSUPP;
444f7917c00SJeff Kirsher 	}
445f7917c00SJeff Kirsher }
446f7917c00SJeff Kirsher 
get_strings(struct net_device * dev,u32 stringset,u8 * data)447f7917c00SJeff Kirsher static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
448f7917c00SJeff Kirsher {
449f7917c00SJeff Kirsher 	if (stringset == ETH_SS_STATS)
450f7917c00SJeff Kirsher 		memcpy(data, stats_strings, sizeof(stats_strings));
451f7917c00SJeff Kirsher }
452f7917c00SJeff Kirsher 
get_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)453f7917c00SJeff Kirsher static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
454f7917c00SJeff Kirsher 		      u64 *data)
455f7917c00SJeff Kirsher {
456f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
457f7917c00SJeff Kirsher 	struct cmac *mac = adapter->port[dev->if_port].mac;
458f7917c00SJeff Kirsher 	const struct cmac_statistics *s;
459f7917c00SJeff Kirsher 	const struct sge_intr_counts *t;
460f7917c00SJeff Kirsher 	struct sge_port_stats ss;
461f7917c00SJeff Kirsher 
462f7917c00SJeff Kirsher 	s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
463f7917c00SJeff Kirsher 	t = t1_sge_get_intr_counts(adapter->sge);
464f7917c00SJeff Kirsher 	t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss);
465f7917c00SJeff Kirsher 
466f7917c00SJeff Kirsher 	*data++ = s->TxOctetsOK;
467f7917c00SJeff Kirsher 	*data++ = s->TxOctetsBad;
468f7917c00SJeff Kirsher 	*data++ = s->TxUnicastFramesOK;
469f7917c00SJeff Kirsher 	*data++ = s->TxMulticastFramesOK;
470f7917c00SJeff Kirsher 	*data++ = s->TxBroadcastFramesOK;
471f7917c00SJeff Kirsher 	*data++ = s->TxPauseFrames;
472f7917c00SJeff Kirsher 	*data++ = s->TxFramesWithDeferredXmissions;
473f7917c00SJeff Kirsher 	*data++ = s->TxLateCollisions;
474f7917c00SJeff Kirsher 	*data++ = s->TxTotalCollisions;
475f7917c00SJeff Kirsher 	*data++ = s->TxFramesAbortedDueToXSCollisions;
476f7917c00SJeff Kirsher 	*data++ = s->TxUnderrun;
477f7917c00SJeff Kirsher 	*data++ = s->TxLengthErrors;
478f7917c00SJeff Kirsher 	*data++ = s->TxInternalMACXmitError;
479f7917c00SJeff Kirsher 	*data++ = s->TxFramesWithExcessiveDeferral;
480f7917c00SJeff Kirsher 	*data++ = s->TxFCSErrors;
481f7917c00SJeff Kirsher 	*data++ = s->TxJumboFramesOK;
482f7917c00SJeff Kirsher 	*data++ = s->TxJumboOctetsOK;
483f7917c00SJeff Kirsher 
484f7917c00SJeff Kirsher 	*data++ = s->RxOctetsOK;
485f7917c00SJeff Kirsher 	*data++ = s->RxOctetsBad;
486f7917c00SJeff Kirsher 	*data++ = s->RxUnicastFramesOK;
487f7917c00SJeff Kirsher 	*data++ = s->RxMulticastFramesOK;
488f7917c00SJeff Kirsher 	*data++ = s->RxBroadcastFramesOK;
489f7917c00SJeff Kirsher 	*data++ = s->RxPauseFrames;
490f7917c00SJeff Kirsher 	*data++ = s->RxFCSErrors;
491f7917c00SJeff Kirsher 	*data++ = s->RxAlignErrors;
492f7917c00SJeff Kirsher 	*data++ = s->RxSymbolErrors;
493f7917c00SJeff Kirsher 	*data++ = s->RxDataErrors;
494f7917c00SJeff Kirsher 	*data++ = s->RxSequenceErrors;
495f7917c00SJeff Kirsher 	*data++ = s->RxRuntErrors;
496f7917c00SJeff Kirsher 	*data++ = s->RxJabberErrors;
497f7917c00SJeff Kirsher 	*data++ = s->RxInternalMACRcvError;
498f7917c00SJeff Kirsher 	*data++ = s->RxInRangeLengthErrors;
499f7917c00SJeff Kirsher 	*data++ = s->RxOutOfRangeLengthField;
500f7917c00SJeff Kirsher 	*data++ = s->RxFrameTooLongErrors;
501f7917c00SJeff Kirsher 	*data++ = s->RxJumboFramesOK;
502f7917c00SJeff Kirsher 	*data++ = s->RxJumboOctetsOK;
503f7917c00SJeff Kirsher 
504f7917c00SJeff Kirsher 	*data++ = ss.rx_cso_good;
505f7917c00SJeff Kirsher 	*data++ = ss.tx_cso;
506f7917c00SJeff Kirsher 	*data++ = ss.tx_tso;
507f7917c00SJeff Kirsher 	*data++ = ss.vlan_xtract;
508f7917c00SJeff Kirsher 	*data++ = ss.vlan_insert;
509f7917c00SJeff Kirsher 	*data++ = ss.tx_need_hdrroom;
510f7917c00SJeff Kirsher 
511f7917c00SJeff Kirsher 	*data++ = t->rx_drops;
512f7917c00SJeff Kirsher 	*data++ = t->pure_rsps;
513f7917c00SJeff Kirsher 	*data++ = t->unhandled_irqs;
514f7917c00SJeff Kirsher 	*data++ = t->respQ_empty;
515f7917c00SJeff Kirsher 	*data++ = t->respQ_overflow;
516f7917c00SJeff Kirsher 	*data++ = t->freelistQ_empty;
517f7917c00SJeff Kirsher 	*data++ = t->pkt_too_big;
518f7917c00SJeff Kirsher 	*data++ = t->pkt_mismatch;
519f7917c00SJeff Kirsher 	*data++ = t->cmdQ_full[0];
520f7917c00SJeff Kirsher 	*data++ = t->cmdQ_full[1];
521f7917c00SJeff Kirsher 
522f7917c00SJeff Kirsher 	if (adapter->espi) {
523f7917c00SJeff Kirsher 		const struct espi_intr_counts *e;
524f7917c00SJeff Kirsher 
525f7917c00SJeff Kirsher 		e = t1_espi_get_intr_counts(adapter->espi);
526f7917c00SJeff Kirsher 		*data++ = e->DIP2_parity_err;
527f7917c00SJeff Kirsher 		*data++ = e->DIP4_err;
528f7917c00SJeff Kirsher 		*data++ = e->rx_drops;
529f7917c00SJeff Kirsher 		*data++ = e->tx_drops;
530f7917c00SJeff Kirsher 		*data++ = e->rx_ovflw;
531f7917c00SJeff Kirsher 		*data++ = e->parity_err;
532f7917c00SJeff Kirsher 	}
533f7917c00SJeff Kirsher }
534f7917c00SJeff Kirsher 
reg_block_dump(struct adapter * ap,void * buf,unsigned int start,unsigned int end)535f7917c00SJeff Kirsher static inline void reg_block_dump(struct adapter *ap, void *buf,
536f7917c00SJeff Kirsher 				  unsigned int start, unsigned int end)
537f7917c00SJeff Kirsher {
538f7917c00SJeff Kirsher 	u32 *p = buf + start;
539f7917c00SJeff Kirsher 
540f7917c00SJeff Kirsher 	for ( ; start <= end; start += sizeof(u32))
541f7917c00SJeff Kirsher 		*p++ = readl(ap->regs + start);
542f7917c00SJeff Kirsher }
543f7917c00SJeff Kirsher 
get_regs(struct net_device * dev,struct ethtool_regs * regs,void * buf)544f7917c00SJeff Kirsher static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
545f7917c00SJeff Kirsher 		     void *buf)
546f7917c00SJeff Kirsher {
547f7917c00SJeff Kirsher 	struct adapter *ap = dev->ml_priv;
548f7917c00SJeff Kirsher 
549f7917c00SJeff Kirsher 	/*
550f7917c00SJeff Kirsher 	 * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
551f7917c00SJeff Kirsher 	 */
552f7917c00SJeff Kirsher 	regs->version = 2;
553f7917c00SJeff Kirsher 
554f7917c00SJeff Kirsher 	memset(buf, 0, T2_REGMAP_SIZE);
555f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
556f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE);
557f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR);
558f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT);
559f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE);
560f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE);
561f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT);
562f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL);
563f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE);
564f7917c00SJeff Kirsher 	reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD);
565f7917c00SJeff Kirsher }
566f7917c00SJeff Kirsher 
get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)56749cad939SPhilippe Reynes static int get_link_ksettings(struct net_device *dev,
56849cad939SPhilippe Reynes 			      struct ethtool_link_ksettings *cmd)
569f7917c00SJeff Kirsher {
570f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
571f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[dev->if_port];
57249cad939SPhilippe Reynes 	u32 supported, advertising;
573f7917c00SJeff Kirsher 
57449cad939SPhilippe Reynes 	supported = p->link_config.supported;
57549cad939SPhilippe Reynes 	advertising = p->link_config.advertising;
576f7917c00SJeff Kirsher 
577f7917c00SJeff Kirsher 	if (netif_carrier_ok(dev)) {
57849cad939SPhilippe Reynes 		cmd->base.speed = p->link_config.speed;
57949cad939SPhilippe Reynes 		cmd->base.duplex = p->link_config.duplex;
580f7917c00SJeff Kirsher 	} else {
58149cad939SPhilippe Reynes 		cmd->base.speed = SPEED_UNKNOWN;
58249cad939SPhilippe Reynes 		cmd->base.duplex = DUPLEX_UNKNOWN;
583f7917c00SJeff Kirsher 	}
584f7917c00SJeff Kirsher 
58549cad939SPhilippe Reynes 	cmd->base.port = (supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
58649cad939SPhilippe Reynes 	cmd->base.phy_address = p->phy->mdio.prtad;
58749cad939SPhilippe Reynes 	cmd->base.autoneg = p->link_config.autoneg;
58849cad939SPhilippe Reynes 
58949cad939SPhilippe Reynes 	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
59049cad939SPhilippe Reynes 						supported);
59149cad939SPhilippe Reynes 	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
59249cad939SPhilippe Reynes 						advertising);
59349cad939SPhilippe Reynes 
594f7917c00SJeff Kirsher 	return 0;
595f7917c00SJeff Kirsher }
596f7917c00SJeff Kirsher 
speed_duplex_to_caps(int speed,int duplex)597f7917c00SJeff Kirsher static int speed_duplex_to_caps(int speed, int duplex)
598f7917c00SJeff Kirsher {
599f7917c00SJeff Kirsher 	int cap = 0;
600f7917c00SJeff Kirsher 
601f7917c00SJeff Kirsher 	switch (speed) {
602f7917c00SJeff Kirsher 	case SPEED_10:
603f7917c00SJeff Kirsher 		if (duplex == DUPLEX_FULL)
604f7917c00SJeff Kirsher 			cap = SUPPORTED_10baseT_Full;
605f7917c00SJeff Kirsher 		else
606f7917c00SJeff Kirsher 			cap = SUPPORTED_10baseT_Half;
607f7917c00SJeff Kirsher 		break;
608f7917c00SJeff Kirsher 	case SPEED_100:
609f7917c00SJeff Kirsher 		if (duplex == DUPLEX_FULL)
610f7917c00SJeff Kirsher 			cap = SUPPORTED_100baseT_Full;
611f7917c00SJeff Kirsher 		else
612f7917c00SJeff Kirsher 			cap = SUPPORTED_100baseT_Half;
613f7917c00SJeff Kirsher 		break;
614f7917c00SJeff Kirsher 	case SPEED_1000:
615f7917c00SJeff Kirsher 		if (duplex == DUPLEX_FULL)
616f7917c00SJeff Kirsher 			cap = SUPPORTED_1000baseT_Full;
617f7917c00SJeff Kirsher 		else
618f7917c00SJeff Kirsher 			cap = SUPPORTED_1000baseT_Half;
619f7917c00SJeff Kirsher 		break;
620f7917c00SJeff Kirsher 	case SPEED_10000:
621f7917c00SJeff Kirsher 		if (duplex == DUPLEX_FULL)
622f7917c00SJeff Kirsher 			cap = SUPPORTED_10000baseT_Full;
623f7917c00SJeff Kirsher 	}
624f7917c00SJeff Kirsher 	return cap;
625f7917c00SJeff Kirsher }
626f7917c00SJeff Kirsher 
627f7917c00SJeff Kirsher #define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
628f7917c00SJeff Kirsher 		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
629f7917c00SJeff Kirsher 		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
630f7917c00SJeff Kirsher 		      ADVERTISED_10000baseT_Full)
631f7917c00SJeff Kirsher 
set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * cmd)63249cad939SPhilippe Reynes static int set_link_ksettings(struct net_device *dev,
63349cad939SPhilippe Reynes 			      const struct ethtool_link_ksettings *cmd)
634f7917c00SJeff Kirsher {
635f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
636f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[dev->if_port];
637f7917c00SJeff Kirsher 	struct link_config *lc = &p->link_config;
63849cad939SPhilippe Reynes 	u32 advertising;
63949cad939SPhilippe Reynes 
64049cad939SPhilippe Reynes 	ethtool_convert_link_mode_to_legacy_u32(&advertising,
64149cad939SPhilippe Reynes 						cmd->link_modes.advertising);
642f7917c00SJeff Kirsher 
643f7917c00SJeff Kirsher 	if (!(lc->supported & SUPPORTED_Autoneg))
644f7917c00SJeff Kirsher 		return -EOPNOTSUPP;             /* can't change speed/duplex */
645f7917c00SJeff Kirsher 
64649cad939SPhilippe Reynes 	if (cmd->base.autoneg == AUTONEG_DISABLE) {
64749cad939SPhilippe Reynes 		u32 speed = cmd->base.speed;
64849cad939SPhilippe Reynes 		int cap = speed_duplex_to_caps(speed, cmd->base.duplex);
649f7917c00SJeff Kirsher 
650f7917c00SJeff Kirsher 		if (!(lc->supported & cap) || (speed == SPEED_1000))
651f7917c00SJeff Kirsher 			return -EINVAL;
652f7917c00SJeff Kirsher 		lc->requested_speed = speed;
65349cad939SPhilippe Reynes 		lc->requested_duplex = cmd->base.duplex;
654f7917c00SJeff Kirsher 		lc->advertising = 0;
655f7917c00SJeff Kirsher 	} else {
65649cad939SPhilippe Reynes 		advertising &= ADVERTISED_MASK;
65749cad939SPhilippe Reynes 		if (advertising & (advertising - 1))
65849cad939SPhilippe Reynes 			advertising = lc->supported;
65949cad939SPhilippe Reynes 		advertising &= lc->supported;
66049cad939SPhilippe Reynes 		if (!advertising)
661f7917c00SJeff Kirsher 			return -EINVAL;
662f7917c00SJeff Kirsher 		lc->requested_speed = SPEED_INVALID;
663f7917c00SJeff Kirsher 		lc->requested_duplex = DUPLEX_INVALID;
66449cad939SPhilippe Reynes 		lc->advertising = advertising | ADVERTISED_Autoneg;
665f7917c00SJeff Kirsher 	}
66649cad939SPhilippe Reynes 	lc->autoneg = cmd->base.autoneg;
667f7917c00SJeff Kirsher 	if (netif_running(dev))
668f7917c00SJeff Kirsher 		t1_link_start(p->phy, p->mac, lc);
669f7917c00SJeff Kirsher 	return 0;
670f7917c00SJeff Kirsher }
671f7917c00SJeff Kirsher 
get_pauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)672f7917c00SJeff Kirsher static void get_pauseparam(struct net_device *dev,
673f7917c00SJeff Kirsher 			   struct ethtool_pauseparam *epause)
674f7917c00SJeff Kirsher {
675f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
676f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[dev->if_port];
677f7917c00SJeff Kirsher 
678f7917c00SJeff Kirsher 	epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
679f7917c00SJeff Kirsher 	epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
680f7917c00SJeff Kirsher 	epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
681f7917c00SJeff Kirsher }
682f7917c00SJeff Kirsher 
set_pauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)683f7917c00SJeff Kirsher static int set_pauseparam(struct net_device *dev,
684f7917c00SJeff Kirsher 			  struct ethtool_pauseparam *epause)
685f7917c00SJeff Kirsher {
686f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
687f7917c00SJeff Kirsher 	struct port_info *p = &adapter->port[dev->if_port];
688f7917c00SJeff Kirsher 	struct link_config *lc = &p->link_config;
689f7917c00SJeff Kirsher 
690f7917c00SJeff Kirsher 	if (epause->autoneg == AUTONEG_DISABLE)
691f7917c00SJeff Kirsher 		lc->requested_fc = 0;
692f7917c00SJeff Kirsher 	else if (lc->supported & SUPPORTED_Autoneg)
693f7917c00SJeff Kirsher 		lc->requested_fc = PAUSE_AUTONEG;
694f7917c00SJeff Kirsher 	else
695f7917c00SJeff Kirsher 		return -EINVAL;
696f7917c00SJeff Kirsher 
697f7917c00SJeff Kirsher 	if (epause->rx_pause)
698f7917c00SJeff Kirsher 		lc->requested_fc |= PAUSE_RX;
699f7917c00SJeff Kirsher 	if (epause->tx_pause)
700f7917c00SJeff Kirsher 		lc->requested_fc |= PAUSE_TX;
701f7917c00SJeff Kirsher 	if (lc->autoneg == AUTONEG_ENABLE) {
702f7917c00SJeff Kirsher 		if (netif_running(dev))
703f7917c00SJeff Kirsher 			t1_link_start(p->phy, p->mac, lc);
704f7917c00SJeff Kirsher 	} else {
705f7917c00SJeff Kirsher 		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
706f7917c00SJeff Kirsher 		if (netif_running(dev))
707f7917c00SJeff Kirsher 			p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
708f7917c00SJeff Kirsher 							 lc->fc);
709f7917c00SJeff Kirsher 	}
710f7917c00SJeff Kirsher 	return 0;
711f7917c00SJeff Kirsher }
712f7917c00SJeff Kirsher 
get_sge_param(struct net_device * dev,struct ethtool_ringparam * e,struct kernel_ethtool_ringparam * kernel_e,struct netlink_ext_ack * extack)71374624944SHao Chen static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e,
71474624944SHao Chen 			  struct kernel_ethtool_ringparam *kernel_e,
71574624944SHao Chen 			  struct netlink_ext_ack *extack)
716f7917c00SJeff Kirsher {
717f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
718f7917c00SJeff Kirsher 	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
719f7917c00SJeff Kirsher 
720f7917c00SJeff Kirsher 	e->rx_max_pending = MAX_RX_BUFFERS;
721f7917c00SJeff Kirsher 	e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
722f7917c00SJeff Kirsher 	e->tx_max_pending = MAX_CMDQ_ENTRIES;
723f7917c00SJeff Kirsher 
724f7917c00SJeff Kirsher 	e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
725f7917c00SJeff Kirsher 	e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
726f7917c00SJeff Kirsher 	e->tx_pending = adapter->params.sge.cmdQ_size[0];
727f7917c00SJeff Kirsher }
728f7917c00SJeff Kirsher 
set_sge_param(struct net_device * dev,struct ethtool_ringparam * e,struct kernel_ethtool_ringparam * kernel_e,struct netlink_ext_ack * extack)72974624944SHao Chen static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e,
73074624944SHao Chen 			 struct kernel_ethtool_ringparam *kernel_e,
73174624944SHao Chen 			 struct netlink_ext_ack *extack)
732f7917c00SJeff Kirsher {
733f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
734f7917c00SJeff Kirsher 	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
735f7917c00SJeff Kirsher 
736f7917c00SJeff Kirsher 	if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
737f7917c00SJeff Kirsher 	    e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
738f7917c00SJeff Kirsher 	    e->tx_pending > MAX_CMDQ_ENTRIES ||
739f7917c00SJeff Kirsher 	    e->rx_pending < MIN_FL_ENTRIES ||
740f7917c00SJeff Kirsher 	    e->rx_jumbo_pending < MIN_FL_ENTRIES ||
741f7917c00SJeff Kirsher 	    e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
742f7917c00SJeff Kirsher 		return -EINVAL;
743f7917c00SJeff Kirsher 
744f7917c00SJeff Kirsher 	if (adapter->flags & FULL_INIT_DONE)
745f7917c00SJeff Kirsher 		return -EBUSY;
746f7917c00SJeff Kirsher 
747f7917c00SJeff Kirsher 	adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
748f7917c00SJeff Kirsher 	adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
749f7917c00SJeff Kirsher 	adapter->params.sge.cmdQ_size[0] = e->tx_pending;
750f7917c00SJeff Kirsher 	adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
751f7917c00SJeff Kirsher 		MAX_CMDQ1_ENTRIES : e->tx_pending;
752f7917c00SJeff Kirsher 	return 0;
753f7917c00SJeff Kirsher }
754f7917c00SJeff Kirsher 
set_coalesce(struct net_device * dev,struct ethtool_coalesce * c,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)755f3ccfda1SYufeng Mo static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c,
756f3ccfda1SYufeng Mo 			struct kernel_ethtool_coalesce *kernel_coal,
757f3ccfda1SYufeng Mo 			struct netlink_ext_ack *extack)
758f7917c00SJeff Kirsher {
759f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
760f7917c00SJeff Kirsher 
761f7917c00SJeff Kirsher 	adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
762f7917c00SJeff Kirsher 	adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
763f7917c00SJeff Kirsher 	adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
764f7917c00SJeff Kirsher 	t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
765f7917c00SJeff Kirsher 	return 0;
766f7917c00SJeff Kirsher }
767f7917c00SJeff Kirsher 
get_coalesce(struct net_device * dev,struct ethtool_coalesce * c,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)768f3ccfda1SYufeng Mo static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c,
769f3ccfda1SYufeng Mo 			struct kernel_ethtool_coalesce *kernel_coal,
770f3ccfda1SYufeng Mo 			struct netlink_ext_ack *extack)
771f7917c00SJeff Kirsher {
772f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
773f7917c00SJeff Kirsher 
774f7917c00SJeff Kirsher 	c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
775f7917c00SJeff Kirsher 	c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
776f7917c00SJeff Kirsher 	c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
777f7917c00SJeff Kirsher 	return 0;
778f7917c00SJeff Kirsher }
779f7917c00SJeff Kirsher 
get_eeprom_len(struct net_device * dev)780f7917c00SJeff Kirsher static int get_eeprom_len(struct net_device *dev)
781f7917c00SJeff Kirsher {
782f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
783f7917c00SJeff Kirsher 
784f7917c00SJeff Kirsher 	return t1_is_asic(adapter) ? EEPROM_SIZE : 0;
785f7917c00SJeff Kirsher }
786f7917c00SJeff Kirsher 
787f7917c00SJeff Kirsher #define EEPROM_MAGIC(ap) \
788f7917c00SJeff Kirsher 	(PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
789f7917c00SJeff Kirsher 
get_eeprom(struct net_device * dev,struct ethtool_eeprom * e,u8 * data)790f7917c00SJeff Kirsher static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
791f7917c00SJeff Kirsher 		      u8 *data)
792f7917c00SJeff Kirsher {
793f7917c00SJeff Kirsher 	int i;
794f7917c00SJeff Kirsher 	u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
795f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
796f7917c00SJeff Kirsher 
797f7917c00SJeff Kirsher 	e->magic = EEPROM_MAGIC(adapter);
798f7917c00SJeff Kirsher 	for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
799f7917c00SJeff Kirsher 		t1_seeprom_read(adapter, i, (__le32 *)&buf[i]);
800f7917c00SJeff Kirsher 	memcpy(data, buf + e->offset, e->len);
801f7917c00SJeff Kirsher 	return 0;
802f7917c00SJeff Kirsher }
803f7917c00SJeff Kirsher 
804f7917c00SJeff Kirsher static const struct ethtool_ops t1_ethtool_ops = {
805d824178dSJakub Kicinski 	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
806d824178dSJakub Kicinski 				     ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
807d824178dSJakub Kicinski 				     ETHTOOL_COALESCE_RATE_SAMPLE_INTERVAL,
808f7917c00SJeff Kirsher 	.get_drvinfo       = get_drvinfo,
809f7917c00SJeff Kirsher 	.get_msglevel      = get_msglevel,
810f7917c00SJeff Kirsher 	.set_msglevel      = set_msglevel,
811f7917c00SJeff Kirsher 	.get_ringparam     = get_sge_param,
812f7917c00SJeff Kirsher 	.set_ringparam     = set_sge_param,
813f7917c00SJeff Kirsher 	.get_coalesce      = get_coalesce,
814f7917c00SJeff Kirsher 	.set_coalesce      = set_coalesce,
815f7917c00SJeff Kirsher 	.get_eeprom_len    = get_eeprom_len,
816f7917c00SJeff Kirsher 	.get_eeprom        = get_eeprom,
817f7917c00SJeff Kirsher 	.get_pauseparam    = get_pauseparam,
818f7917c00SJeff Kirsher 	.set_pauseparam    = set_pauseparam,
819f7917c00SJeff Kirsher 	.get_link          = ethtool_op_get_link,
820f7917c00SJeff Kirsher 	.get_strings       = get_strings,
821f7917c00SJeff Kirsher 	.get_sset_count	   = get_sset_count,
822f7917c00SJeff Kirsher 	.get_ethtool_stats = get_stats,
823f7917c00SJeff Kirsher 	.get_regs_len      = get_regs_len,
824f7917c00SJeff Kirsher 	.get_regs          = get_regs,
82549cad939SPhilippe Reynes 	.get_link_ksettings = get_link_ksettings,
82649cad939SPhilippe Reynes 	.set_link_ksettings = set_link_ksettings,
827f7917c00SJeff Kirsher };
828f7917c00SJeff Kirsher 
t1_ioctl(struct net_device * dev,struct ifreq * req,int cmd)829f7917c00SJeff Kirsher static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
830f7917c00SJeff Kirsher {
831f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
832f7917c00SJeff Kirsher 	struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
833f7917c00SJeff Kirsher 
834f7917c00SJeff Kirsher 	return mdio_mii_ioctl(mdio, if_mii(req), cmd);
835f7917c00SJeff Kirsher }
836f7917c00SJeff Kirsher 
t1_change_mtu(struct net_device * dev,int new_mtu)837f7917c00SJeff Kirsher static int t1_change_mtu(struct net_device *dev, int new_mtu)
838f7917c00SJeff Kirsher {
839f7917c00SJeff Kirsher 	int ret;
840f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
841f7917c00SJeff Kirsher 	struct cmac *mac = adapter->port[dev->if_port].mac;
842f7917c00SJeff Kirsher 
843f7917c00SJeff Kirsher 	if (!mac->ops->set_mtu)
844f7917c00SJeff Kirsher 		return -EOPNOTSUPP;
845f7917c00SJeff Kirsher 	if ((ret = mac->ops->set_mtu(mac, new_mtu)))
846f7917c00SJeff Kirsher 		return ret;
847f7917c00SJeff Kirsher 	dev->mtu = new_mtu;
848f7917c00SJeff Kirsher 	return 0;
849f7917c00SJeff Kirsher }
850f7917c00SJeff Kirsher 
t1_set_mac_addr(struct net_device * dev,void * p)851f7917c00SJeff Kirsher static int t1_set_mac_addr(struct net_device *dev, void *p)
852f7917c00SJeff Kirsher {
853f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
854f7917c00SJeff Kirsher 	struct cmac *mac = adapter->port[dev->if_port].mac;
855f7917c00SJeff Kirsher 	struct sockaddr *addr = p;
856f7917c00SJeff Kirsher 
857f7917c00SJeff Kirsher 	if (!mac->ops->macaddress_set)
858f7917c00SJeff Kirsher 		return -EOPNOTSUPP;
859f7917c00SJeff Kirsher 
860a05e4c0aSJakub Kicinski 	eth_hw_addr_set(dev, addr->sa_data);
861f7917c00SJeff Kirsher 	mac->ops->macaddress_set(mac, dev->dev_addr);
862f7917c00SJeff Kirsher 	return 0;
863f7917c00SJeff Kirsher }
864f7917c00SJeff Kirsher 
t1_fix_features(struct net_device * dev,netdev_features_t features)865c8f44affSMichał Mirosław static netdev_features_t t1_fix_features(struct net_device *dev,
866c8f44affSMichał Mirosław 	netdev_features_t features)
867f7917c00SJeff Kirsher {
868f7917c00SJeff Kirsher 	/*
869f7917c00SJeff Kirsher 	 * Since there is no support for separate rx/tx vlan accel
870f7917c00SJeff Kirsher 	 * enable/disable make sure tx flag is always in same state as rx.
871f7917c00SJeff Kirsher 	 */
872f646968fSPatrick McHardy 	if (features & NETIF_F_HW_VLAN_CTAG_RX)
873f646968fSPatrick McHardy 		features |= NETIF_F_HW_VLAN_CTAG_TX;
874f7917c00SJeff Kirsher 	else
875f646968fSPatrick McHardy 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
876f7917c00SJeff Kirsher 
877f7917c00SJeff Kirsher 	return features;
878f7917c00SJeff Kirsher }
879f7917c00SJeff Kirsher 
t1_set_features(struct net_device * dev,netdev_features_t features)880c8f44affSMichał Mirosław static int t1_set_features(struct net_device *dev, netdev_features_t features)
881f7917c00SJeff Kirsher {
882c8f44affSMichał Mirosław 	netdev_features_t changed = dev->features ^ features;
883f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
884f7917c00SJeff Kirsher 
885f646968fSPatrick McHardy 	if (changed & NETIF_F_HW_VLAN_CTAG_RX)
886f7917c00SJeff Kirsher 		t1_vlan_mode(adapter, features);
887f7917c00SJeff Kirsher 
888f7917c00SJeff Kirsher 	return 0;
889f7917c00SJeff Kirsher }
890f7917c00SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
t1_netpoll(struct net_device * dev)891f7917c00SJeff Kirsher static void t1_netpoll(struct net_device *dev)
892f7917c00SJeff Kirsher {
893f7917c00SJeff Kirsher 	unsigned long flags;
894f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
895f7917c00SJeff Kirsher 
896f7917c00SJeff Kirsher 	local_irq_save(flags);
897f7917c00SJeff Kirsher 	t1_interrupt(adapter->pdev->irq, adapter);
898f7917c00SJeff Kirsher 	local_irq_restore(flags);
899f7917c00SJeff Kirsher }
900f7917c00SJeff Kirsher #endif
901f7917c00SJeff Kirsher 
902f7917c00SJeff Kirsher /*
903f7917c00SJeff Kirsher  * Periodic accumulation of MAC statistics.  This is used only if the MAC
904f7917c00SJeff Kirsher  * does not have any other way to prevent stats counter overflow.
905f7917c00SJeff Kirsher  */
mac_stats_task(struct work_struct * work)906f7917c00SJeff Kirsher static void mac_stats_task(struct work_struct *work)
907f7917c00SJeff Kirsher {
908f7917c00SJeff Kirsher 	int i;
909f7917c00SJeff Kirsher 	struct adapter *adapter =
910f7917c00SJeff Kirsher 		container_of(work, struct adapter, stats_update_task.work);
911f7917c00SJeff Kirsher 
912f7917c00SJeff Kirsher 	for_each_port(adapter, i) {
913f7917c00SJeff Kirsher 		struct port_info *p = &adapter->port[i];
914f7917c00SJeff Kirsher 
915f7917c00SJeff Kirsher 		if (netif_running(p->dev))
916f7917c00SJeff Kirsher 			p->mac->ops->statistics_update(p->mac,
917f7917c00SJeff Kirsher 						       MAC_STATS_UPDATE_FAST);
918f7917c00SJeff Kirsher 	}
919f7917c00SJeff Kirsher 
920f7917c00SJeff Kirsher 	/* Schedule the next statistics update if any port is active. */
921f7917c00SJeff Kirsher 	spin_lock(&adapter->work_lock);
922f7917c00SJeff Kirsher 	if (adapter->open_device_map & PORT_MASK)
923f7917c00SJeff Kirsher 		schedule_mac_stats_update(adapter,
924f7917c00SJeff Kirsher 					  adapter->params.stats_update_period);
925f7917c00SJeff Kirsher 	spin_unlock(&adapter->work_lock);
926f7917c00SJeff Kirsher }
927f7917c00SJeff Kirsher 
928f7917c00SJeff Kirsher static const struct net_device_ops cxgb_netdev_ops = {
929f7917c00SJeff Kirsher 	.ndo_open		= cxgb_open,
930f7917c00SJeff Kirsher 	.ndo_stop		= cxgb_close,
931f7917c00SJeff Kirsher 	.ndo_start_xmit		= t1_start_xmit,
932f7917c00SJeff Kirsher 	.ndo_get_stats		= t1_get_stats,
933f7917c00SJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
934afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= t1_set_rxmode,
935a7605370SArnd Bergmann 	.ndo_eth_ioctl		= t1_ioctl,
936f7917c00SJeff Kirsher 	.ndo_change_mtu		= t1_change_mtu,
937f7917c00SJeff Kirsher 	.ndo_set_mac_address	= t1_set_mac_addr,
938f7917c00SJeff Kirsher 	.ndo_fix_features	= t1_fix_features,
939f7917c00SJeff Kirsher 	.ndo_set_features	= t1_set_features,
940f7917c00SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
941f7917c00SJeff Kirsher 	.ndo_poll_controller	= t1_netpoll,
942f7917c00SJeff Kirsher #endif
943f7917c00SJeff Kirsher };
944f7917c00SJeff Kirsher 
init_one(struct pci_dev * pdev,const struct pci_device_id * ent)9451dd06ae8SGreg Kroah-Hartman static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
946f7917c00SJeff Kirsher {
947f7917c00SJeff Kirsher 	unsigned long mmio_start, mmio_len;
948f7917c00SJeff Kirsher 	const struct board_info *bi;
949f7917c00SJeff Kirsher 	struct adapter *adapter = NULL;
950f7917c00SJeff Kirsher 	struct port_info *pi;
9511aae5cc0SChristophe JAILLET 	int i, err;
952f7917c00SJeff Kirsher 
953f7917c00SJeff Kirsher 	err = pci_enable_device(pdev);
954f7917c00SJeff Kirsher 	if (err)
955f7917c00SJeff Kirsher 		return err;
956f7917c00SJeff Kirsher 
957f7917c00SJeff Kirsher 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
958f7917c00SJeff Kirsher 		pr_err("%s: cannot find PCI device memory base address\n",
959f7917c00SJeff Kirsher 		       pci_name(pdev));
960f7917c00SJeff Kirsher 		err = -ENODEV;
961f7917c00SJeff Kirsher 		goto out_disable_pdev;
962f7917c00SJeff Kirsher 	}
963f7917c00SJeff Kirsher 
9641aae5cc0SChristophe JAILLET 	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
9651aae5cc0SChristophe JAILLET 	if (err) {
966f7917c00SJeff Kirsher 		pr_err("%s: no usable DMA configuration\n", pci_name(pdev));
967f7917c00SJeff Kirsher 		goto out_disable_pdev;
968f7917c00SJeff Kirsher 	}
969f7917c00SJeff Kirsher 
970f7917c00SJeff Kirsher 	err = pci_request_regions(pdev, DRV_NAME);
971f7917c00SJeff Kirsher 	if (err) {
972f7917c00SJeff Kirsher 		pr_err("%s: cannot obtain PCI resources\n", pci_name(pdev));
973f7917c00SJeff Kirsher 		goto out_disable_pdev;
974f7917c00SJeff Kirsher 	}
975f7917c00SJeff Kirsher 
976f7917c00SJeff Kirsher 	pci_set_master(pdev);
977f7917c00SJeff Kirsher 
978f7917c00SJeff Kirsher 	mmio_start = pci_resource_start(pdev, 0);
979f7917c00SJeff Kirsher 	mmio_len = pci_resource_len(pdev, 0);
980f7917c00SJeff Kirsher 	bi = t1_get_board_info(ent->driver_data);
981f7917c00SJeff Kirsher 
982f7917c00SJeff Kirsher 	for (i = 0; i < bi->port_number; ++i) {
983f7917c00SJeff Kirsher 		struct net_device *netdev;
984f7917c00SJeff Kirsher 
985f7917c00SJeff Kirsher 		netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
986f7917c00SJeff Kirsher 		if (!netdev) {
987f7917c00SJeff Kirsher 			err = -ENOMEM;
988f7917c00SJeff Kirsher 			goto out_free_dev;
989f7917c00SJeff Kirsher 		}
990f7917c00SJeff Kirsher 
991f7917c00SJeff Kirsher 		SET_NETDEV_DEV(netdev, &pdev->dev);
992f7917c00SJeff Kirsher 
993f7917c00SJeff Kirsher 		if (!adapter) {
994f7917c00SJeff Kirsher 			adapter = netdev_priv(netdev);
995f7917c00SJeff Kirsher 			adapter->pdev = pdev;
996f7917c00SJeff Kirsher 			adapter->port[0].dev = netdev;  /* so we don't leak it */
997f7917c00SJeff Kirsher 
998f7917c00SJeff Kirsher 			adapter->regs = ioremap(mmio_start, mmio_len);
999f7917c00SJeff Kirsher 			if (!adapter->regs) {
1000f7917c00SJeff Kirsher 				pr_err("%s: cannot map device registers\n",
1001f7917c00SJeff Kirsher 				       pci_name(pdev));
1002f7917c00SJeff Kirsher 				err = -ENOMEM;
1003f7917c00SJeff Kirsher 				goto out_free_dev;
1004f7917c00SJeff Kirsher 			}
1005f7917c00SJeff Kirsher 
1006f7917c00SJeff Kirsher 			if (t1_get_board_rev(adapter, bi, &adapter->params)) {
1007f7917c00SJeff Kirsher 				err = -ENODEV;	  /* Can't handle this chip rev */
1008f7917c00SJeff Kirsher 				goto out_free_dev;
1009f7917c00SJeff Kirsher 			}
1010f7917c00SJeff Kirsher 
1011f7917c00SJeff Kirsher 			adapter->name = pci_name(pdev);
1012f7917c00SJeff Kirsher 			adapter->msg_enable = dflt_msg_enable;
1013f7917c00SJeff Kirsher 			adapter->mmio_len = mmio_len;
1014f7917c00SJeff Kirsher 
1015f7917c00SJeff Kirsher 			spin_lock_init(&adapter->tpi_lock);
1016f7917c00SJeff Kirsher 			spin_lock_init(&adapter->work_lock);
1017f7917c00SJeff Kirsher 			spin_lock_init(&adapter->async_lock);
1018f7917c00SJeff Kirsher 			spin_lock_init(&adapter->mac_lock);
1019f7917c00SJeff Kirsher 
1020f7917c00SJeff Kirsher 			INIT_DELAYED_WORK(&adapter->stats_update_task,
1021f7917c00SJeff Kirsher 					  mac_stats_task);
1022f7917c00SJeff Kirsher 
1023f7917c00SJeff Kirsher 			pci_set_drvdata(pdev, netdev);
1024f7917c00SJeff Kirsher 		}
1025f7917c00SJeff Kirsher 
1026f7917c00SJeff Kirsher 		pi = &adapter->port[i];
1027f7917c00SJeff Kirsher 		pi->dev = netdev;
1028f7917c00SJeff Kirsher 		netif_carrier_off(netdev);
1029f7917c00SJeff Kirsher 		netdev->irq = pdev->irq;
1030f7917c00SJeff Kirsher 		netdev->if_port = i;
1031f7917c00SJeff Kirsher 		netdev->mem_start = mmio_start;
1032f7917c00SJeff Kirsher 		netdev->mem_end = mmio_start + mmio_len - 1;
1033f7917c00SJeff Kirsher 		netdev->ml_priv = adapter;
1034f7917c00SJeff Kirsher 		netdev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
1035f7917c00SJeff Kirsher 			NETIF_F_RXCSUM;
1036f7917c00SJeff Kirsher 		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
10371aae5cc0SChristophe JAILLET 			NETIF_F_RXCSUM | NETIF_F_LLTX | NETIF_F_HIGHDMA;
1038f7917c00SJeff Kirsher 
1039f7917c00SJeff Kirsher 		if (vlan_tso_capable(adapter)) {
1040f7917c00SJeff Kirsher 			netdev->features |=
1041f646968fSPatrick McHardy 				NETIF_F_HW_VLAN_CTAG_TX |
1042f646968fSPatrick McHardy 				NETIF_F_HW_VLAN_CTAG_RX;
1043f646968fSPatrick McHardy 			netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
1044f7917c00SJeff Kirsher 
1045f7917c00SJeff Kirsher 			/* T204: disable TSO */
1046f7917c00SJeff Kirsher 			if (!(is_T2(adapter)) || bi->port_number != 4) {
1047f7917c00SJeff Kirsher 				netdev->hw_features |= NETIF_F_TSO;
1048f7917c00SJeff Kirsher 				netdev->features |= NETIF_F_TSO;
1049f7917c00SJeff Kirsher 			}
1050f7917c00SJeff Kirsher 		}
1051f7917c00SJeff Kirsher 
1052f7917c00SJeff Kirsher 		netdev->netdev_ops = &cxgb_netdev_ops;
1053f7917c00SJeff Kirsher 		netdev->hard_header_len += (netdev->hw_features & NETIF_F_TSO) ?
1054f7917c00SJeff Kirsher 			sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
1055f7917c00SJeff Kirsher 
1056*b48b89f9SJakub Kicinski 		netif_napi_add(netdev, &adapter->napi, t1_poll);
1057f7917c00SJeff Kirsher 
10587ad24ea4SWilfried Klaebe 		netdev->ethtool_ops = &t1_ethtool_ops;
105944770e11SJarod Wilson 
106044770e11SJarod Wilson 		switch (bi->board) {
106144770e11SJarod Wilson 		case CHBT_BOARD_CHT110:
106244770e11SJarod Wilson 		case CHBT_BOARD_N110:
106344770e11SJarod Wilson 		case CHBT_BOARD_N210:
106444770e11SJarod Wilson 		case CHBT_BOARD_CHT210:
106544770e11SJarod Wilson 			netdev->max_mtu = PM3393_MAX_FRAME_SIZE -
106644770e11SJarod Wilson 					  (ETH_HLEN + ETH_FCS_LEN);
106744770e11SJarod Wilson 			break;
106844770e11SJarod Wilson 		case CHBT_BOARD_CHN204:
106944770e11SJarod Wilson 			netdev->max_mtu = VSC7326_MAX_MTU;
107044770e11SJarod Wilson 			break;
107144770e11SJarod Wilson 		default:
107244770e11SJarod Wilson 			netdev->max_mtu = ETH_DATA_LEN;
107344770e11SJarod Wilson 			break;
107444770e11SJarod Wilson 		}
1075f7917c00SJeff Kirsher 	}
1076f7917c00SJeff Kirsher 
1077f7917c00SJeff Kirsher 	if (t1_init_sw_modules(adapter, bi) < 0) {
1078f7917c00SJeff Kirsher 		err = -ENODEV;
1079f7917c00SJeff Kirsher 		goto out_free_dev;
1080f7917c00SJeff Kirsher 	}
1081f7917c00SJeff Kirsher 
1082f7917c00SJeff Kirsher 	/*
1083f7917c00SJeff Kirsher 	 * The card is now ready to go.  If any errors occur during device
1084f7917c00SJeff Kirsher 	 * registration we do not fail the whole card but rather proceed only
1085f7917c00SJeff Kirsher 	 * with the ports we manage to register successfully.  However we must
1086f7917c00SJeff Kirsher 	 * register at least one net device.
1087f7917c00SJeff Kirsher 	 */
1088f7917c00SJeff Kirsher 	for (i = 0; i < bi->port_number; ++i) {
1089f7917c00SJeff Kirsher 		err = register_netdev(adapter->port[i].dev);
1090f7917c00SJeff Kirsher 		if (err)
1091428ac43fSJoe Perches 			pr_warn("%s: cannot register net device %s, skipping\n",
1092f7917c00SJeff Kirsher 				pci_name(pdev), adapter->port[i].dev->name);
1093f7917c00SJeff Kirsher 		else {
1094f7917c00SJeff Kirsher 			/*
1095f7917c00SJeff Kirsher 			 * Change the name we use for messages to the name of
1096f7917c00SJeff Kirsher 			 * the first successfully registered interface.
1097f7917c00SJeff Kirsher 			 */
1098f7917c00SJeff Kirsher 			if (!adapter->registered_device_map)
1099f7917c00SJeff Kirsher 				adapter->name = adapter->port[i].dev->name;
1100f7917c00SJeff Kirsher 
1101f7917c00SJeff Kirsher 			__set_bit(i, &adapter->registered_device_map);
1102f7917c00SJeff Kirsher 		}
1103f7917c00SJeff Kirsher 	}
1104f7917c00SJeff Kirsher 	if (!adapter->registered_device_map) {
1105f7917c00SJeff Kirsher 		pr_err("%s: could not register any net devices\n",
1106f7917c00SJeff Kirsher 		       pci_name(pdev));
11077db8263aSYang Li 		err = -EINVAL;
1108f7917c00SJeff Kirsher 		goto out_release_adapter_res;
1109f7917c00SJeff Kirsher 	}
1110f7917c00SJeff Kirsher 
1111428ac43fSJoe Perches 	pr_info("%s: %s (rev %d), %s %dMHz/%d-bit\n",
1112428ac43fSJoe Perches 		adapter->name, bi->desc, adapter->params.chip_revision,
1113f7917c00SJeff Kirsher 		adapter->params.pci.is_pcix ? "PCIX" : "PCI",
1114f7917c00SJeff Kirsher 		adapter->params.pci.speed, adapter->params.pci.width);
1115f7917c00SJeff Kirsher 
1116f7917c00SJeff Kirsher 	/*
1117f7917c00SJeff Kirsher 	 * Set the T1B ASIC and memory clocks.
1118f7917c00SJeff Kirsher 	 */
1119f7917c00SJeff Kirsher 	if (t1powersave)
1120f7917c00SJeff Kirsher 		adapter->t1powersave = LCLOCK;	/* HW default is powersave mode. */
1121f7917c00SJeff Kirsher 	else
1122f7917c00SJeff Kirsher 		adapter->t1powersave = HCLOCK;
1123f7917c00SJeff Kirsher 	if (t1_is_T1B(adapter))
1124f7917c00SJeff Kirsher 		t1_clock(adapter, t1powersave);
1125f7917c00SJeff Kirsher 
1126f7917c00SJeff Kirsher 	return 0;
1127f7917c00SJeff Kirsher 
1128f7917c00SJeff Kirsher out_release_adapter_res:
1129f7917c00SJeff Kirsher 	t1_free_sw_modules(adapter);
1130f7917c00SJeff Kirsher out_free_dev:
1131f7917c00SJeff Kirsher 	if (adapter) {
1132f7917c00SJeff Kirsher 		if (adapter->regs)
1133f7917c00SJeff Kirsher 			iounmap(adapter->regs);
1134f7917c00SJeff Kirsher 		for (i = bi->port_number - 1; i >= 0; --i)
1135f7917c00SJeff Kirsher 			if (adapter->port[i].dev)
1136f7917c00SJeff Kirsher 				free_netdev(adapter->port[i].dev);
1137f7917c00SJeff Kirsher 	}
1138f7917c00SJeff Kirsher 	pci_release_regions(pdev);
1139f7917c00SJeff Kirsher out_disable_pdev:
1140f7917c00SJeff Kirsher 	pci_disable_device(pdev);
1141f7917c00SJeff Kirsher 	return err;
1142f7917c00SJeff Kirsher }
1143f7917c00SJeff Kirsher 
bit_bang(struct adapter * adapter,int bitdata,int nbits)1144f7917c00SJeff Kirsher static void bit_bang(struct adapter *adapter, int bitdata, int nbits)
1145f7917c00SJeff Kirsher {
1146f7917c00SJeff Kirsher 	int data;
1147f7917c00SJeff Kirsher 	int i;
1148f7917c00SJeff Kirsher 	u32 val;
1149f7917c00SJeff Kirsher 
1150f7917c00SJeff Kirsher 	enum {
1151f7917c00SJeff Kirsher 		S_CLOCK = 1 << 3,
1152f7917c00SJeff Kirsher 		S_DATA = 1 << 4
1153f7917c00SJeff Kirsher 	};
1154f7917c00SJeff Kirsher 
1155f7917c00SJeff Kirsher 	for (i = (nbits - 1); i > -1; i--) {
1156f7917c00SJeff Kirsher 
1157f7917c00SJeff Kirsher 		udelay(50);
1158f7917c00SJeff Kirsher 
1159f7917c00SJeff Kirsher 		data = ((bitdata >> i) & 0x1);
1160f7917c00SJeff Kirsher 		__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1161f7917c00SJeff Kirsher 
1162f7917c00SJeff Kirsher 		if (data)
1163f7917c00SJeff Kirsher 			val |= S_DATA;
1164f7917c00SJeff Kirsher 		else
1165f7917c00SJeff Kirsher 			val &= ~S_DATA;
1166f7917c00SJeff Kirsher 
1167f7917c00SJeff Kirsher 		udelay(50);
1168f7917c00SJeff Kirsher 
1169f7917c00SJeff Kirsher 		/* Set SCLOCK low */
1170f7917c00SJeff Kirsher 		val &= ~S_CLOCK;
1171f7917c00SJeff Kirsher 		__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1172f7917c00SJeff Kirsher 
1173f7917c00SJeff Kirsher 		udelay(50);
1174f7917c00SJeff Kirsher 
1175f7917c00SJeff Kirsher 		/* Write SCLOCK high */
1176f7917c00SJeff Kirsher 		val |= S_CLOCK;
1177f7917c00SJeff Kirsher 		__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1178f7917c00SJeff Kirsher 
1179f7917c00SJeff Kirsher 	}
1180f7917c00SJeff Kirsher }
1181f7917c00SJeff Kirsher 
t1_clock(struct adapter * adapter,int mode)1182f7917c00SJeff Kirsher static int t1_clock(struct adapter *adapter, int mode)
1183f7917c00SJeff Kirsher {
1184f7917c00SJeff Kirsher 	u32 val;
1185f7917c00SJeff Kirsher 	int M_CORE_VAL;
1186f7917c00SJeff Kirsher 	int M_MEM_VAL;
1187f7917c00SJeff Kirsher 
1188f7917c00SJeff Kirsher 	enum {
1189f7917c00SJeff Kirsher 		M_CORE_BITS	= 9,
1190f7917c00SJeff Kirsher 		T_CORE_VAL	= 0,
1191f7917c00SJeff Kirsher 		T_CORE_BITS	= 2,
1192f7917c00SJeff Kirsher 		N_CORE_VAL	= 0,
1193f7917c00SJeff Kirsher 		N_CORE_BITS	= 2,
1194f7917c00SJeff Kirsher 		M_MEM_BITS	= 9,
1195f7917c00SJeff Kirsher 		T_MEM_VAL	= 0,
1196f7917c00SJeff Kirsher 		T_MEM_BITS	= 2,
1197f7917c00SJeff Kirsher 		N_MEM_VAL	= 0,
1198f7917c00SJeff Kirsher 		N_MEM_BITS	= 2,
1199f7917c00SJeff Kirsher 		NP_LOAD		= 1 << 17,
1200f7917c00SJeff Kirsher 		S_LOAD_MEM	= 1 << 5,
1201f7917c00SJeff Kirsher 		S_LOAD_CORE	= 1 << 6,
1202f7917c00SJeff Kirsher 		S_CLOCK		= 1 << 3
1203f7917c00SJeff Kirsher 	};
1204f7917c00SJeff Kirsher 
1205f7917c00SJeff Kirsher 	if (!t1_is_T1B(adapter))
1206f7917c00SJeff Kirsher 		return -ENODEV;	/* Can't re-clock this chip. */
1207f7917c00SJeff Kirsher 
1208f7917c00SJeff Kirsher 	if (mode & 2)
1209f7917c00SJeff Kirsher 		return 0;	/* show current mode. */
1210f7917c00SJeff Kirsher 
1211f7917c00SJeff Kirsher 	if ((adapter->t1powersave & 1) == (mode & 1))
1212f7917c00SJeff Kirsher 		return -EALREADY;	/* ASIC already running in mode. */
1213f7917c00SJeff Kirsher 
1214f7917c00SJeff Kirsher 	if ((mode & 1) == HCLOCK) {
1215f7917c00SJeff Kirsher 		M_CORE_VAL = 0x14;
1216f7917c00SJeff Kirsher 		M_MEM_VAL = 0x18;
1217f7917c00SJeff Kirsher 		adapter->t1powersave = HCLOCK;	/* overclock */
1218f7917c00SJeff Kirsher 	} else {
1219f7917c00SJeff Kirsher 		M_CORE_VAL = 0xe;
1220f7917c00SJeff Kirsher 		M_MEM_VAL = 0x10;
1221f7917c00SJeff Kirsher 		adapter->t1powersave = LCLOCK;	/* underclock */
1222f7917c00SJeff Kirsher 	}
1223f7917c00SJeff Kirsher 
1224f7917c00SJeff Kirsher 	/* Don't interrupt this serial stream! */
1225f7917c00SJeff Kirsher 	spin_lock(&adapter->tpi_lock);
1226f7917c00SJeff Kirsher 
1227f7917c00SJeff Kirsher 	/* Initialize for ASIC core */
1228f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1229f7917c00SJeff Kirsher 	val |= NP_LOAD;
1230f7917c00SJeff Kirsher 	udelay(50);
1231f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1232f7917c00SJeff Kirsher 	udelay(50);
1233f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1234f7917c00SJeff Kirsher 	val &= ~S_LOAD_CORE;
1235f7917c00SJeff Kirsher 	val &= ~S_CLOCK;
1236f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1237f7917c00SJeff Kirsher 	udelay(50);
1238f7917c00SJeff Kirsher 
1239f7917c00SJeff Kirsher 	/* Serial program the ASIC clock synthesizer */
1240f7917c00SJeff Kirsher 	bit_bang(adapter, T_CORE_VAL, T_CORE_BITS);
1241f7917c00SJeff Kirsher 	bit_bang(adapter, N_CORE_VAL, N_CORE_BITS);
1242f7917c00SJeff Kirsher 	bit_bang(adapter, M_CORE_VAL, M_CORE_BITS);
1243f7917c00SJeff Kirsher 	udelay(50);
1244f7917c00SJeff Kirsher 
1245f7917c00SJeff Kirsher 	/* Finish ASIC core */
1246f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1247f7917c00SJeff Kirsher 	val |= S_LOAD_CORE;
1248f7917c00SJeff Kirsher 	udelay(50);
1249f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1250f7917c00SJeff Kirsher 	udelay(50);
1251f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1252f7917c00SJeff Kirsher 	val &= ~S_LOAD_CORE;
1253f7917c00SJeff Kirsher 	udelay(50);
1254f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1255f7917c00SJeff Kirsher 	udelay(50);
1256f7917c00SJeff Kirsher 
1257f7917c00SJeff Kirsher 	/* Initialize for memory */
1258f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1259f7917c00SJeff Kirsher 	val |= NP_LOAD;
1260f7917c00SJeff Kirsher 	udelay(50);
1261f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1262f7917c00SJeff Kirsher 	udelay(50);
1263f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1264f7917c00SJeff Kirsher 	val &= ~S_LOAD_MEM;
1265f7917c00SJeff Kirsher 	val &= ~S_CLOCK;
1266f7917c00SJeff Kirsher 	udelay(50);
1267f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1268f7917c00SJeff Kirsher 	udelay(50);
1269f7917c00SJeff Kirsher 
1270f7917c00SJeff Kirsher 	/* Serial program the memory clock synthesizer */
1271f7917c00SJeff Kirsher 	bit_bang(adapter, T_MEM_VAL, T_MEM_BITS);
1272f7917c00SJeff Kirsher 	bit_bang(adapter, N_MEM_VAL, N_MEM_BITS);
1273f7917c00SJeff Kirsher 	bit_bang(adapter, M_MEM_VAL, M_MEM_BITS);
1274f7917c00SJeff Kirsher 	udelay(50);
1275f7917c00SJeff Kirsher 
1276f7917c00SJeff Kirsher 	/* Finish memory */
1277f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1278f7917c00SJeff Kirsher 	val |= S_LOAD_MEM;
1279f7917c00SJeff Kirsher 	udelay(50);
1280f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1281f7917c00SJeff Kirsher 	udelay(50);
1282f7917c00SJeff Kirsher 	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1283f7917c00SJeff Kirsher 	val &= ~S_LOAD_MEM;
1284f7917c00SJeff Kirsher 	udelay(50);
1285f7917c00SJeff Kirsher 	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1286f7917c00SJeff Kirsher 
1287f7917c00SJeff Kirsher 	spin_unlock(&adapter->tpi_lock);
1288f7917c00SJeff Kirsher 
1289f7917c00SJeff Kirsher 	return 0;
1290f7917c00SJeff Kirsher }
1291f7917c00SJeff Kirsher 
t1_sw_reset(struct pci_dev * pdev)1292f7917c00SJeff Kirsher static inline void t1_sw_reset(struct pci_dev *pdev)
1293f7917c00SJeff Kirsher {
1294f7917c00SJeff Kirsher 	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
1295f7917c00SJeff Kirsher 	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
1296f7917c00SJeff Kirsher }
1297f7917c00SJeff Kirsher 
remove_one(struct pci_dev * pdev)1298ff76a3ccSBill Pemberton static void remove_one(struct pci_dev *pdev)
1299f7917c00SJeff Kirsher {
1300f7917c00SJeff Kirsher 	struct net_device *dev = pci_get_drvdata(pdev);
1301f7917c00SJeff Kirsher 	struct adapter *adapter = dev->ml_priv;
1302f7917c00SJeff Kirsher 	int i;
1303f7917c00SJeff Kirsher 
1304f7917c00SJeff Kirsher 	for_each_port(adapter, i) {
1305f7917c00SJeff Kirsher 		if (test_bit(i, &adapter->registered_device_map))
1306f7917c00SJeff Kirsher 			unregister_netdev(adapter->port[i].dev);
1307f7917c00SJeff Kirsher 	}
1308f7917c00SJeff Kirsher 
1309f7917c00SJeff Kirsher 	t1_free_sw_modules(adapter);
1310f7917c00SJeff Kirsher 	iounmap(adapter->regs);
1311f7917c00SJeff Kirsher 
1312f7917c00SJeff Kirsher 	while (--i >= 0) {
1313f7917c00SJeff Kirsher 		if (adapter->port[i].dev)
1314f7917c00SJeff Kirsher 			free_netdev(adapter->port[i].dev);
1315f7917c00SJeff Kirsher 	}
1316f7917c00SJeff Kirsher 
1317f7917c00SJeff Kirsher 	pci_release_regions(pdev);
1318f7917c00SJeff Kirsher 	pci_disable_device(pdev);
1319f7917c00SJeff Kirsher 	t1_sw_reset(pdev);
1320f7917c00SJeff Kirsher }
1321f7917c00SJeff Kirsher 
132265c21912SPeter Hüwe static struct pci_driver cxgb_pci_driver = {
1323f7917c00SJeff Kirsher 	.name     = DRV_NAME,
1324f7917c00SJeff Kirsher 	.id_table = t1_pci_tbl,
1325f7917c00SJeff Kirsher 	.probe    = init_one,
1326ff76a3ccSBill Pemberton 	.remove   = remove_one,
1327f7917c00SJeff Kirsher };
1328f7917c00SJeff Kirsher 
132965c21912SPeter Hüwe module_pci_driver(cxgb_pci_driver);
1330