blob: 0fe7ff750d77e1618a9fd49a59bbf9577ed9190d [file] [log] [blame]
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001/*****************************************************************************
2 * *
3 * File: cxgb2.c *
Scott Bardone559fb512005-06-23 01:40:19 -04004 * $Revision: 1.25 $ *
5 * $Date: 2005/06/22 00:43:25 $ *
Christoph Lameter8199d3a2005-03-30 13:34:31 -08006 * Description: *
7 * Chelsio 10Gb Ethernet Driver. *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License, version 2, as *
11 * published by the Free Software Foundation. *
12 * *
13 * You should have received a copy of the GNU General Public License along *
Jeff Kirsher0ab75ae2013-12-06 06:28:43 -080014 * with this program; if not, see <http://www.gnu.org/licenses/>. *
Christoph Lameter8199d3a2005-03-30 13:34:31 -080015 * *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
17 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
19 * *
20 * http://www.chelsio.com *
21 * *
22 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
23 * All rights reserved. *
24 * *
25 * Maintainers: maintainers@chelsio.com *
26 * *
27 * Authors: Dimitrios Michailidis <dm@chelsio.com> *
28 * Tina Yang <tainay@chelsio.com> *
29 * Felix Marti <felix@chelsio.com> *
30 * Scott Bardone <sbardone@chelsio.com> *
31 * Kurt Ottaway <kottaway@chelsio.com> *
32 * Frank DiMambro <frank@chelsio.com> *
33 * *
34 * History: *
35 * *
36 ****************************************************************************/
37
38#include "common.h"
Christoph Lameter8199d3a2005-03-30 13:34:31 -080039#include <linux/module.h>
Christoph Lameter8199d3a2005-03-30 13:34:31 -080040#include <linux/pci.h>
41#include <linux/netdevice.h>
42#include <linux/etherdevice.h>
43#include <linux/if_vlan.h>
44#include <linux/mii.h>
45#include <linux/sockios.h>
Scott Bardone559fb512005-06-23 01:40:19 -040046#include <linux/dma-mapping.h>
Christoph Lameter8199d3a2005-03-30 13:34:31 -080047#include <asm/uaccess.h>
48
Christoph Lameter8199d3a2005-03-30 13:34:31 -080049#include "cpl5_cmd.h"
50#include "regs.h"
51#include "gmac.h"
52#include "cphy.h"
53#include "sge.h"
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -080054#include "tp.h"
Christoph Lameter8199d3a2005-03-30 13:34:31 -080055#include "espi.h"
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -080056#include "elmer0.h"
Christoph Lameter8199d3a2005-03-30 13:34:31 -080057
Scott Bardone559fb512005-06-23 01:40:19 -040058#include <linux/workqueue.h>
59
Christoph Lameter8199d3a2005-03-30 13:34:31 -080060static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
61{
62 schedule_delayed_work(&ap->stats_update_task, secs * HZ);
63}
64
65static inline void cancel_mac_stats_update(struct adapter *ap)
66{
67 cancel_delayed_work(&ap->stats_update_task);
68}
Christoph Lameter8199d3a2005-03-30 13:34:31 -080069
Francois Romieu356bd142006-12-11 23:47:00 +010070#define MAX_CMDQ_ENTRIES 16384
71#define MAX_CMDQ1_ENTRIES 1024
72#define MAX_RX_BUFFERS 16384
73#define MAX_RX_JUMBO_BUFFERS 16384
Christoph Lameter8199d3a2005-03-30 13:34:31 -080074#define MAX_TX_BUFFERS_HIGH 16384U
75#define MAX_TX_BUFFERS_LOW 1536U
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -080076#define MAX_TX_BUFFERS 1460U
Francois Romieu356bd142006-12-11 23:47:00 +010077#define MIN_FL_ENTRIES 32
Christoph Lameter8199d3a2005-03-30 13:34:31 -080078
Christoph Lameter8199d3a2005-03-30 13:34:31 -080079#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
80 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
81 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
82
83/*
84 * The EEPROM is actually bigger but only the first few bytes are used so we
85 * only report those.
86 */
87#define EEPROM_SIZE 32
88
Scott Bardone559fb512005-06-23 01:40:19 -040089MODULE_DESCRIPTION(DRV_DESCRIPTION);
Christoph Lameter8199d3a2005-03-30 13:34:31 -080090MODULE_AUTHOR("Chelsio Communications");
91MODULE_LICENSE("GPL");
Christoph Lameter8199d3a2005-03-30 13:34:31 -080092
93static int dflt_msg_enable = DFLT_MSG_ENABLE;
94
Rusty Russell8d3b33f2006-03-25 03:07:05 -080095module_param(dflt_msg_enable, int, 0);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -080096MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap");
Christoph Lameter8199d3a2005-03-30 13:34:31 -080097
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -080098#define HCLOCK 0x0
99#define LCLOCK 0x1
100
101/* T1 cards powersave mode */
102static int t1_clock(struct adapter *adapter, int mode);
103static int t1powersave = 1; /* HW default is powersave mode. */
104
105module_param(t1powersave, int, 0);
106MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode");
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800107
Stephen Hemminger325dde42006-12-01 16:36:20 -0800108static int disable_msi = 0;
109module_param(disable_msi, int, 0);
110MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800111
112static const char pci_speed[][4] = {
113 "33", "66", "100", "133"
114};
115
116/*
117 * Setup MAC to receive the types of packets we want.
118 */
119static void t1_set_rxmode(struct net_device *dev)
120{
Wang Chenc3ccc122008-11-16 23:06:39 -0800121 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800122 struct cmac *mac = adapter->port[dev->if_port].mac;
123 struct t1_rx_mode rm;
124
125 rm.dev = dev;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800126 mac->ops->set_rx_mode(mac, &rm);
127}
128
129static void link_report(struct port_info *p)
130{
131 if (!netif_carrier_ok(p->dev))
Joe Perches428ac432013-01-06 13:34:49 +0000132 netdev_info(p->dev, "link down\n");
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800133 else {
Scott Bardone559fb512005-06-23 01:40:19 -0400134 const char *s = "10Mbps";
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800135
136 switch (p->link_config.speed) {
Scott Bardone559fb512005-06-23 01:40:19 -0400137 case SPEED_10000: s = "10Gbps"; break;
138 case SPEED_1000: s = "1000Mbps"; break;
139 case SPEED_100: s = "100Mbps"; break;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800140 }
141
Joe Perches428ac432013-01-06 13:34:49 +0000142 netdev_info(p->dev, "link up, %s, %s-duplex\n",
143 s, p->link_config.duplex == DUPLEX_FULL
144 ? "full" : "half");
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800145 }
146}
147
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800148void t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat,
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800149 int speed, int duplex, int pause)
150{
151 struct port_info *p = &adapter->port[port_id];
152
153 if (link_stat != netif_carrier_ok(p->dev)) {
154 if (link_stat)
155 netif_carrier_on(p->dev);
156 else
157 netif_carrier_off(p->dev);
158 link_report(p);
159
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800160 /* multi-ports: inform toe */
161 if ((speed > 0) && (adapter->params.nports > 1)) {
162 unsigned int sched_speed = 10;
163 switch (speed) {
164 case SPEED_1000:
165 sched_speed = 1000;
166 break;
167 case SPEED_100:
168 sched_speed = 100;
169 break;
170 case SPEED_10:
171 sched_speed = 10;
172 break;
173 }
174 t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed);
175 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800176 }
177}
178
179static void link_start(struct port_info *p)
180{
181 struct cmac *mac = p->mac;
182
183 mac->ops->reset(mac);
184 if (mac->ops->macaddress_set)
185 mac->ops->macaddress_set(mac, p->dev->dev_addr);
186 t1_set_rxmode(p->dev);
187 t1_link_start(p->phy, mac, &p->link_config);
188 mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
189}
190
191static void enable_hw_csum(struct adapter *adapter)
192{
Michał Mirosław30f554f2011-04-18 13:31:20 +0000193 if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800194 t1_tp_set_ip_checksum_offload(adapter->tp, 1); /* for TSO only */
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800195 t1_tp_set_tcp_checksum_offload(adapter->tp, 1);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800196}
197
198/*
199 * Things to do upon first use of a card.
200 * This must run with the rtnl lock held.
201 */
202static int cxgb_up(struct adapter *adapter)
203{
204 int err = 0;
205
206 if (!(adapter->flags & FULL_INIT_DONE)) {
207 err = t1_init_hw_modules(adapter);
208 if (err)
209 goto out_err;
210
211 enable_hw_csum(adapter);
212 adapter->flags |= FULL_INIT_DONE;
213 }
214
215 t1_interrupts_clear(adapter);
Stephen Hemminger325dde42006-12-01 16:36:20 -0800216
Stephen Hemminger7fe26a62006-12-08 11:08:33 -0800217 adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
218 err = request_irq(adapter->pdev->irq, t1_interrupt,
Stephen Hemminger325dde42006-12-01 16:36:20 -0800219 adapter->params.has_msi ? 0 : IRQF_SHARED,
220 adapter->name, adapter);
221 if (err) {
222 if (adapter->params.has_msi)
223 pci_disable_msi(adapter->pdev);
224
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800225 goto out_err;
Scott Bardone559fb512005-06-23 01:40:19 -0400226 }
Stephen Hemminger325dde42006-12-01 16:36:20 -0800227
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800228 t1_sge_start(adapter->sge);
229 t1_interrupts_enable(adapter);
Francois Romieu356bd142006-12-11 23:47:00 +0100230out_err:
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800231 return err;
232}
233
234/*
235 * Release resources when all the ports have been stopped.
236 */
237static void cxgb_down(struct adapter *adapter)
238{
239 t1_sge_stop(adapter->sge);
240 t1_interrupts_disable(adapter);
241 free_irq(adapter->pdev->irq, adapter);
Stephen Hemminger325dde42006-12-01 16:36:20 -0800242 if (adapter->params.has_msi)
243 pci_disable_msi(adapter->pdev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800244}
245
246static int cxgb_open(struct net_device *dev)
247{
248 int err;
Wang Chenc3ccc122008-11-16 23:06:39 -0800249 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800250 int other_ports = adapter->open_device_map & PORT_MASK;
251
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700252 napi_enable(&adapter->napi);
253 if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
254 napi_disable(&adapter->napi);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800255 return err;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700256 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800257
258 __set_bit(dev->if_port, &adapter->open_device_map);
259 link_start(&adapter->port[dev->if_port]);
260 netif_start_queue(dev);
261 if (!other_ports && adapter->params.stats_update_period)
262 schedule_mac_stats_update(adapter,
263 adapter->params.stats_update_period);
Jiri Pirko133b0852011-07-20 04:54:15 +0000264
265 t1_vlan_mode(adapter, dev->features);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800266 return 0;
267}
268
269static int cxgb_close(struct net_device *dev)
270{
Wang Chenc3ccc122008-11-16 23:06:39 -0800271 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800272 struct port_info *p = &adapter->port[dev->if_port];
273 struct cmac *mac = p->mac;
274
275 netif_stop_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700276 napi_disable(&adapter->napi);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800277 mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
278 netif_carrier_off(dev);
279
280 clear_bit(dev->if_port, &adapter->open_device_map);
281 if (adapter->params.stats_update_period &&
282 !(adapter->open_device_map & PORT_MASK)) {
283 /* Stop statistics accumulation. */
284 smp_mb__after_clear_bit();
285 spin_lock(&adapter->work_lock); /* sync with update task */
286 spin_unlock(&adapter->work_lock);
287 cancel_mac_stats_update(adapter);
288 }
289
290 if (!adapter->open_device_map)
291 cxgb_down(adapter);
292 return 0;
293}
294
295static struct net_device_stats *t1_get_stats(struct net_device *dev)
296{
Wang Chenc3ccc122008-11-16 23:06:39 -0800297 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800298 struct port_info *p = &adapter->port[dev->if_port];
299 struct net_device_stats *ns = &p->netstats;
300 const struct cmac_statistics *pstats;
301
302 /* Do a full update of the MAC stats */
303 pstats = p->mac->ops->statistics_update(p->mac,
Stephen Hemminger20578152006-11-17 11:21:22 -0800304 MAC_STATS_UPDATE_FULL);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800305
306 ns->tx_packets = pstats->TxUnicastFramesOK +
307 pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
308
309 ns->rx_packets = pstats->RxUnicastFramesOK +
310 pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
311
312 ns->tx_bytes = pstats->TxOctetsOK;
313 ns->rx_bytes = pstats->RxOctetsOK;
314
315 ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
316 pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
317 ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
318 pstats->RxFCSErrors + pstats->RxAlignErrors +
319 pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
320 pstats->RxSymbolErrors + pstats->RxRuntErrors;
321
322 ns->multicast = pstats->RxMulticastFramesOK;
323 ns->collisions = pstats->TxTotalCollisions;
324
325 /* detailed rx_errors */
326 ns->rx_length_errors = pstats->RxFrameTooLongErrors +
327 pstats->RxJabberErrors;
328 ns->rx_over_errors = 0;
329 ns->rx_crc_errors = pstats->RxFCSErrors;
330 ns->rx_frame_errors = pstats->RxAlignErrors;
331 ns->rx_fifo_errors = 0;
332 ns->rx_missed_errors = 0;
333
334 /* detailed tx_errors */
335 ns->tx_aborted_errors = pstats->TxFramesAbortedDueToXSCollisions;
336 ns->tx_carrier_errors = 0;
337 ns->tx_fifo_errors = pstats->TxUnderrun;
338 ns->tx_heartbeat_errors = 0;
339 ns->tx_window_errors = pstats->TxLateCollisions;
340 return ns;
341}
342
343static u32 get_msglevel(struct net_device *dev)
344{
Wang Chenc3ccc122008-11-16 23:06:39 -0800345 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800346
347 return adapter->msg_enable;
348}
349
350static void set_msglevel(struct net_device *dev, u32 val)
351{
Wang Chenc3ccc122008-11-16 23:06:39 -0800352 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800353
354 adapter->msg_enable = val;
355}
356
357static char stats_strings[][ETH_GSTRING_LEN] = {
Stephen Hemminger20578152006-11-17 11:21:22 -0800358 "TxOctetsOK",
359 "TxOctetsBad",
360 "TxUnicastFramesOK",
361 "TxMulticastFramesOK",
362 "TxBroadcastFramesOK",
363 "TxPauseFrames",
364 "TxFramesWithDeferredXmissions",
365 "TxLateCollisions",
366 "TxTotalCollisions",
367 "TxFramesAbortedDueToXSCollisions",
368 "TxUnderrun",
369 "TxLengthErrors",
370 "TxInternalMACXmitError",
371 "TxFramesWithExcessiveDeferral",
372 "TxFCSErrors",
Divy Le Raye0348b92007-11-27 13:30:20 -0800373 "TxJumboFramesOk",
374 "TxJumboOctetsOk",
375
Stephen Hemminger20578152006-11-17 11:21:22 -0800376 "RxOctetsOK",
377 "RxOctetsBad",
378 "RxUnicastFramesOK",
379 "RxMulticastFramesOK",
380 "RxBroadcastFramesOK",
381 "RxPauseFrames",
382 "RxFCSErrors",
383 "RxAlignErrors",
384 "RxSymbolErrors",
385 "RxDataErrors",
386 "RxSequenceErrors",
387 "RxRuntErrors",
388 "RxJabberErrors",
389 "RxInternalMACRcvError",
390 "RxInRangeLengthErrors",
391 "RxOutOfRangeLengthField",
392 "RxFrameTooLongErrors",
Divy Le Raye0348b92007-11-27 13:30:20 -0800393 "RxJumboFramesOk",
394 "RxJumboOctetsOk",
Scott Bardone559fb512005-06-23 01:40:19 -0400395
Stephen Hemminger56f643c2006-12-01 16:36:21 -0800396 /* Port stats */
Scott Bardone559fb512005-06-23 01:40:19 -0400397 "RxCsumGood",
398 "TxCsumOffload",
Stephen Hemminger56f643c2006-12-01 16:36:21 -0800399 "TxTso",
400 "RxVlan",
401 "TxVlan",
Divy Le Ray7832ee02007-11-27 13:30:09 -0800402 "TxNeedHeadroom",
403
Stephen Hemminger56f643c2006-12-01 16:36:21 -0800404 /* Interrupt stats */
405 "rx drops",
406 "pure_rsps",
407 "unhandled irqs",
Scott Bardone559fb512005-06-23 01:40:19 -0400408 "respQ_empty",
409 "respQ_overflow",
410 "freelistQ_empty",
411 "pkt_too_big",
412 "pkt_mismatch",
413 "cmdQ_full0",
414 "cmdQ_full1",
Stephen Hemminger20578152006-11-17 11:21:22 -0800415
Scott Bardone559fb512005-06-23 01:40:19 -0400416 "espi_DIP2ParityErr",
417 "espi_DIP4Err",
418 "espi_RxDrops",
419 "espi_TxDrops",
420 "espi_RxOvfl",
421 "espi_ParityErr"
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800422};
Stephen Hemminger20578152006-11-17 11:21:22 -0800423
Scott Bardone559fb512005-06-23 01:40:19 -0400424#define T2_REGMAP_SIZE (3 * 1024)
425
426static int get_regs_len(struct net_device *dev)
427{
428 return T2_REGMAP_SIZE;
429}
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800430
431static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
432{
Wang Chenc3ccc122008-11-16 23:06:39 -0800433 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800434
Rick Jones23020ab2011-11-09 09:58:07 +0000435 strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
436 strlcpy(info->version, DRV_VERSION, sizeof(info->version));
Rick Jones23020ab2011-11-09 09:58:07 +0000437 strlcpy(info->bus_info, pci_name(adapter->pdev),
438 sizeof(info->bus_info));
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800439}
440
Jeff Garzikb9f2c042007-10-03 18:07:32 -0700441static int get_sset_count(struct net_device *dev, int sset)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800442{
Jeff Garzikb9f2c042007-10-03 18:07:32 -0700443 switch (sset) {
444 case ETH_SS_STATS:
445 return ARRAY_SIZE(stats_strings);
446 default:
447 return -EOPNOTSUPP;
448 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800449}
450
451static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
452{
453 if (stringset == ETH_SS_STATS)
454 memcpy(data, stats_strings, sizeof(stats_strings));
455}
456
457static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
458 u64 *data)
459{
Wang Chenc3ccc122008-11-16 23:06:39 -0800460 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800461 struct cmac *mac = adapter->port[dev->if_port].mac;
462 const struct cmac_statistics *s;
Scott Bardone559fb512005-06-23 01:40:19 -0400463 const struct sge_intr_counts *t;
Stephen Hemminger56f643c2006-12-01 16:36:21 -0800464 struct sge_port_stats ss;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800465
466 s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
Scott Bardone559fb512005-06-23 01:40:19 -0400467 t = t1_sge_get_intr_counts(adapter->sge);
Divy Le Raye0348b92007-11-27 13:30:20 -0800468 t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss);
469
470 *data++ = s->TxOctetsOK;
471 *data++ = s->TxOctetsBad;
472 *data++ = s->TxUnicastFramesOK;
473 *data++ = s->TxMulticastFramesOK;
474 *data++ = s->TxBroadcastFramesOK;
475 *data++ = s->TxPauseFrames;
476 *data++ = s->TxFramesWithDeferredXmissions;
477 *data++ = s->TxLateCollisions;
478 *data++ = s->TxTotalCollisions;
479 *data++ = s->TxFramesAbortedDueToXSCollisions;
480 *data++ = s->TxUnderrun;
481 *data++ = s->TxLengthErrors;
482 *data++ = s->TxInternalMACXmitError;
483 *data++ = s->TxFramesWithExcessiveDeferral;
484 *data++ = s->TxFCSErrors;
485 *data++ = s->TxJumboFramesOK;
486 *data++ = s->TxJumboOctetsOK;
487
488 *data++ = s->RxOctetsOK;
489 *data++ = s->RxOctetsBad;
490 *data++ = s->RxUnicastFramesOK;
491 *data++ = s->RxMulticastFramesOK;
492 *data++ = s->RxBroadcastFramesOK;
493 *data++ = s->RxPauseFrames;
494 *data++ = s->RxFCSErrors;
495 *data++ = s->RxAlignErrors;
496 *data++ = s->RxSymbolErrors;
497 *data++ = s->RxDataErrors;
498 *data++ = s->RxSequenceErrors;
499 *data++ = s->RxRuntErrors;
500 *data++ = s->RxJabberErrors;
501 *data++ = s->RxInternalMACRcvError;
502 *data++ = s->RxInRangeLengthErrors;
503 *data++ = s->RxOutOfRangeLengthField;
504 *data++ = s->RxFrameTooLongErrors;
505 *data++ = s->RxJumboFramesOK;
506 *data++ = s->RxJumboOctetsOK;
507
508 *data++ = ss.rx_cso_good;
509 *data++ = ss.tx_cso;
510 *data++ = ss.tx_tso;
511 *data++ = ss.vlan_xtract;
512 *data++ = ss.vlan_insert;
513 *data++ = ss.tx_need_hdrroom;
514
Stephen Hemminger56f643c2006-12-01 16:36:21 -0800515 *data++ = t->rx_drops;
516 *data++ = t->pure_rsps;
517 *data++ = t->unhandled_irqs;
518 *data++ = t->respQ_empty;
519 *data++ = t->respQ_overflow;
520 *data++ = t->freelistQ_empty;
521 *data++ = t->pkt_too_big;
522 *data++ = t->pkt_mismatch;
523 *data++ = t->cmdQ_full[0];
524 *data++ = t->cmdQ_full[1];
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800525
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800526 if (adapter->espi) {
527 const struct espi_intr_counts *e;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800528
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800529 e = t1_espi_get_intr_counts(adapter->espi);
Stephen Hemminger56f643c2006-12-01 16:36:21 -0800530 *data++ = e->DIP2_parity_err;
531 *data++ = e->DIP4_err;
532 *data++ = e->rx_drops;
533 *data++ = e->tx_drops;
534 *data++ = e->rx_ovflw;
535 *data++ = e->parity_err;
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800536 }
Scott Bardone559fb512005-06-23 01:40:19 -0400537}
538
539static inline void reg_block_dump(struct adapter *ap, void *buf,
540 unsigned int start, unsigned int end)
541{
542 u32 *p = buf + start;
543
544 for ( ; start <= end; start += sizeof(u32))
545 *p++ = readl(ap->regs + start);
546}
547
548static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
549 void *buf)
550{
Wang Chenc3ccc122008-11-16 23:06:39 -0800551 struct adapter *ap = dev->ml_priv;
Scott Bardone559fb512005-06-23 01:40:19 -0400552
553 /*
554 * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
555 */
556 regs->version = 2;
557
558 memset(buf, 0, T2_REGMAP_SIZE);
559 reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800560 reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE);
561 reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR);
562 reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT);
563 reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE);
564 reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE);
565 reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT);
566 reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL);
567 reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE);
568 reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800569}
570
571static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
572{
Wang Chenc3ccc122008-11-16 23:06:39 -0800573 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800574 struct port_info *p = &adapter->port[dev->if_port];
575
576 cmd->supported = p->link_config.supported;
577 cmd->advertising = p->link_config.advertising;
578
579 if (netif_carrier_ok(dev)) {
David Decotigny70739492011-04-27 18:32:40 +0000580 ethtool_cmd_speed_set(cmd, p->link_config.speed);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800581 cmd->duplex = p->link_config.duplex;
582 } else {
David Decotigny70739492011-04-27 18:32:40 +0000583 ethtool_cmd_speed_set(cmd, -1);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800584 cmd->duplex = -1;
585 }
586
Stephen Hemminger20578152006-11-17 11:21:22 -0800587 cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
Ben Hutchings23c33202009-04-29 08:06:34 +0000588 cmd->phy_address = p->phy->mdio.prtad;
Stephen Hemminger20578152006-11-17 11:21:22 -0800589 cmd->transceiver = XCVR_EXTERNAL;
590 cmd->autoneg = p->link_config.autoneg;
591 cmd->maxtxpkt = 0;
592 cmd->maxrxpkt = 0;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800593 return 0;
594}
595
596static int speed_duplex_to_caps(int speed, int duplex)
597{
598 int cap = 0;
599
600 switch (speed) {
601 case SPEED_10:
602 if (duplex == DUPLEX_FULL)
603 cap = SUPPORTED_10baseT_Full;
604 else
605 cap = SUPPORTED_10baseT_Half;
606 break;
607 case SPEED_100:
608 if (duplex == DUPLEX_FULL)
609 cap = SUPPORTED_100baseT_Full;
610 else
611 cap = SUPPORTED_100baseT_Half;
612 break;
613 case SPEED_1000:
614 if (duplex == DUPLEX_FULL)
615 cap = SUPPORTED_1000baseT_Full;
616 else
617 cap = SUPPORTED_1000baseT_Half;
618 break;
619 case SPEED_10000:
620 if (duplex == DUPLEX_FULL)
621 cap = SUPPORTED_10000baseT_Full;
622 }
623 return cap;
624}
625
626#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
627 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
628 ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
629 ADVERTISED_10000baseT_Full)
630
631static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
632{
Wang Chenc3ccc122008-11-16 23:06:39 -0800633 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800634 struct port_info *p = &adapter->port[dev->if_port];
635 struct link_config *lc = &p->link_config;
636
637 if (!(lc->supported & SUPPORTED_Autoneg))
Scott Bardone559fb512005-06-23 01:40:19 -0400638 return -EOPNOTSUPP; /* can't change speed/duplex */
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800639
640 if (cmd->autoneg == AUTONEG_DISABLE) {
David Decotigny25db0332011-04-27 18:32:39 +0000641 u32 speed = ethtool_cmd_speed(cmd);
642 int cap = speed_duplex_to_caps(speed, cmd->duplex);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800643
David Decotigny25db0332011-04-27 18:32:39 +0000644 if (!(lc->supported & cap) || (speed == SPEED_1000))
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800645 return -EINVAL;
David Decotigny25db0332011-04-27 18:32:39 +0000646 lc->requested_speed = speed;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800647 lc->requested_duplex = cmd->duplex;
648 lc->advertising = 0;
649 } else {
650 cmd->advertising &= ADVERTISED_MASK;
651 if (cmd->advertising & (cmd->advertising - 1))
652 cmd->advertising = lc->supported;
653 cmd->advertising &= lc->supported;
654 if (!cmd->advertising)
655 return -EINVAL;
656 lc->requested_speed = SPEED_INVALID;
657 lc->requested_duplex = DUPLEX_INVALID;
658 lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
659 }
660 lc->autoneg = cmd->autoneg;
661 if (netif_running(dev))
662 t1_link_start(p->phy, p->mac, lc);
663 return 0;
664}
665
666static void get_pauseparam(struct net_device *dev,
667 struct ethtool_pauseparam *epause)
668{
Wang Chenc3ccc122008-11-16 23:06:39 -0800669 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800670 struct port_info *p = &adapter->port[dev->if_port];
671
672 epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
673 epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
674 epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
675}
676
677static int set_pauseparam(struct net_device *dev,
678 struct ethtool_pauseparam *epause)
679{
Wang Chenc3ccc122008-11-16 23:06:39 -0800680 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800681 struct port_info *p = &adapter->port[dev->if_port];
682 struct link_config *lc = &p->link_config;
683
684 if (epause->autoneg == AUTONEG_DISABLE)
685 lc->requested_fc = 0;
686 else if (lc->supported & SUPPORTED_Autoneg)
687 lc->requested_fc = PAUSE_AUTONEG;
688 else
689 return -EINVAL;
690
691 if (epause->rx_pause)
692 lc->requested_fc |= PAUSE_RX;
693 if (epause->tx_pause)
694 lc->requested_fc |= PAUSE_TX;
695 if (lc->autoneg == AUTONEG_ENABLE) {
696 if (netif_running(dev))
697 t1_link_start(p->phy, p->mac, lc);
698 } else {
699 lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
700 if (netif_running(dev))
701 p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
702 lc->fc);
703 }
704 return 0;
705}
706
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800707static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
708{
Wang Chenc3ccc122008-11-16 23:06:39 -0800709 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800710 int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
711
712 e->rx_max_pending = MAX_RX_BUFFERS;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800713 e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
714 e->tx_max_pending = MAX_CMDQ_ENTRIES;
715
716 e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800717 e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
718 e->tx_pending = adapter->params.sge.cmdQ_size[0];
719}
720
721static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
722{
Wang Chenc3ccc122008-11-16 23:06:39 -0800723 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800724 int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
725
726 if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
727 e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
728 e->tx_pending > MAX_CMDQ_ENTRIES ||
729 e->rx_pending < MIN_FL_ENTRIES ||
730 e->rx_jumbo_pending < MIN_FL_ENTRIES ||
731 e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
732 return -EINVAL;
733
734 if (adapter->flags & FULL_INIT_DONE)
Francois Romieu356bd142006-12-11 23:47:00 +0100735 return -EBUSY;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800736
737 adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
738 adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
739 adapter->params.sge.cmdQ_size[0] = e->tx_pending;
740 adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
741 MAX_CMDQ1_ENTRIES : e->tx_pending;
742 return 0;
743}
744
745static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
746{
Wang Chenc3ccc122008-11-16 23:06:39 -0800747 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800748
Stephen Hemminger7fe26a62006-12-08 11:08:33 -0800749 adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
Francois Romieu356bd142006-12-11 23:47:00 +0100750 adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800751 adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800752 t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
753 return 0;
754}
755
756static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
757{
Wang Chenc3ccc122008-11-16 23:06:39 -0800758 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800759
Scott Bardone559fb512005-06-23 01:40:19 -0400760 c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800761 c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
762 c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
763 return 0;
764}
765
766static int get_eeprom_len(struct net_device *dev)
767{
Wang Chenc3ccc122008-11-16 23:06:39 -0800768 struct adapter *adapter = dev->ml_priv;
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800769
Francois Romieu356bd142006-12-11 23:47:00 +0100770 return t1_is_asic(adapter) ? EEPROM_SIZE : 0;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800771}
772
773#define EEPROM_MAGIC(ap) \
774 (PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
775
776static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
777 u8 *data)
778{
779 int i;
780 u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
Wang Chenc3ccc122008-11-16 23:06:39 -0800781 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800782
783 e->magic = EEPROM_MAGIC(adapter);
784 for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
Al Viroac390c602007-12-22 18:56:33 +0000785 t1_seeprom_read(adapter, i, (__le32 *)&buf[i]);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800786 memcpy(data, buf + e->offset, e->len);
787 return 0;
788}
789
Jeff Garzik7282d492006-09-13 14:30:00 -0400790static const struct ethtool_ops t1_ethtool_ops = {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800791 .get_settings = get_settings,
792 .set_settings = set_settings,
793 .get_drvinfo = get_drvinfo,
794 .get_msglevel = get_msglevel,
795 .set_msglevel = set_msglevel,
796 .get_ringparam = get_sge_param,
797 .set_ringparam = set_sge_param,
798 .get_coalesce = get_coalesce,
799 .set_coalesce = set_coalesce,
800 .get_eeprom_len = get_eeprom_len,
801 .get_eeprom = get_eeprom,
802 .get_pauseparam = get_pauseparam,
803 .set_pauseparam = set_pauseparam,
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800804 .get_link = ethtool_op_get_link,
805 .get_strings = get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -0700806 .get_sset_count = get_sset_count,
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800807 .get_ethtool_stats = get_stats,
Scott Bardone559fb512005-06-23 01:40:19 -0400808 .get_regs_len = get_regs_len,
809 .get_regs = get_regs,
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800810};
811
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800812static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
813{
Wang Chenc3ccc122008-11-16 23:06:39 -0800814 struct adapter *adapter = dev->ml_priv;
Ben Hutchings23c33202009-04-29 08:06:34 +0000815 struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800816
Ben Hutchings23c33202009-04-29 08:06:34 +0000817 return mdio_mii_ioctl(mdio, if_mii(req), cmd);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800818}
819
820static int t1_change_mtu(struct net_device *dev, int new_mtu)
821{
822 int ret;
Wang Chenc3ccc122008-11-16 23:06:39 -0800823 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800824 struct cmac *mac = adapter->port[dev->if_port].mac;
825
826 if (!mac->ops->set_mtu)
Francois Romieu356bd142006-12-11 23:47:00 +0100827 return -EOPNOTSUPP;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800828 if (new_mtu < 68)
Francois Romieu356bd142006-12-11 23:47:00 +0100829 return -EINVAL;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800830 if ((ret = mac->ops->set_mtu(mac, new_mtu)))
831 return ret;
832 dev->mtu = new_mtu;
833 return 0;
834}
835
836static int t1_set_mac_addr(struct net_device *dev, void *p)
837{
Wang Chenc3ccc122008-11-16 23:06:39 -0800838 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800839 struct cmac *mac = adapter->port[dev->if_port].mac;
840 struct sockaddr *addr = p;
841
842 if (!mac->ops->macaddress_set)
843 return -EOPNOTSUPP;
844
845 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
846 mac->ops->macaddress_set(mac, dev->dev_addr);
847 return 0;
848}
849
Michał Mirosławc8f44af2011-11-15 15:29:55 +0000850static netdev_features_t t1_fix_features(struct net_device *dev,
851 netdev_features_t features)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800852{
Jiri Pirko133b0852011-07-20 04:54:15 +0000853 /*
854 * Since there is no support for separate rx/tx vlan accel
855 * enable/disable make sure tx flag is always in same state as rx.
856 */
Patrick McHardyf6469682013-04-19 02:04:27 +0000857 if (features & NETIF_F_HW_VLAN_CTAG_RX)
858 features |= NETIF_F_HW_VLAN_CTAG_TX;
Jiri Pirko133b0852011-07-20 04:54:15 +0000859 else
Patrick McHardyf6469682013-04-19 02:04:27 +0000860 features &= ~NETIF_F_HW_VLAN_CTAG_TX;
Jiri Pirko133b0852011-07-20 04:54:15 +0000861
862 return features;
863}
864
Michał Mirosławc8f44af2011-11-15 15:29:55 +0000865static int t1_set_features(struct net_device *dev, netdev_features_t features)
Jiri Pirko133b0852011-07-20 04:54:15 +0000866{
Michał Mirosławc8f44af2011-11-15 15:29:55 +0000867 netdev_features_t changed = dev->features ^ features;
Wang Chenc3ccc122008-11-16 23:06:39 -0800868 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800869
Patrick McHardyf6469682013-04-19 02:04:27 +0000870 if (changed & NETIF_F_HW_VLAN_CTAG_RX)
Jiri Pirko133b0852011-07-20 04:54:15 +0000871 t1_vlan_mode(adapter, features);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800872
Jiri Pirko133b0852011-07-20 04:54:15 +0000873 return 0;
874}
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800875#ifdef CONFIG_NET_POLL_CONTROLLER
876static void t1_netpoll(struct net_device *dev)
877{
Scott Bardone559fb512005-06-23 01:40:19 -0400878 unsigned long flags;
Wang Chenc3ccc122008-11-16 23:06:39 -0800879 struct adapter *adapter = dev->ml_priv;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800880
Scott Bardone559fb512005-06-23 01:40:19 -0400881 local_irq_save(flags);
Stephen Hemminger7fe26a62006-12-08 11:08:33 -0800882 t1_interrupt(adapter->pdev->irq, adapter);
Scott Bardone559fb512005-06-23 01:40:19 -0400883 local_irq_restore(flags);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800884}
885#endif
886
887/*
888 * Periodic accumulation of MAC statistics. This is used only if the MAC
889 * does not have any other way to prevent stats counter overflow.
890 */
David Howellsc4028952006-11-22 14:57:56 +0000891static void mac_stats_task(struct work_struct *work)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800892{
893 int i;
David Howellsc4028952006-11-22 14:57:56 +0000894 struct adapter *adapter =
895 container_of(work, struct adapter, stats_update_task.work);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800896
897 for_each_port(adapter, i) {
898 struct port_info *p = &adapter->port[i];
899
900 if (netif_running(p->dev))
901 p->mac->ops->statistics_update(p->mac,
902 MAC_STATS_UPDATE_FAST);
903 }
904
905 /* Schedule the next statistics update if any port is active. */
906 spin_lock(&adapter->work_lock);
907 if (adapter->open_device_map & PORT_MASK)
908 schedule_mac_stats_update(adapter,
909 adapter->params.stats_update_period);
910 spin_unlock(&adapter->work_lock);
911}
912
913/*
914 * Processes elmer0 external interrupts in process context.
915 */
David Howellsc4028952006-11-22 14:57:56 +0000916static void ext_intr_task(struct work_struct *work)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800917{
David Howellsc4028952006-11-22 14:57:56 +0000918 struct adapter *adapter =
919 container_of(work, struct adapter, ext_intr_handler_task);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800920
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -0800921 t1_elmer0_ext_intr_handler(adapter);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800922
923 /* Now reenable external interrupts */
Scott Bardone559fb512005-06-23 01:40:19 -0400924 spin_lock_irq(&adapter->async_lock);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800925 adapter->slow_intr_mask |= F_PL_INTR_EXT;
Scott Bardone559fb512005-06-23 01:40:19 -0400926 writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
927 writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
Stephen Hemminger20578152006-11-17 11:21:22 -0800928 adapter->regs + A_PL_ENABLE);
Scott Bardone559fb512005-06-23 01:40:19 -0400929 spin_unlock_irq(&adapter->async_lock);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800930}
931
932/*
933 * Interrupt-context handler for elmer0 external interrupts.
934 */
935void t1_elmer0_ext_intr(struct adapter *adapter)
936{
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800937 /*
938 * Schedule a task to handle external interrupts as we require
939 * a process context. We disable EXT interrupts in the interim
940 * and let the task reenable them when it's done.
941 */
942 adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
Scott Bardone559fb512005-06-23 01:40:19 -0400943 writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
Stephen Hemminger20578152006-11-17 11:21:22 -0800944 adapter->regs + A_PL_ENABLE);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800945 schedule_work(&adapter->ext_intr_handler_task);
946}
947
948void t1_fatal_err(struct adapter *adapter)
949{
950 if (adapter->flags & FULL_INIT_DONE) {
951 t1_sge_stop(adapter->sge);
952 t1_interrupts_disable(adapter);
953 }
Joe Perchesc1f51212010-02-22 16:56:57 +0000954 pr_alert("%s: encountered fatal error, operation suspended\n",
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800955 adapter->name);
956}
957
Stephen Hemminger80ff32b2008-11-19 22:17:06 -0800958static const struct net_device_ops cxgb_netdev_ops = {
959 .ndo_open = cxgb_open,
960 .ndo_stop = cxgb_close,
Stephen Hemminger00829822008-11-20 20:14:53 -0800961 .ndo_start_xmit = t1_start_xmit,
Stephen Hemminger80ff32b2008-11-19 22:17:06 -0800962 .ndo_get_stats = t1_get_stats,
963 .ndo_validate_addr = eth_validate_addr,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000964 .ndo_set_rx_mode = t1_set_rxmode,
Stephen Hemminger80ff32b2008-11-19 22:17:06 -0800965 .ndo_do_ioctl = t1_ioctl,
966 .ndo_change_mtu = t1_change_mtu,
967 .ndo_set_mac_address = t1_set_mac_addr,
Jiri Pirko133b0852011-07-20 04:54:15 +0000968 .ndo_fix_features = t1_fix_features,
969 .ndo_set_features = t1_set_features,
Stephen Hemminger80ff32b2008-11-19 22:17:06 -0800970#ifdef CONFIG_NET_POLL_CONTROLLER
971 .ndo_poll_controller = t1_netpoll,
972#endif
973};
974
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +0000975static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800976{
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800977 int i, err, pci_using_dac = 0;
978 unsigned long mmio_start, mmio_len;
979 const struct board_info *bi;
980 struct adapter *adapter = NULL;
981 struct port_info *pi;
982
Joe Perches428ac432013-01-06 13:34:49 +0000983 pr_info_once("%s - version %s\n", DRV_DESCRIPTION, DRV_VERSION);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800984
985 err = pci_enable_device(pdev);
986 if (err)
Stephen Hemminger20578152006-11-17 11:21:22 -0800987 return err;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800988
989 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
Joe Perchesc1f51212010-02-22 16:56:57 +0000990 pr_err("%s: cannot find PCI device memory base address\n",
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800991 pci_name(pdev));
992 err = -ENODEV;
993 goto out_disable_pdev;
994 }
995
Yang Hongyang6a355282009-04-06 19:01:13 -0700996 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800997 pci_using_dac = 1;
Scott Bardone559fb512005-06-23 01:40:19 -0400998
Yang Hongyang6a355282009-04-06 19:01:13 -0700999 if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
Joe Perchesc1f51212010-02-22 16:56:57 +00001000 pr_err("%s: unable to obtain 64-bit DMA for "
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001001 "consistent allocations\n", pci_name(pdev));
1002 err = -ENODEV;
1003 goto out_disable_pdev;
1004 }
Scott Bardone559fb512005-06-23 01:40:19 -04001005
Yang Hongyang284901a2009-04-06 19:01:15 -07001006 } else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
Joe Perchesc1f51212010-02-22 16:56:57 +00001007 pr_err("%s: no usable DMA configuration\n", pci_name(pdev));
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001008 goto out_disable_pdev;
1009 }
1010
Scott Bardone559fb512005-06-23 01:40:19 -04001011 err = pci_request_regions(pdev, DRV_NAME);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001012 if (err) {
Joe Perchesc1f51212010-02-22 16:56:57 +00001013 pr_err("%s: cannot obtain PCI resources\n", pci_name(pdev));
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001014 goto out_disable_pdev;
1015 }
1016
1017 pci_set_master(pdev);
1018
Stephen Hemminger20578152006-11-17 11:21:22 -08001019 mmio_start = pci_resource_start(pdev, 0);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001020 mmio_len = pci_resource_len(pdev, 0);
1021 bi = t1_get_board_info(ent->driver_data);
1022
1023 for (i = 0; i < bi->port_number; ++i) {
1024 struct net_device *netdev;
1025
1026 netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
1027 if (!netdev) {
1028 err = -ENOMEM;
1029 goto out_free_dev;
1030 }
1031
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001032 SET_NETDEV_DEV(netdev, &pdev->dev);
1033
1034 if (!adapter) {
Wang Chenc3ccc122008-11-16 23:06:39 -08001035 adapter = netdev_priv(netdev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001036 adapter->pdev = pdev;
1037 adapter->port[0].dev = netdev; /* so we don't leak it */
1038
1039 adapter->regs = ioremap(mmio_start, mmio_len);
1040 if (!adapter->regs) {
Joe Perchesc1f51212010-02-22 16:56:57 +00001041 pr_err("%s: cannot map device registers\n",
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001042 pci_name(pdev));
1043 err = -ENOMEM;
1044 goto out_free_dev;
1045 }
1046
1047 if (t1_get_board_rev(adapter, bi, &adapter->params)) {
1048 err = -ENODEV; /* Can't handle this chip rev */
1049 goto out_free_dev;
1050 }
1051
1052 adapter->name = pci_name(pdev);
1053 adapter->msg_enable = dflt_msg_enable;
1054 adapter->mmio_len = mmio_len;
1055
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001056 spin_lock_init(&adapter->tpi_lock);
1057 spin_lock_init(&adapter->work_lock);
1058 spin_lock_init(&adapter->async_lock);
Stephen Hemminger352c4172006-12-01 16:36:17 -08001059 spin_lock_init(&adapter->mac_lock);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001060
1061 INIT_WORK(&adapter->ext_intr_handler_task,
David Howellsc4028952006-11-22 14:57:56 +00001062 ext_intr_task);
1063 INIT_DELAYED_WORK(&adapter->stats_update_task,
1064 mac_stats_task);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001065
1066 pci_set_drvdata(pdev, netdev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001067 }
1068
1069 pi = &adapter->port[i];
1070 pi->dev = netdev;
1071 netif_carrier_off(netdev);
1072 netdev->irq = pdev->irq;
1073 netdev->if_port = i;
1074 netdev->mem_start = mmio_start;
1075 netdev->mem_end = mmio_start + mmio_len - 1;
Wang Chenc3ccc122008-11-16 23:06:39 -08001076 netdev->ml_priv = adapter;
Michał Mirosław30f554f2011-04-18 13:31:20 +00001077 netdev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
1078 NETIF_F_RXCSUM;
1079 netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
1080 NETIF_F_RXCSUM | NETIF_F_LLTX;
Scott Bardone559fb512005-06-23 01:40:19 -04001081
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001082 if (pci_using_dac)
1083 netdev->features |= NETIF_F_HIGHDMA;
1084 if (vlan_tso_capable(adapter)) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001085 netdev->features |=
Patrick McHardyf6469682013-04-19 02:04:27 +00001086 NETIF_F_HW_VLAN_CTAG_TX |
1087 NETIF_F_HW_VLAN_CTAG_RX;
1088 netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001089
1090 /* T204: disable TSO */
1091 if (!(is_T2(adapter)) || bi->port_number != 4) {
Michał Mirosław30f554f2011-04-18 13:31:20 +00001092 netdev->hw_features |= NETIF_F_TSO;
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001093 netdev->features |= NETIF_F_TSO;
1094 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001095 }
1096
Stephen Hemminger80ff32b2008-11-19 22:17:06 -08001097 netdev->netdev_ops = &cxgb_netdev_ops;
Michał Mirosław30f554f2011-04-18 13:31:20 +00001098 netdev->hard_header_len += (netdev->hw_features & NETIF_F_TSO) ?
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001099 sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
Stephen Hemminger80ff32b2008-11-19 22:17:06 -08001100
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001101 netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001102
Stephen Hemminger20578152006-11-17 11:21:22 -08001103 SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001104 }
1105
1106 if (t1_init_sw_modules(adapter, bi) < 0) {
1107 err = -ENODEV;
1108 goto out_free_dev;
1109 }
1110
1111 /*
1112 * The card is now ready to go. If any errors occur during device
1113 * registration we do not fail the whole card but rather proceed only
1114 * with the ports we manage to register successfully. However we must
1115 * register at least one net device.
1116 */
1117 for (i = 0; i < bi->port_number; ++i) {
1118 err = register_netdev(adapter->port[i].dev);
1119 if (err)
Joe Perches428ac432013-01-06 13:34:49 +00001120 pr_warn("%s: cannot register net device %s, skipping\n",
1121 pci_name(pdev), adapter->port[i].dev->name);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001122 else {
1123 /*
1124 * Change the name we use for messages to the name of
1125 * the first successfully registered interface.
1126 */
1127 if (!adapter->registered_device_map)
1128 adapter->name = adapter->port[i].dev->name;
1129
Stephen Hemminger20578152006-11-17 11:21:22 -08001130 __set_bit(i, &adapter->registered_device_map);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001131 }
1132 }
1133 if (!adapter->registered_device_map) {
Joe Perchesc1f51212010-02-22 16:56:57 +00001134 pr_err("%s: could not register any net devices\n",
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001135 pci_name(pdev));
1136 goto out_release_adapter_res;
1137 }
1138
Joe Perches428ac432013-01-06 13:34:49 +00001139 pr_info("%s: %s (rev %d), %s %dMHz/%d-bit\n",
1140 adapter->name, bi->desc, adapter->params.chip_revision,
1141 adapter->params.pci.is_pcix ? "PCIX" : "PCI",
1142 adapter->params.pci.speed, adapter->params.pci.width);
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001143
1144 /*
1145 * Set the T1B ASIC and memory clocks.
1146 */
1147 if (t1powersave)
1148 adapter->t1powersave = LCLOCK; /* HW default is powersave mode. */
1149 else
1150 adapter->t1powersave = HCLOCK;
1151 if (t1_is_T1B(adapter))
1152 t1_clock(adapter, t1powersave);
1153
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001154 return 0;
1155
Francois Romieu356bd142006-12-11 23:47:00 +01001156out_release_adapter_res:
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001157 t1_free_sw_modules(adapter);
Francois Romieu356bd142006-12-11 23:47:00 +01001158out_free_dev:
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001159 if (adapter) {
Stephen Hemmingere4876472006-11-17 11:25:23 -08001160 if (adapter->regs)
1161 iounmap(adapter->regs);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001162 for (i = bi->port_number - 1; i >= 0; --i)
Stephen Hemmingere4876472006-11-17 11:25:23 -08001163 if (adapter->port[i].dev)
1164 free_netdev(adapter->port[i].dev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001165 }
1166 pci_release_regions(pdev);
Francois Romieu356bd142006-12-11 23:47:00 +01001167out_disable_pdev:
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001168 pci_disable_device(pdev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001169 return err;
1170}
1171
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001172static void bit_bang(struct adapter *adapter, int bitdata, int nbits)
1173{
1174 int data;
1175 int i;
1176 u32 val;
1177
1178 enum {
1179 S_CLOCK = 1 << 3,
1180 S_DATA = 1 << 4
1181 };
1182
1183 for (i = (nbits - 1); i > -1; i--) {
1184
1185 udelay(50);
1186
1187 data = ((bitdata >> i) & 0x1);
1188 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1189
1190 if (data)
1191 val |= S_DATA;
1192 else
1193 val &= ~S_DATA;
1194
1195 udelay(50);
1196
1197 /* Set SCLOCK low */
1198 val &= ~S_CLOCK;
1199 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1200
1201 udelay(50);
1202
1203 /* Write SCLOCK high */
1204 val |= S_CLOCK;
1205 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1206
1207 }
1208}
1209
1210static int t1_clock(struct adapter *adapter, int mode)
1211{
1212 u32 val;
1213 int M_CORE_VAL;
1214 int M_MEM_VAL;
1215
1216 enum {
Francois Romieu356bd142006-12-11 23:47:00 +01001217 M_CORE_BITS = 9,
1218 T_CORE_VAL = 0,
1219 T_CORE_BITS = 2,
1220 N_CORE_VAL = 0,
1221 N_CORE_BITS = 2,
1222 M_MEM_BITS = 9,
1223 T_MEM_VAL = 0,
1224 T_MEM_BITS = 2,
1225 N_MEM_VAL = 0,
1226 N_MEM_BITS = 2,
1227 NP_LOAD = 1 << 17,
1228 S_LOAD_MEM = 1 << 5,
1229 S_LOAD_CORE = 1 << 6,
1230 S_CLOCK = 1 << 3
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001231 };
1232
1233 if (!t1_is_T1B(adapter))
1234 return -ENODEV; /* Can't re-clock this chip. */
1235
Francois Romieud7487422006-12-11 23:49:13 +01001236 if (mode & 2)
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001237 return 0; /* show current mode. */
Stephen Hemmingerf1d3d382006-12-01 16:36:16 -08001238
1239 if ((adapter->t1powersave & 1) == (mode & 1))
1240 return -EALREADY; /* ASIC already running in mode. */
1241
1242 if ((mode & 1) == HCLOCK) {
1243 M_CORE_VAL = 0x14;
1244 M_MEM_VAL = 0x18;
1245 adapter->t1powersave = HCLOCK; /* overclock */
1246 } else {
1247 M_CORE_VAL = 0xe;
1248 M_MEM_VAL = 0x10;
1249 adapter->t1powersave = LCLOCK; /* underclock */
1250 }
1251
1252 /* Don't interrupt this serial stream! */
1253 spin_lock(&adapter->tpi_lock);
1254
1255 /* Initialize for ASIC core */
1256 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1257 val |= NP_LOAD;
1258 udelay(50);
1259 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1260 udelay(50);
1261 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1262 val &= ~S_LOAD_CORE;
1263 val &= ~S_CLOCK;
1264 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1265 udelay(50);
1266
1267 /* Serial program the ASIC clock synthesizer */
1268 bit_bang(adapter, T_CORE_VAL, T_CORE_BITS);
1269 bit_bang(adapter, N_CORE_VAL, N_CORE_BITS);
1270 bit_bang(adapter, M_CORE_VAL, M_CORE_BITS);
1271 udelay(50);
1272
1273 /* Finish ASIC core */
1274 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1275 val |= S_LOAD_CORE;
1276 udelay(50);
1277 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1278 udelay(50);
1279 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1280 val &= ~S_LOAD_CORE;
1281 udelay(50);
1282 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1283 udelay(50);
1284
1285 /* Initialize for memory */
1286 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1287 val |= NP_LOAD;
1288 udelay(50);
1289 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1290 udelay(50);
1291 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1292 val &= ~S_LOAD_MEM;
1293 val &= ~S_CLOCK;
1294 udelay(50);
1295 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1296 udelay(50);
1297
1298 /* Serial program the memory clock synthesizer */
1299 bit_bang(adapter, T_MEM_VAL, T_MEM_BITS);
1300 bit_bang(adapter, N_MEM_VAL, N_MEM_BITS);
1301 bit_bang(adapter, M_MEM_VAL, M_MEM_BITS);
1302 udelay(50);
1303
1304 /* Finish memory */
1305 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1306 val |= S_LOAD_MEM;
1307 udelay(50);
1308 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1309 udelay(50);
1310 __t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1311 val &= ~S_LOAD_MEM;
1312 udelay(50);
1313 __t1_tpi_write(adapter, A_ELMER0_GPO, val);
1314
1315 spin_unlock(&adapter->tpi_lock);
1316
1317 return 0;
1318}
1319
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001320static inline void t1_sw_reset(struct pci_dev *pdev)
1321{
1322 pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
1323 pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
1324}
1325
Bill Pembertonff76a3c2012-12-03 09:23:04 -05001326static void remove_one(struct pci_dev *pdev)
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001327{
1328 struct net_device *dev = pci_get_drvdata(pdev);
Wang Chenc3ccc122008-11-16 23:06:39 -08001329 struct adapter *adapter = dev->ml_priv;
Francois Romieu47cbe6f2006-12-05 23:19:06 +01001330 int i;
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001331
Francois Romieu47cbe6f2006-12-05 23:19:06 +01001332 for_each_port(adapter, i) {
1333 if (test_bit(i, &adapter->registered_device_map))
1334 unregister_netdev(adapter->port[i].dev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001335 }
Francois Romieu47cbe6f2006-12-05 23:19:06 +01001336
1337 t1_free_sw_modules(adapter);
1338 iounmap(adapter->regs);
1339
1340 while (--i >= 0) {
1341 if (adapter->port[i].dev)
1342 free_netdev(adapter->port[i].dev);
1343 }
1344
1345 pci_release_regions(pdev);
1346 pci_disable_device(pdev);
Francois Romieu47cbe6f2006-12-05 23:19:06 +01001347 t1_sw_reset(pdev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001348}
1349
Peter Hüwe65c21912013-05-21 13:42:55 +00001350static struct pci_driver cxgb_pci_driver = {
Scott Bardone559fb512005-06-23 01:40:19 -04001351 .name = DRV_NAME,
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001352 .id_table = t1_pci_tbl,
1353 .probe = init_one,
Bill Pembertonff76a3c2012-12-03 09:23:04 -05001354 .remove = remove_one,
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001355};
1356
Peter Hüwe65c21912013-05-21 13:42:55 +00001357module_pci_driver(cxgb_pci_driver);