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