blob: 3309bfc774e04c3eba927a0776232b24c7bb9a47 [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 *
14 * with this program; if not, write to the Free Software Foundation, Inc., *
15 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
16 * *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED *
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
20 * *
21 * http://www.chelsio.com *
22 * *
23 * Copyright (c) 2003 - 2005 Chelsio Communications, Inc. *
24 * All rights reserved. *
25 * *
26 * Maintainers: maintainers@chelsio.com *
27 * *
28 * Authors: Dimitrios Michailidis <dm@chelsio.com> *
29 * Tina Yang <tainay@chelsio.com> *
30 * Felix Marti <felix@chelsio.com> *
31 * Scott Bardone <sbardone@chelsio.com> *
32 * Kurt Ottaway <kottaway@chelsio.com> *
33 * Frank DiMambro <frank@chelsio.com> *
34 * *
35 * History: *
36 * *
37 ****************************************************************************/
38
39#include "common.h"
Christoph Lameter8199d3a2005-03-30 13:34:31 -080040#include <linux/module.h>
41#include <linux/init.h>
42#include <linux/pci.h>
43#include <linux/netdevice.h>
44#include <linux/etherdevice.h>
45#include <linux/if_vlan.h>
46#include <linux/mii.h>
47#include <linux/sockios.h>
48#include <linux/proc_fs.h>
Scott Bardone559fb512005-06-23 01:40:19 -040049#include <linux/dma-mapping.h>
Christoph Lameter8199d3a2005-03-30 13:34:31 -080050#include <asm/uaccess.h>
51
Christoph Lameter8199d3a2005-03-30 13:34:31 -080052#include "cpl5_cmd.h"
53#include "regs.h"
54#include "gmac.h"
55#include "cphy.h"
56#include "sge.h"
Christoph Lameter8199d3a2005-03-30 13:34:31 -080057#include "espi.h"
58
Scott Bardone559fb512005-06-23 01:40:19 -040059#include <linux/workqueue.h>
60
Christoph Lameter8199d3a2005-03-30 13:34:31 -080061static inline void schedule_mac_stats_update(struct adapter *ap, int secs)
62{
63 schedule_delayed_work(&ap->stats_update_task, secs * HZ);
64}
65
66static inline void cancel_mac_stats_update(struct adapter *ap)
67{
68 cancel_delayed_work(&ap->stats_update_task);
69}
Christoph Lameter8199d3a2005-03-30 13:34:31 -080070
Christoph Lameter8199d3a2005-03-30 13:34:31 -080071#define MAX_CMDQ_ENTRIES 16384
72#define MAX_CMDQ1_ENTRIES 1024
73#define MAX_RX_BUFFERS 16384
74#define MAX_RX_JUMBO_BUFFERS 16384
75#define MAX_TX_BUFFERS_HIGH 16384U
76#define MAX_TX_BUFFERS_LOW 1536U
77#define MIN_FL_ENTRIES 32
78
79#define PORT_MASK ((1 << MAX_NPORTS) - 1)
80
81#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
82 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
83 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
84
85/*
86 * The EEPROM is actually bigger but only the first few bytes are used so we
87 * only report those.
88 */
89#define EEPROM_SIZE 32
90
Scott Bardone559fb512005-06-23 01:40:19 -040091MODULE_DESCRIPTION(DRV_DESCRIPTION);
Christoph Lameter8199d3a2005-03-30 13:34:31 -080092MODULE_AUTHOR("Chelsio Communications");
93MODULE_LICENSE("GPL");
Christoph Lameter8199d3a2005-03-30 13:34:31 -080094
95static int dflt_msg_enable = DFLT_MSG_ENABLE;
96
Rusty Russell8d3b33f2006-03-25 03:07:05 -080097module_param(dflt_msg_enable, int, 0);
Christoph Lameter8199d3a2005-03-30 13:34:31 -080098MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap");
99
100
101static const char pci_speed[][4] = {
102 "33", "66", "100", "133"
103};
104
105/*
106 * Setup MAC to receive the types of packets we want.
107 */
108static void t1_set_rxmode(struct net_device *dev)
109{
110 struct adapter *adapter = dev->priv;
111 struct cmac *mac = adapter->port[dev->if_port].mac;
112 struct t1_rx_mode rm;
113
114 rm.dev = dev;
115 rm.idx = 0;
116 rm.list = dev->mc_list;
117 mac->ops->set_rx_mode(mac, &rm);
118}
119
120static void link_report(struct port_info *p)
121{
122 if (!netif_carrier_ok(p->dev))
Stephen Hemminger20578152006-11-17 11:21:22 -0800123 printk(KERN_INFO "%s: link down\n", p->dev->name);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800124 else {
Scott Bardone559fb512005-06-23 01:40:19 -0400125 const char *s = "10Mbps";
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800126
127 switch (p->link_config.speed) {
Scott Bardone559fb512005-06-23 01:40:19 -0400128 case SPEED_10000: s = "10Gbps"; break;
129 case SPEED_1000: s = "1000Mbps"; break;
130 case SPEED_100: s = "100Mbps"; break;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800131 }
132
Stephen Hemminger20578152006-11-17 11:21:22 -0800133 printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800134 p->dev->name, s,
135 p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
136 }
137}
138
139void t1_link_changed(struct adapter *adapter, int port_id, int link_stat,
140 int speed, int duplex, int pause)
141{
142 struct port_info *p = &adapter->port[port_id];
143
144 if (link_stat != netif_carrier_ok(p->dev)) {
145 if (link_stat)
146 netif_carrier_on(p->dev);
147 else
148 netif_carrier_off(p->dev);
149 link_report(p);
150
151 }
152}
153
154static void link_start(struct port_info *p)
155{
156 struct cmac *mac = p->mac;
157
158 mac->ops->reset(mac);
159 if (mac->ops->macaddress_set)
160 mac->ops->macaddress_set(mac, p->dev->dev_addr);
161 t1_set_rxmode(p->dev);
162 t1_link_start(p->phy, mac, &p->link_config);
163 mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
164}
165
166static void enable_hw_csum(struct adapter *adapter)
167{
168 if (adapter->flags & TSO_CAPABLE)
Scott Bardone559fb512005-06-23 01:40:19 -0400169 t1_tp_set_ip_checksum_offload(adapter, 1); /* for TSO only */
170 t1_tp_set_tcp_checksum_offload(adapter, 1);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800171}
172
173/*
174 * Things to do upon first use of a card.
175 * This must run with the rtnl lock held.
176 */
177static int cxgb_up(struct adapter *adapter)
178{
179 int err = 0;
180
181 if (!(adapter->flags & FULL_INIT_DONE)) {
182 err = t1_init_hw_modules(adapter);
183 if (err)
184 goto out_err;
185
186 enable_hw_csum(adapter);
187 adapter->flags |= FULL_INIT_DONE;
188 }
189
190 t1_interrupts_clear(adapter);
Scott Bardone559fb512005-06-23 01:40:19 -0400191 if ((err = request_irq(adapter->pdev->irq,
Thomas Gleixner1fb9df52006-07-01 19:29:39 -0700192 t1_select_intr_handler(adapter), IRQF_SHARED,
Scott Bardone559fb512005-06-23 01:40:19 -0400193 adapter->name, adapter))) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800194 goto out_err;
Scott Bardone559fb512005-06-23 01:40:19 -0400195 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800196 t1_sge_start(adapter->sge);
197 t1_interrupts_enable(adapter);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800198 out_err:
199 return err;
200}
201
202/*
203 * Release resources when all the ports have been stopped.
204 */
205static void cxgb_down(struct adapter *adapter)
206{
207 t1_sge_stop(adapter->sge);
208 t1_interrupts_disable(adapter);
209 free_irq(adapter->pdev->irq, adapter);
210}
211
212static int cxgb_open(struct net_device *dev)
213{
214 int err;
215 struct adapter *adapter = dev->priv;
216 int other_ports = adapter->open_device_map & PORT_MASK;
217
218 if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0)
219 return err;
220
221 __set_bit(dev->if_port, &adapter->open_device_map);
222 link_start(&adapter->port[dev->if_port]);
223 netif_start_queue(dev);
224 if (!other_ports && adapter->params.stats_update_period)
225 schedule_mac_stats_update(adapter,
226 adapter->params.stats_update_period);
227 return 0;
228}
229
230static int cxgb_close(struct net_device *dev)
231{
232 struct adapter *adapter = dev->priv;
233 struct port_info *p = &adapter->port[dev->if_port];
234 struct cmac *mac = p->mac;
235
236 netif_stop_queue(dev);
237 mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
238 netif_carrier_off(dev);
239
240 clear_bit(dev->if_port, &adapter->open_device_map);
241 if (adapter->params.stats_update_period &&
242 !(adapter->open_device_map & PORT_MASK)) {
243 /* Stop statistics accumulation. */
244 smp_mb__after_clear_bit();
245 spin_lock(&adapter->work_lock); /* sync with update task */
246 spin_unlock(&adapter->work_lock);
247 cancel_mac_stats_update(adapter);
248 }
249
250 if (!adapter->open_device_map)
251 cxgb_down(adapter);
252 return 0;
253}
254
255static struct net_device_stats *t1_get_stats(struct net_device *dev)
256{
257 struct adapter *adapter = dev->priv;
258 struct port_info *p = &adapter->port[dev->if_port];
259 struct net_device_stats *ns = &p->netstats;
260 const struct cmac_statistics *pstats;
261
262 /* Do a full update of the MAC stats */
263 pstats = p->mac->ops->statistics_update(p->mac,
Stephen Hemminger20578152006-11-17 11:21:22 -0800264 MAC_STATS_UPDATE_FULL);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800265
266 ns->tx_packets = pstats->TxUnicastFramesOK +
267 pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
268
269 ns->rx_packets = pstats->RxUnicastFramesOK +
270 pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
271
272 ns->tx_bytes = pstats->TxOctetsOK;
273 ns->rx_bytes = pstats->RxOctetsOK;
274
275 ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
276 pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
277 ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
278 pstats->RxFCSErrors + pstats->RxAlignErrors +
279 pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
280 pstats->RxSymbolErrors + pstats->RxRuntErrors;
281
282 ns->multicast = pstats->RxMulticastFramesOK;
283 ns->collisions = pstats->TxTotalCollisions;
284
285 /* detailed rx_errors */
286 ns->rx_length_errors = pstats->RxFrameTooLongErrors +
287 pstats->RxJabberErrors;
288 ns->rx_over_errors = 0;
289 ns->rx_crc_errors = pstats->RxFCSErrors;
290 ns->rx_frame_errors = pstats->RxAlignErrors;
291 ns->rx_fifo_errors = 0;
292 ns->rx_missed_errors = 0;
293
294 /* detailed tx_errors */
295 ns->tx_aborted_errors = pstats->TxFramesAbortedDueToXSCollisions;
296 ns->tx_carrier_errors = 0;
297 ns->tx_fifo_errors = pstats->TxUnderrun;
298 ns->tx_heartbeat_errors = 0;
299 ns->tx_window_errors = pstats->TxLateCollisions;
300 return ns;
301}
302
303static u32 get_msglevel(struct net_device *dev)
304{
305 struct adapter *adapter = dev->priv;
306
307 return adapter->msg_enable;
308}
309
310static void set_msglevel(struct net_device *dev, u32 val)
311{
312 struct adapter *adapter = dev->priv;
313
314 adapter->msg_enable = val;
315}
316
317static char stats_strings[][ETH_GSTRING_LEN] = {
Stephen Hemminger20578152006-11-17 11:21:22 -0800318 "TxOctetsOK",
319 "TxOctetsBad",
320 "TxUnicastFramesOK",
321 "TxMulticastFramesOK",
322 "TxBroadcastFramesOK",
323 "TxPauseFrames",
324 "TxFramesWithDeferredXmissions",
325 "TxLateCollisions",
326 "TxTotalCollisions",
327 "TxFramesAbortedDueToXSCollisions",
328 "TxUnderrun",
329 "TxLengthErrors",
330 "TxInternalMACXmitError",
331 "TxFramesWithExcessiveDeferral",
332 "TxFCSErrors",
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800333
Stephen Hemminger20578152006-11-17 11:21:22 -0800334 "RxOctetsOK",
335 "RxOctetsBad",
336 "RxUnicastFramesOK",
337 "RxMulticastFramesOK",
338 "RxBroadcastFramesOK",
339 "RxPauseFrames",
340 "RxFCSErrors",
341 "RxAlignErrors",
342 "RxSymbolErrors",
343 "RxDataErrors",
344 "RxSequenceErrors",
345 "RxRuntErrors",
346 "RxJabberErrors",
347 "RxInternalMACRcvError",
348 "RxInRangeLengthErrors",
349 "RxOutOfRangeLengthField",
350 "RxFrameTooLongErrors",
Scott Bardone559fb512005-06-23 01:40:19 -0400351
352 "TSO",
353 "VLANextractions",
354 "VLANinsertions",
355 "RxCsumGood",
356 "TxCsumOffload",
357 "RxDrops"
358
359 "respQ_empty",
360 "respQ_overflow",
361 "freelistQ_empty",
362 "pkt_too_big",
363 "pkt_mismatch",
364 "cmdQ_full0",
365 "cmdQ_full1",
366 "tx_ipfrags",
367 "tx_reg_pkts",
368 "tx_lso_pkts",
369 "tx_do_cksum",
Stephen Hemminger20578152006-11-17 11:21:22 -0800370
Scott Bardone559fb512005-06-23 01:40:19 -0400371 "espi_DIP2ParityErr",
372 "espi_DIP4Err",
373 "espi_RxDrops",
374 "espi_TxDrops",
375 "espi_RxOvfl",
376 "espi_ParityErr"
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800377};
Stephen Hemminger20578152006-11-17 11:21:22 -0800378
Scott Bardone559fb512005-06-23 01:40:19 -0400379#define T2_REGMAP_SIZE (3 * 1024)
380
381static int get_regs_len(struct net_device *dev)
382{
383 return T2_REGMAP_SIZE;
384}
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800385
386static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
387{
388 struct adapter *adapter = dev->priv;
389
Scott Bardone559fb512005-06-23 01:40:19 -0400390 strcpy(info->driver, DRV_NAME);
391 strcpy(info->version, DRV_VERSION);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800392 strcpy(info->fw_version, "N/A");
393 strcpy(info->bus_info, pci_name(adapter->pdev));
394}
395
396static int get_stats_count(struct net_device *dev)
397{
398 return ARRAY_SIZE(stats_strings);
399}
400
401static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
402{
403 if (stringset == ETH_SS_STATS)
404 memcpy(data, stats_strings, sizeof(stats_strings));
405}
406
407static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
408 u64 *data)
409{
410 struct adapter *adapter = dev->priv;
411 struct cmac *mac = adapter->port[dev->if_port].mac;
412 const struct cmac_statistics *s;
Scott Bardone559fb512005-06-23 01:40:19 -0400413 const struct sge_port_stats *ss;
414 const struct sge_intr_counts *t;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800415
416 s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
Scott Bardone559fb512005-06-23 01:40:19 -0400417 ss = t1_sge_get_port_stats(adapter->sge, dev->if_port);
418 t = t1_sge_get_intr_counts(adapter->sge);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800419
Stephen Hemminger20578152006-11-17 11:21:22 -0800420 *data++ = s->TxOctetsOK;
421 *data++ = s->TxOctetsBad;
422 *data++ = s->TxUnicastFramesOK;
423 *data++ = s->TxMulticastFramesOK;
424 *data++ = s->TxBroadcastFramesOK;
425 *data++ = s->TxPauseFrames;
426 *data++ = s->TxFramesWithDeferredXmissions;
427 *data++ = s->TxLateCollisions;
428 *data++ = s->TxTotalCollisions;
429 *data++ = s->TxFramesAbortedDueToXSCollisions;
430 *data++ = s->TxUnderrun;
431 *data++ = s->TxLengthErrors;
432 *data++ = s->TxInternalMACXmitError;
433 *data++ = s->TxFramesWithExcessiveDeferral;
434 *data++ = s->TxFCSErrors;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800435
Stephen Hemminger20578152006-11-17 11:21:22 -0800436 *data++ = s->RxOctetsOK;
437 *data++ = s->RxOctetsBad;
438 *data++ = s->RxUnicastFramesOK;
439 *data++ = s->RxMulticastFramesOK;
440 *data++ = s->RxBroadcastFramesOK;
441 *data++ = s->RxPauseFrames;
442 *data++ = s->RxFCSErrors;
443 *data++ = s->RxAlignErrors;
444 *data++ = s->RxSymbolErrors;
445 *data++ = s->RxDataErrors;
446 *data++ = s->RxSequenceErrors;
447 *data++ = s->RxRuntErrors;
448 *data++ = s->RxJabberErrors;
449 *data++ = s->RxInternalMACRcvError;
450 *data++ = s->RxInRangeLengthErrors;
451 *data++ = s->RxOutOfRangeLengthField;
452 *data++ = s->RxFrameTooLongErrors;
Scott Bardone559fb512005-06-23 01:40:19 -0400453
454 *data++ = ss->tso;
455 *data++ = ss->vlan_xtract;
456 *data++ = ss->vlan_insert;
457 *data++ = ss->rx_cso_good;
458 *data++ = ss->tx_cso;
459 *data++ = ss->rx_drops;
460
461 *data++ = (u64)t->respQ_empty;
462 *data++ = (u64)t->respQ_overflow;
463 *data++ = (u64)t->freelistQ_empty;
464 *data++ = (u64)t->pkt_too_big;
465 *data++ = (u64)t->pkt_mismatch;
466 *data++ = (u64)t->cmdQ_full[0];
467 *data++ = (u64)t->cmdQ_full[1];
468 *data++ = (u64)t->tx_ipfrags;
469 *data++ = (u64)t->tx_reg_pkts;
470 *data++ = (u64)t->tx_lso_pkts;
471 *data++ = (u64)t->tx_do_cksum;
472}
473
474static inline void reg_block_dump(struct adapter *ap, void *buf,
475 unsigned int start, unsigned int end)
476{
477 u32 *p = buf + start;
478
479 for ( ; start <= end; start += sizeof(u32))
480 *p++ = readl(ap->regs + start);
481}
482
483static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
484 void *buf)
485{
486 struct adapter *ap = dev->priv;
487
488 /*
489 * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
490 */
491 regs->version = 2;
492
493 memset(buf, 0, T2_REGMAP_SIZE);
494 reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800495}
496
497static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
498{
499 struct adapter *adapter = dev->priv;
500 struct port_info *p = &adapter->port[dev->if_port];
501
502 cmd->supported = p->link_config.supported;
503 cmd->advertising = p->link_config.advertising;
504
505 if (netif_carrier_ok(dev)) {
506 cmd->speed = p->link_config.speed;
507 cmd->duplex = p->link_config.duplex;
508 } else {
509 cmd->speed = -1;
510 cmd->duplex = -1;
511 }
512
Stephen Hemminger20578152006-11-17 11:21:22 -0800513 cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
514 cmd->phy_address = p->phy->addr;
515 cmd->transceiver = XCVR_EXTERNAL;
516 cmd->autoneg = p->link_config.autoneg;
517 cmd->maxtxpkt = 0;
518 cmd->maxrxpkt = 0;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800519 return 0;
520}
521
522static int speed_duplex_to_caps(int speed, int duplex)
523{
524 int cap = 0;
525
526 switch (speed) {
527 case SPEED_10:
528 if (duplex == DUPLEX_FULL)
529 cap = SUPPORTED_10baseT_Full;
530 else
531 cap = SUPPORTED_10baseT_Half;
532 break;
533 case SPEED_100:
534 if (duplex == DUPLEX_FULL)
535 cap = SUPPORTED_100baseT_Full;
536 else
537 cap = SUPPORTED_100baseT_Half;
538 break;
539 case SPEED_1000:
540 if (duplex == DUPLEX_FULL)
541 cap = SUPPORTED_1000baseT_Full;
542 else
543 cap = SUPPORTED_1000baseT_Half;
544 break;
545 case SPEED_10000:
546 if (duplex == DUPLEX_FULL)
547 cap = SUPPORTED_10000baseT_Full;
548 }
549 return cap;
550}
551
552#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
553 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
554 ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
555 ADVERTISED_10000baseT_Full)
556
557static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
558{
559 struct adapter *adapter = dev->priv;
560 struct port_info *p = &adapter->port[dev->if_port];
561 struct link_config *lc = &p->link_config;
562
563 if (!(lc->supported & SUPPORTED_Autoneg))
Scott Bardone559fb512005-06-23 01:40:19 -0400564 return -EOPNOTSUPP; /* can't change speed/duplex */
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800565
566 if (cmd->autoneg == AUTONEG_DISABLE) {
567 int cap = speed_duplex_to_caps(cmd->speed, cmd->duplex);
568
569 if (!(lc->supported & cap) || cmd->speed == SPEED_1000)
570 return -EINVAL;
571 lc->requested_speed = cmd->speed;
572 lc->requested_duplex = cmd->duplex;
573 lc->advertising = 0;
574 } else {
575 cmd->advertising &= ADVERTISED_MASK;
576 if (cmd->advertising & (cmd->advertising - 1))
577 cmd->advertising = lc->supported;
578 cmd->advertising &= lc->supported;
579 if (!cmd->advertising)
580 return -EINVAL;
581 lc->requested_speed = SPEED_INVALID;
582 lc->requested_duplex = DUPLEX_INVALID;
583 lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
584 }
585 lc->autoneg = cmd->autoneg;
586 if (netif_running(dev))
587 t1_link_start(p->phy, p->mac, lc);
588 return 0;
589}
590
591static void get_pauseparam(struct net_device *dev,
592 struct ethtool_pauseparam *epause)
593{
594 struct adapter *adapter = dev->priv;
595 struct port_info *p = &adapter->port[dev->if_port];
596
597 epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
598 epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
599 epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
600}
601
602static int set_pauseparam(struct net_device *dev,
603 struct ethtool_pauseparam *epause)
604{
605 struct adapter *adapter = dev->priv;
606 struct port_info *p = &adapter->port[dev->if_port];
607 struct link_config *lc = &p->link_config;
608
609 if (epause->autoneg == AUTONEG_DISABLE)
610 lc->requested_fc = 0;
611 else if (lc->supported & SUPPORTED_Autoneg)
612 lc->requested_fc = PAUSE_AUTONEG;
613 else
614 return -EINVAL;
615
616 if (epause->rx_pause)
617 lc->requested_fc |= PAUSE_RX;
618 if (epause->tx_pause)
619 lc->requested_fc |= PAUSE_TX;
620 if (lc->autoneg == AUTONEG_ENABLE) {
621 if (netif_running(dev))
622 t1_link_start(p->phy, p->mac, lc);
623 } else {
624 lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
625 if (netif_running(dev))
626 p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
627 lc->fc);
628 }
629 return 0;
630}
631
632static u32 get_rx_csum(struct net_device *dev)
633{
634 struct adapter *adapter = dev->priv;
635
636 return (adapter->flags & RX_CSUM_ENABLED) != 0;
637}
638
639static int set_rx_csum(struct net_device *dev, u32 data)
640{
641 struct adapter *adapter = dev->priv;
642
643 if (data)
644 adapter->flags |= RX_CSUM_ENABLED;
645 else
646 adapter->flags &= ~RX_CSUM_ENABLED;
647 return 0;
648}
649
650static int set_tso(struct net_device *dev, u32 value)
651{
652 struct adapter *adapter = dev->priv;
653
654 if (!(adapter->flags & TSO_CAPABLE))
655 return value ? -EOPNOTSUPP : 0;
656 return ethtool_op_set_tso(dev, value);
657}
658
659static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
660{
661 struct adapter *adapter = dev->priv;
662 int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
663
664 e->rx_max_pending = MAX_RX_BUFFERS;
665 e->rx_mini_max_pending = 0;
666 e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
667 e->tx_max_pending = MAX_CMDQ_ENTRIES;
668
669 e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
670 e->rx_mini_pending = 0;
671 e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
672 e->tx_pending = adapter->params.sge.cmdQ_size[0];
673}
674
675static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
676{
677 struct adapter *adapter = dev->priv;
678 int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
679
680 if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
681 e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
682 e->tx_pending > MAX_CMDQ_ENTRIES ||
683 e->rx_pending < MIN_FL_ENTRIES ||
684 e->rx_jumbo_pending < MIN_FL_ENTRIES ||
685 e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
686 return -EINVAL;
687
688 if (adapter->flags & FULL_INIT_DONE)
Stephen Hemminger20578152006-11-17 11:21:22 -0800689 return -EBUSY;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800690
691 adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
692 adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
693 adapter->params.sge.cmdQ_size[0] = e->tx_pending;
694 adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
695 MAX_CMDQ1_ENTRIES : e->tx_pending;
696 return 0;
697}
698
699static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
700{
701 struct adapter *adapter = dev->priv;
702
Scott Bardone559fb512005-06-23 01:40:19 -0400703 /*
704 * If RX coalescing is requested we use NAPI, otherwise interrupts.
705 * This choice can be made only when all ports and the TOE are off.
706 */
707 if (adapter->open_device_map == 0)
708 adapter->params.sge.polling = c->use_adaptive_rx_coalesce;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800709
Scott Bardone559fb512005-06-23 01:40:19 -0400710 if (adapter->params.sge.polling) {
711 adapter->params.sge.rx_coalesce_usecs = 0;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800712 } else {
713 adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
714 }
Scott Bardone559fb512005-06-23 01:40:19 -0400715 adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800716 adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800717 t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
718 return 0;
719}
720
721static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
722{
723 struct adapter *adapter = dev->priv;
724
Scott Bardone559fb512005-06-23 01:40:19 -0400725 c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800726 c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
727 c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
728 return 0;
729}
730
731static int get_eeprom_len(struct net_device *dev)
732{
Scott Bardone559fb512005-06-23 01:40:19 -0400733 return EEPROM_SIZE;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800734}
735
736#define EEPROM_MAGIC(ap) \
737 (PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
738
739static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
740 u8 *data)
741{
742 int i;
743 u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
744 struct adapter *adapter = dev->priv;
745
746 e->magic = EEPROM_MAGIC(adapter);
747 for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
748 t1_seeprom_read(adapter, i, (u32 *)&buf[i]);
749 memcpy(data, buf + e->offset, e->len);
750 return 0;
751}
752
Jeff Garzik7282d492006-09-13 14:30:00 -0400753static const struct ethtool_ops t1_ethtool_ops = {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800754 .get_settings = get_settings,
755 .set_settings = set_settings,
756 .get_drvinfo = get_drvinfo,
757 .get_msglevel = get_msglevel,
758 .set_msglevel = set_msglevel,
759 .get_ringparam = get_sge_param,
760 .set_ringparam = set_sge_param,
761 .get_coalesce = get_coalesce,
762 .set_coalesce = set_coalesce,
763 .get_eeprom_len = get_eeprom_len,
764 .get_eeprom = get_eeprom,
765 .get_pauseparam = get_pauseparam,
766 .set_pauseparam = set_pauseparam,
767 .get_rx_csum = get_rx_csum,
768 .set_rx_csum = set_rx_csum,
769 .get_tx_csum = ethtool_op_get_tx_csum,
770 .set_tx_csum = ethtool_op_set_tx_csum,
771 .get_sg = ethtool_op_get_sg,
772 .set_sg = ethtool_op_set_sg,
773 .get_link = ethtool_op_get_link,
774 .get_strings = get_strings,
775 .get_stats_count = get_stats_count,
776 .get_ethtool_stats = get_stats,
Scott Bardone559fb512005-06-23 01:40:19 -0400777 .get_regs_len = get_regs_len,
778 .get_regs = get_regs,
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800779 .get_tso = ethtool_op_get_tso,
780 .set_tso = set_tso,
781};
782
Scott Bardone559fb512005-06-23 01:40:19 -0400783static void cxgb_proc_cleanup(struct adapter *adapter,
784 struct proc_dir_entry *dir)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800785{
Scott Bardone559fb512005-06-23 01:40:19 -0400786 const char *name;
787 name = adapter->name;
788 remove_proc_entry(name, dir);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800789}
Scott Bardone559fb512005-06-23 01:40:19 -0400790//#define chtoe_setup_toedev(adapter) NULL
791#define update_mtu_tab(adapter)
792#define write_smt_entry(adapter, idx)
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800793
794static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
795{
Stephen Hemminger20578152006-11-17 11:21:22 -0800796 struct adapter *adapter = dev->priv;
797 struct mii_ioctl_data *data = if_mii(req);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800798
799 switch (cmd) {
Stephen Hemminger20578152006-11-17 11:21:22 -0800800 case SIOCGMIIPHY:
801 data->phy_id = adapter->port[dev->if_port].phy->addr;
802 /* FALLTHRU */
803 case SIOCGMIIREG: {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800804 struct cphy *phy = adapter->port[dev->if_port].phy;
805 u32 val;
806
Scott Bardone559fb512005-06-23 01:40:19 -0400807 if (!phy->mdio_read)
Stephen Hemminger20578152006-11-17 11:21:22 -0800808 return -EOPNOTSUPP;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800809 phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
810 &val);
Stephen Hemminger20578152006-11-17 11:21:22 -0800811 data->val_out = val;
812 break;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800813 }
Stephen Hemminger20578152006-11-17 11:21:22 -0800814 case SIOCSMIIREG: {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800815 struct cphy *phy = adapter->port[dev->if_port].phy;
816
Stephen Hemminger20578152006-11-17 11:21:22 -0800817 if (!capable(CAP_NET_ADMIN))
818 return -EPERM;
Scott Bardone559fb512005-06-23 01:40:19 -0400819 if (!phy->mdio_write)
Stephen Hemminger20578152006-11-17 11:21:22 -0800820 return -EOPNOTSUPP;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800821 phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
Scott Bardone559fb512005-06-23 01:40:19 -0400822 data->val_in);
Stephen Hemminger20578152006-11-17 11:21:22 -0800823 break;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800824 }
825
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800826 default:
827 return -EOPNOTSUPP;
828 }
829 return 0;
830}
831
832static int t1_change_mtu(struct net_device *dev, int new_mtu)
833{
834 int ret;
835 struct adapter *adapter = dev->priv;
836 struct cmac *mac = adapter->port[dev->if_port].mac;
837
838 if (!mac->ops->set_mtu)
Stephen Hemminger20578152006-11-17 11:21:22 -0800839 return -EOPNOTSUPP;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800840 if (new_mtu < 68)
Stephen Hemminger20578152006-11-17 11:21:22 -0800841 return -EINVAL;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800842 if ((ret = mac->ops->set_mtu(mac, new_mtu)))
843 return ret;
844 dev->mtu = new_mtu;
845 return 0;
846}
847
848static int t1_set_mac_addr(struct net_device *dev, void *p)
849{
850 struct adapter *adapter = dev->priv;
851 struct cmac *mac = adapter->port[dev->if_port].mac;
852 struct sockaddr *addr = p;
853
854 if (!mac->ops->macaddress_set)
855 return -EOPNOTSUPP;
856
857 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
858 mac->ops->macaddress_set(mac, dev->dev_addr);
859 return 0;
860}
861
862#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
863static void vlan_rx_register(struct net_device *dev,
864 struct vlan_group *grp)
865{
866 struct adapter *adapter = dev->priv;
867
868 spin_lock_irq(&adapter->async_lock);
869 adapter->vlan_grp = grp;
870 t1_set_vlan_accel(adapter, grp != NULL);
871 spin_unlock_irq(&adapter->async_lock);
872}
873
874static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
875{
876 struct adapter *adapter = dev->priv;
877
878 spin_lock_irq(&adapter->async_lock);
879 if (adapter->vlan_grp)
880 adapter->vlan_grp->vlan_devices[vid] = NULL;
881 spin_unlock_irq(&adapter->async_lock);
882}
883#endif
884
885#ifdef CONFIG_NET_POLL_CONTROLLER
886static void t1_netpoll(struct net_device *dev)
887{
Scott Bardone559fb512005-06-23 01:40:19 -0400888 unsigned long flags;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800889 struct adapter *adapter = dev->priv;
890
Scott Bardone559fb512005-06-23 01:40:19 -0400891 local_irq_save(flags);
Stephen Hemminger20578152006-11-17 11:21:22 -0800892 t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter);
Scott Bardone559fb512005-06-23 01:40:19 -0400893 local_irq_restore(flags);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800894}
895#endif
896
897/*
898 * Periodic accumulation of MAC statistics. This is used only if the MAC
899 * does not have any other way to prevent stats counter overflow.
900 */
901static void mac_stats_task(void *data)
902{
903 int i;
904 struct adapter *adapter = data;
905
906 for_each_port(adapter, i) {
907 struct port_info *p = &adapter->port[i];
908
909 if (netif_running(p->dev))
910 p->mac->ops->statistics_update(p->mac,
911 MAC_STATS_UPDATE_FAST);
912 }
913
914 /* Schedule the next statistics update if any port is active. */
915 spin_lock(&adapter->work_lock);
916 if (adapter->open_device_map & PORT_MASK)
917 schedule_mac_stats_update(adapter,
918 adapter->params.stats_update_period);
919 spin_unlock(&adapter->work_lock);
920}
921
922/*
923 * Processes elmer0 external interrupts in process context.
924 */
925static void ext_intr_task(void *data)
926{
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800927 struct adapter *adapter = data;
928
929 elmer0_ext_intr_handler(adapter);
930
931 /* Now reenable external interrupts */
Scott Bardone559fb512005-06-23 01:40:19 -0400932 spin_lock_irq(&adapter->async_lock);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800933 adapter->slow_intr_mask |= F_PL_INTR_EXT;
Scott Bardone559fb512005-06-23 01:40:19 -0400934 writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
935 writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
Stephen Hemminger20578152006-11-17 11:21:22 -0800936 adapter->regs + A_PL_ENABLE);
Scott Bardone559fb512005-06-23 01:40:19 -0400937 spin_unlock_irq(&adapter->async_lock);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800938}
939
940/*
941 * Interrupt-context handler for elmer0 external interrupts.
942 */
943void t1_elmer0_ext_intr(struct adapter *adapter)
944{
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800945 /*
946 * Schedule a task to handle external interrupts as we require
947 * a process context. We disable EXT interrupts in the interim
948 * and let the task reenable them when it's done.
949 */
950 adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
Scott Bardone559fb512005-06-23 01:40:19 -0400951 writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
Stephen Hemminger20578152006-11-17 11:21:22 -0800952 adapter->regs + A_PL_ENABLE);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800953 schedule_work(&adapter->ext_intr_handler_task);
954}
955
956void t1_fatal_err(struct adapter *adapter)
957{
958 if (adapter->flags & FULL_INIT_DONE) {
959 t1_sge_stop(adapter->sge);
960 t1_interrupts_disable(adapter);
961 }
962 CH_ALERT("%s: encountered fatal error, operation suspended\n",
963 adapter->name);
964}
965
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800966static int __devinit init_one(struct pci_dev *pdev,
967 const struct pci_device_id *ent)
968{
969 static int version_printed;
970
971 int i, err, pci_using_dac = 0;
972 unsigned long mmio_start, mmio_len;
973 const struct board_info *bi;
974 struct adapter *adapter = NULL;
975 struct port_info *pi;
976
977 if (!version_printed) {
Scott Bardone559fb512005-06-23 01:40:19 -0400978 printk(KERN_INFO "%s - version %s\n", DRV_DESCRIPTION,
979 DRV_VERSION);
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800980 ++version_printed;
981 }
982
983 err = pci_enable_device(pdev);
984 if (err)
Stephen Hemminger20578152006-11-17 11:21:22 -0800985 return err;
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800986
987 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
988 CH_ERR("%s: cannot find PCI device memory base address\n",
989 pci_name(pdev));
990 err = -ENODEV;
991 goto out_disable_pdev;
992 }
993
Scott Bardone559fb512005-06-23 01:40:19 -0400994 if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800995 pci_using_dac = 1;
Scott Bardone559fb512005-06-23 01:40:19 -0400996
997 if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -0800998 CH_ERR("%s: unable to obtain 64-bit DMA for"
999 "consistent allocations\n", pci_name(pdev));
1000 err = -ENODEV;
1001 goto out_disable_pdev;
1002 }
Scott Bardone559fb512005-06-23 01:40:19 -04001003
1004 } else if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001005 CH_ERR("%s: no usable DMA configuration\n", pci_name(pdev));
1006 goto out_disable_pdev;
1007 }
1008
Scott Bardone559fb512005-06-23 01:40:19 -04001009 err = pci_request_regions(pdev, DRV_NAME);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001010 if (err) {
1011 CH_ERR("%s: cannot obtain PCI resources\n", pci_name(pdev));
1012 goto out_disable_pdev;
1013 }
1014
1015 pci_set_master(pdev);
1016
Stephen Hemminger20578152006-11-17 11:21:22 -08001017 mmio_start = pci_resource_start(pdev, 0);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001018 mmio_len = pci_resource_len(pdev, 0);
1019 bi = t1_get_board_info(ent->driver_data);
1020
1021 for (i = 0; i < bi->port_number; ++i) {
1022 struct net_device *netdev;
1023
1024 netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
1025 if (!netdev) {
1026 err = -ENOMEM;
1027 goto out_free_dev;
1028 }
1029
1030 SET_MODULE_OWNER(netdev);
1031 SET_NETDEV_DEV(netdev, &pdev->dev);
1032
1033 if (!adapter) {
1034 adapter = netdev->priv;
1035 adapter->pdev = pdev;
1036 adapter->port[0].dev = netdev; /* so we don't leak it */
1037
1038 adapter->regs = ioremap(mmio_start, mmio_len);
1039 if (!adapter->regs) {
1040 CH_ERR("%s: cannot map device registers\n",
1041 pci_name(pdev));
1042 err = -ENOMEM;
1043 goto out_free_dev;
1044 }
1045
1046 if (t1_get_board_rev(adapter, bi, &adapter->params)) {
1047 err = -ENODEV; /* Can't handle this chip rev */
1048 goto out_free_dev;
1049 }
1050
1051 adapter->name = pci_name(pdev);
1052 adapter->msg_enable = dflt_msg_enable;
1053 adapter->mmio_len = mmio_len;
1054
1055 init_MUTEX(&adapter->mib_mutex);
1056 spin_lock_init(&adapter->tpi_lock);
1057 spin_lock_init(&adapter->work_lock);
1058 spin_lock_init(&adapter->async_lock);
1059
1060 INIT_WORK(&adapter->ext_intr_handler_task,
1061 ext_intr_task, adapter);
1062 INIT_WORK(&adapter->stats_update_task, mac_stats_task,
1063 adapter);
1064
1065 pci_set_drvdata(pdev, netdev);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001066 }
1067
1068 pi = &adapter->port[i];
1069 pi->dev = netdev;
1070 netif_carrier_off(netdev);
1071 netdev->irq = pdev->irq;
1072 netdev->if_port = i;
1073 netdev->mem_start = mmio_start;
1074 netdev->mem_end = mmio_start + mmio_len - 1;
1075 netdev->priv = adapter;
1076 netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
Scott Bardone559fb512005-06-23 01:40:19 -04001077 netdev->features |= NETIF_F_LLTX;
1078
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001079 adapter->flags |= RX_CSUM_ENABLED | TCP_CSUM_CAPABLE;
1080 if (pci_using_dac)
1081 netdev->features |= NETIF_F_HIGHDMA;
1082 if (vlan_tso_capable(adapter)) {
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001083#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
1084 adapter->flags |= VLAN_ACCEL_CAPABLE;
1085 netdev->features |=
1086 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
1087 netdev->vlan_rx_register = vlan_rx_register;
1088 netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
1089#endif
1090 adapter->flags |= TSO_CAPABLE;
1091 netdev->features |= NETIF_F_TSO;
1092 }
1093
1094 netdev->open = cxgb_open;
1095 netdev->stop = cxgb_close;
1096 netdev->hard_start_xmit = t1_start_xmit;
1097 netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ?
1098 sizeof(struct cpl_tx_pkt_lso) :
1099 sizeof(struct cpl_tx_pkt);
1100 netdev->get_stats = t1_get_stats;
1101 netdev->set_multicast_list = t1_set_rxmode;
1102 netdev->do_ioctl = t1_ioctl;
1103 netdev->change_mtu = t1_change_mtu;
1104 netdev->set_mac_address = t1_set_mac_addr;
1105#ifdef CONFIG_NET_POLL_CONTROLLER
1106 netdev->poll_controller = t1_netpoll;
1107#endif
1108 netdev->weight = 64;
1109
Stephen Hemminger20578152006-11-17 11:21:22 -08001110 SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001111 }
1112
1113 if (t1_init_sw_modules(adapter, bi) < 0) {
1114 err = -ENODEV;
1115 goto out_free_dev;
1116 }
1117
1118 /*
1119 * The card is now ready to go. If any errors occur during device
1120 * registration we do not fail the whole card but rather proceed only
1121 * with the ports we manage to register successfully. However we must
1122 * register at least one net device.
1123 */
1124 for (i = 0; i < bi->port_number; ++i) {
1125 err = register_netdev(adapter->port[i].dev);
1126 if (err)
1127 CH_WARN("%s: cannot register net device %s, skipping\n",
1128 pci_name(pdev), adapter->port[i].dev->name);
1129 else {
1130 /*
1131 * Change the name we use for messages to the name of
1132 * the first successfully registered interface.
1133 */
1134 if (!adapter->registered_device_map)
1135 adapter->name = adapter->port[i].dev->name;
1136
Stephen Hemminger20578152006-11-17 11:21:22 -08001137 __set_bit(i, &adapter->registered_device_map);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001138 }
1139 }
1140 if (!adapter->registered_device_map) {
1141 CH_ERR("%s: could not register any net devices\n",
1142 pci_name(pdev));
1143 goto out_release_adapter_res;
1144 }
1145
1146 printk(KERN_INFO "%s: %s (rev %d), %s %dMHz/%d-bit\n", adapter->name,
1147 bi->desc, adapter->params.chip_revision,
1148 adapter->params.pci.is_pcix ? "PCIX" : "PCI",
1149 adapter->params.pci.speed, adapter->params.pci.width);
1150 return 0;
1151
1152 out_release_adapter_res:
1153 t1_free_sw_modules(adapter);
1154 out_free_dev:
1155 if (adapter) {
Scott Bardone559fb512005-06-23 01:40:19 -04001156 if (adapter->regs) iounmap(adapter->regs);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001157 for (i = bi->port_number - 1; i >= 0; --i)
Scott Bardone559fb512005-06-23 01:40:19 -04001158 if (adapter->port[i].dev) {
1159 cxgb_proc_cleanup(adapter, proc_root_driver);
1160 kfree(adapter->port[i].dev);
1161 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001162 }
1163 pci_release_regions(pdev);
1164 out_disable_pdev:
1165 pci_disable_device(pdev);
1166 pci_set_drvdata(pdev, NULL);
1167 return err;
1168}
1169
1170static inline void t1_sw_reset(struct pci_dev *pdev)
1171{
1172 pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
1173 pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
1174}
1175
1176static void __devexit remove_one(struct pci_dev *pdev)
1177{
1178 struct net_device *dev = pci_get_drvdata(pdev);
1179
1180 if (dev) {
1181 int i;
1182 struct adapter *adapter = dev->priv;
1183
1184 for_each_port(adapter, i)
1185 if (test_bit(i, &adapter->registered_device_map))
1186 unregister_netdev(adapter->port[i].dev);
1187
1188 t1_free_sw_modules(adapter);
1189 iounmap(adapter->regs);
1190 while (--i >= 0)
Scott Bardone559fb512005-06-23 01:40:19 -04001191 if (adapter->port[i].dev) {
1192 cxgb_proc_cleanup(adapter, proc_root_driver);
1193 kfree(adapter->port[i].dev);
1194 }
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001195 pci_release_regions(pdev);
1196 pci_disable_device(pdev);
1197 pci_set_drvdata(pdev, NULL);
1198 t1_sw_reset(pdev);
1199 }
1200}
1201
1202static struct pci_driver driver = {
Scott Bardone559fb512005-06-23 01:40:19 -04001203 .name = DRV_NAME,
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001204 .id_table = t1_pci_tbl,
1205 .probe = init_one,
1206 .remove = __devexit_p(remove_one),
1207};
1208
1209static int __init t1_init_module(void)
1210{
Jeff Garzik29917622006-08-19 17:48:59 -04001211 return pci_register_driver(&driver);
Christoph Lameter8199d3a2005-03-30 13:34:31 -08001212}
1213
1214static void __exit t1_cleanup_module(void)
1215{
1216 pci_unregister_driver(&driver);
1217}
1218
1219module_init(t1_init_module);
1220module_exit(t1_cleanup_module);