[ar71xx] register GPIO buttons on the AP83 board
[openwrt.git] / package / broadcom-57xx / src / b57um.c
1 /******************************************************************************/
2 /* */
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2005 Broadcom */
4 /* Corporation. */
5 /* All rights reserved. */
6 /* */
7 /* This program is free software; you can redistribute it and/or modify */
8 /* it under the terms of the GNU General Public License as published by */
9 /* the Free Software Foundation, located in the file LICENSE. */
10 /* */
11 /******************************************************************************/
12
13 /* $Id: b57um.c,v 1.32 2007/09/06 07:28:06 yogo Exp $ */
14
15 char bcm5700_driver[] = "bcm57xx";
16 char bcm5700_version[] = "8.3.14";
17 char bcm5700_date[] = "(11/2/05)";
18
19 #define B57UM
20 #include "mm.h"
21 #include "linux/mii.h" //@.@jack add it 2006/06/28.
22 #include "typedefs.h"
23 #include "osl.h"
24 #include "bcmdefs.h"
25 #include "bcmdevs.h"
26 #include "sbconfig.h"
27 #include "sbutils.h"
28 #include "hndgige.h"
29 #include "bcmrobo.h"
30 #include "robo_register.c"
31
32 #include "bcmendian.h"
33 #include "bcmnvram.h"
34 #include "proto/ethernet.h"
35 #include "proto/vlan.h"
36 #include "proto/bcmtcp.h"
37 #include "proto/bcmip.h"
38 #define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
39
40 /* this is needed to get good and stable performances */
41 #define EXTRA_HDR BCMEXTRAHDROOM
42
43 #define SIOCGREG_STATUS 0x8996 /* Read Switch register (for debug)*/
44 #define SIOCSREG_STATUS 0x8997 /* Write Switch register(for debug)*/
45
46 /* This structure is used in SIOCXREG_STATUS ioctl calls*/
47 struct reg_ioctl_data {
48 u16 page_num;
49 u16 addr_num;
50 u16 len;
51 u16 val_in[4];
52 u16 val_out[4];
53 };
54
55 /* A few user-configurable values. */
56
57 #define MAX_UNITS 16
58 /* Used to pass the full-duplex flag, etc. */
59 static int line_speed[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
60 static int auto_speed[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
61 static int full_duplex[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
62 static int rx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
63 static int tx_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
64 static int auto_flow_control[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
65 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
66 static int mtu[MAX_UNITS] = {1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500,1500}; /* Jumbo MTU for interfaces. */
67 #endif
68 static int tx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
69 static int rx_checksum[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
70 static int scatter_gather[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
71 static int activate_gpio = -1;
72
73 #define TX_DESC_CNT DEFAULT_TX_PACKET_DESC_COUNT
74 static unsigned int tx_pkt_desc_cnt[MAX_UNITS] =
75 {TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
76 TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
77 TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,TX_DESC_CNT,
78 TX_DESC_CNT};
79
80 #define RX_DESC_CNT DEFAULT_STD_RCV_DESC_COUNT
81 static unsigned int rx_std_desc_cnt[MAX_UNITS] =
82 {RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
83 RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
84 RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,RX_DESC_CNT,
85 RX_DESC_CNT };
86
87 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
88 #define JBO_DESC_CNT DEFAULT_JUMBO_RCV_DESC_COUNT
89 static unsigned int rx_jumbo_desc_cnt[MAX_UNITS] =
90 {JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
91 JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
92 JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,JBO_DESC_CNT,
93 JBO_DESC_CNT };
94 #endif
95
96 #ifdef BCM_INT_COAL
97 #ifdef BCM_NAPI_RXPOLL
98 static unsigned int adaptive_coalesce[MAX_UNITS] =
99 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
100 #else
101 static unsigned int adaptive_coalesce[MAX_UNITS] =
102 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
103 #endif
104
105 #define RX_COAL_TK DEFAULT_RX_COALESCING_TICKS
106 static unsigned int rx_coalesce_ticks[MAX_UNITS] =
107 {RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
108 RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
109 RX_COAL_TK,RX_COAL_TK, RX_COAL_TK,RX_COAL_TK,RX_COAL_TK,
110 RX_COAL_TK};
111
112 #define RX_COAL_FM DEFAULT_RX_MAX_COALESCED_FRAMES
113 static unsigned int rx_max_coalesce_frames[MAX_UNITS] =
114 {RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
115 RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
116 RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,RX_COAL_FM,
117 RX_COAL_FM};
118
119 #define TX_COAL_TK DEFAULT_TX_COALESCING_TICKS
120 static unsigned int tx_coalesce_ticks[MAX_UNITS] =
121 {TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
122 TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
123 TX_COAL_TK,TX_COAL_TK, TX_COAL_TK,TX_COAL_TK,TX_COAL_TK,
124 TX_COAL_TK};
125
126 #define TX_COAL_FM DEFAULT_TX_MAX_COALESCED_FRAMES
127 static unsigned int tx_max_coalesce_frames[MAX_UNITS] =
128 {TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
129 TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
130 TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,TX_COAL_FM,
131 TX_COAL_FM};
132
133 #define ST_COAL_TK DEFAULT_STATS_COALESCING_TICKS
134 static unsigned int stats_coalesce_ticks[MAX_UNITS] =
135 {ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
136 ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
137 ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,ST_COAL_TK,
138 ST_COAL_TK,};
139
140 #endif
141 #ifdef BCM_WOL
142 static int enable_wol[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
143 #endif
144 #ifdef BCM_TSO
145 static int enable_tso[MAX_UNITS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
146 #endif
147 #ifdef BCM_NIC_SEND_BD
148 static int nic_tx_bd[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
149 #endif
150 #ifdef BCM_ASF
151 static int vlan_tag_mode[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
152 #endif
153 static int delay_link[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
154 static int disable_d3hot[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
155
156 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
157 static int disable_msi[MAX_UNITS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
158 static int bcm_msi_chipset_bug = 0;
159 #endif
160
161 #define BCM_TIMER_GRANULARITY (1000000 / HZ)
162
163 /* Hack to hook the data path to the BCM WL dirver */
164 #ifdef BCM_WL_EMULATOR
165 #include "bcmnvram.h"
166 #include "wl_bcm57emu.h"
167 #ifdef SKB_MANAGER
168 int skb_old_alloc = 0;
169 #endif
170 #endif /* BCM_WL_EMULATOR */
171
172 /* Operational parameters that usually are not changed. */
173 /* Time in jiffies before concluding the transmitter is hung. */
174 #define TX_TIMEOUT (2*HZ)
175
176 #if (LINUX_VERSION_CODE < 0x02030d)
177 #define pci_resource_start(dev, bar) (dev->base_address[bar] & PCI_BASE_ADDRESS_MEM_MASK)
178 #elif (LINUX_VERSION_CODE < 0x02032b)
179 #define pci_resource_start(dev, bar) (dev->resource[bar] & PCI_BASE_ADDRESS_MEM_MASK)
180 #endif
181
182 #if (LINUX_VERSION_CODE < 0x02032b)
183 #define dev_kfree_skb_irq(skb) dev_kfree_skb(skb)
184 #define netif_wake_queue(dev) clear_bit(0, &dev->tbusy); mark_bh(NET_BH)
185 #define netif_stop_queue(dev) set_bit(0, &dev->tbusy)
186
187 static inline void netif_start_queue(struct net_device *dev)
188 {
189 dev->tbusy = 0;
190 dev->interrupt = 0;
191 dev->start = 1;
192 }
193
194 #define netif_queue_stopped(dev) dev->tbusy
195 #define netif_running(dev) dev->start
196
197 static inline void tasklet_schedule(struct tasklet_struct *tasklet)
198 {
199 queue_task(tasklet, &tq_immediate);
200 mark_bh(IMMEDIATE_BH);
201 }
202
203 static inline void tasklet_init(struct tasklet_struct *tasklet,
204 void (*func)(unsigned long),
205 unsigned long data)
206 {
207 tasklet->next = NULL;
208 tasklet->sync = 0;
209 tasklet->routine = (void (*)(void *))func;
210 tasklet->data = (void *)data;
211 }
212
213 #define tasklet_kill(tasklet)
214
215 #endif
216
217 #if (LINUX_VERSION_CODE < 0x020300)
218 struct pci_device_id {
219 unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
220 unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
221 unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
222 unsigned long driver_data; /* Data private to the driver */
223 };
224
225 #define PCI_ANY_ID 0
226
227 #define pci_set_drvdata(pdev, dev)
228 #define pci_get_drvdata(pdev) 0
229
230 #define pci_enable_device(pdev) 0
231
232 #define __devinit __init
233 #define __devinitdata __initdata
234 #define __devexit
235
236 #define SET_MODULE_OWNER(dev)
237 #define MODULE_DEVICE_TABLE(pci, pci_tbl)
238
239 #endif
240
241 #if (LINUX_VERSION_CODE < 0x020411)
242 #ifndef __devexit_p
243 #define __devexit_p(x) x
244 #endif
245 #endif
246
247 #ifndef MODULE_LICENSE
248 #define MODULE_LICENSE(license)
249 #endif
250
251 #ifndef IRQ_RETVAL
252 typedef void irqreturn_t;
253 #define IRQ_RETVAL(x)
254 #endif
255
256 #if (LINUX_VERSION_CODE < 0x02032a)
257 static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
258 dma_addr_t *dma_handle)
259 {
260 void *virt_ptr;
261
262 /* Maximum in slab.c */
263 if (size > 131072)
264 return 0;
265
266 virt_ptr = kmalloc(size, GFP_KERNEL);
267 *dma_handle = virt_to_bus(virt_ptr);
268 return virt_ptr;
269 }
270 #define pci_free_consistent(dev, size, ptr, dma_ptr) kfree(ptr)
271
272 #endif /*#if (LINUX_VERSION_CODE < 0x02032a) */
273
274
275 #if (LINUX_VERSION_CODE < 0x02040d)
276
277 #if (LINUX_VERSION_CODE >= 0x020409) && defined(RED_HAT_LINUX_KERNEL)
278
279 #define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL)
280 #define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL)
281
282 #else
283 /* pci_set_dma_mask is using dma_addr_t */
284
285 #define BCM_32BIT_DMA_MASK ((dma_addr_t) 0xffffffff)
286 #define BCM_64BIT_DMA_MASK ((dma_addr_t) 0xffffffff)
287
288 #endif
289
290 #else /* (LINUX_VERSION_CODE < 0x02040d) */
291
292 #define BCM_32BIT_DMA_MASK ((u64) 0x00000000ffffffffULL)
293 #define BCM_64BIT_DMA_MASK ((u64) 0xffffffffffffffffULL)
294 #endif
295
296 #if (LINUX_VERSION_CODE < 0x020329)
297 #define pci_set_dma_mask(pdev, mask) (0)
298 #else
299 #if (LINUX_VERSION_CODE < 0x020403)
300 int
301 pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
302 {
303 if(! pci_dma_supported(dev, mask))
304 return -EIO;
305
306 dev->dma_mask = mask;
307
308 return 0;
309 }
310 #endif
311 #endif
312
313 #if (LINUX_VERSION_CODE < 0x020547)
314 #define pci_set_consistent_dma_mask(pdev, mask) (0)
315 #endif
316
317 #if (LINUX_VERSION_CODE < 0x020402)
318 #define pci_request_regions(pdev, name) (0)
319 #define pci_release_regions(pdev)
320 #endif
321
322 #if !defined(spin_is_locked)
323 #define spin_is_locked(lock) (test_bit(0,(lock)))
324 #endif
325
326 #define BCM5700_LOCK(pUmDevice, flags) \
327 if ((pUmDevice)->do_global_lock) { \
328 spin_lock_irqsave(&(pUmDevice)->global_lock, flags); \
329 }
330
331 #define BCM5700_UNLOCK(pUmDevice, flags) \
332 if ((pUmDevice)->do_global_lock) { \
333 spin_unlock_irqrestore(&(pUmDevice)->global_lock, flags);\
334 }
335
336 inline void
337 bcm5700_intr_lock(PUM_DEVICE_BLOCK pUmDevice)
338 {
339 if (pUmDevice->do_global_lock) {
340 spin_lock(&pUmDevice->global_lock);
341 }
342 }
343
344 inline void
345 bcm5700_intr_unlock(PUM_DEVICE_BLOCK pUmDevice)
346 {
347 if (pUmDevice->do_global_lock) {
348 spin_unlock(&pUmDevice->global_lock);
349 }
350 }
351
352 void
353 bcm5700_intr_off(PUM_DEVICE_BLOCK pUmDevice)
354 {
355 atomic_inc(&pUmDevice->intr_sem);
356 LM_DisableInterrupt(&pUmDevice->lm_dev);
357 #if (LINUX_VERSION_CODE >= 0x2051c)
358 synchronize_irq(pUmDevice->dev->irq);
359 #else
360 synchronize_irq();
361 #endif
362 LM_DisableInterrupt(&pUmDevice->lm_dev);
363 }
364
365 void
366 bcm5700_intr_on(PUM_DEVICE_BLOCK pUmDevice)
367 {
368 if (atomic_dec_and_test(&pUmDevice->intr_sem)) {
369 LM_EnableInterrupt(&pUmDevice->lm_dev);
370 }
371 }
372
373
374 int MM_Packet_Desc_Size = sizeof(UM_PACKET);
375
376 #if defined(MODULE)
377 MODULE_AUTHOR("Michael Chan <mchan at broadcom dot com> and Gary Zambrano <zambrano at broadcom dot com>");
378 MODULE_DESCRIPTION("BCM5700 Driver");
379 MODULE_LICENSE("GPL");
380
381 #if (LINUX_VERSION_CODE < 0x020605)
382
383 MODULE_PARM(debug, "i");
384 MODULE_PARM(msglevel, "i");
385 MODULE_PARM(activate_gpio, "0-15i");
386 MODULE_PARM(line_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
387 MODULE_PARM(auto_speed, "1-" __MODULE_STRING(MAX_UNITS) "i");
388 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
389 MODULE_PARM(rx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
390 MODULE_PARM(tx_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
391 MODULE_PARM(auto_flow_control, "1-" __MODULE_STRING(MAX_UNITS) "i");
392 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
393 MODULE_PARM(mtu, "1-" __MODULE_STRING(MAX_UNITS) "i");
394 #endif
395 MODULE_PARM(tx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i");
396 MODULE_PARM(rx_checksum, "1-" __MODULE_STRING(MAX_UNITS) "i");
397 MODULE_PARM(scatter_gather, "1-" __MODULE_STRING(MAX_UNITS) "i");
398 MODULE_PARM(tx_pkt_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
399 MODULE_PARM(rx_std_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
400 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
401 MODULE_PARM(rx_jumbo_desc_cnt, "1-" __MODULE_STRING(MAX_UNITS) "i");
402 #endif
403 #ifdef BCM_INT_COAL
404 MODULE_PARM(adaptive_coalesce, "1-" __MODULE_STRING(MAX_UNITS) "i");
405 MODULE_PARM(rx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
406 MODULE_PARM(rx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i");
407 MODULE_PARM(tx_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
408 MODULE_PARM(tx_max_coalesce_frames, "1-" __MODULE_STRING(MAX_UNITS) "i");
409 MODULE_PARM(stats_coalesce_ticks, "1-" __MODULE_STRING(MAX_UNITS) "i");
410 #endif
411 #ifdef BCM_WOL
412 MODULE_PARM(enable_wol, "1-" __MODULE_STRING(MAX_UNITS) "i");
413 #endif
414 #ifdef BCM_TSO
415 MODULE_PARM(enable_tso, "1-" __MODULE_STRING(MAX_UNITS) "i");
416 #endif
417 #ifdef BCM_NIC_SEND_BD
418 MODULE_PARM(nic_tx_bd, "1-" __MODULE_STRING(MAX_UNITS) "i");
419 #endif
420 #ifdef BCM_ASF
421 MODULE_PARM(vlan_tag_mode, "1-" __MODULE_STRING(MAX_UNITS) "i");
422 #endif
423 MODULE_PARM(delay_link, "1-" __MODULE_STRING(MAX_UNITS) "i");
424 MODULE_PARM(disable_d3hot, "1-" __MODULE_STRING(MAX_UNITS) "i");
425
426 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
427 MODULE_PARM(disable_msi, "1-" __MODULE_STRING(MAX_UNITS) "i");
428 #endif
429
430 #else /* parms*/
431
432 #if (LINUX_VERSION_CODE >= 0x020605) && (LINUX_VERSION_CODE < 0x02060a)
433
434 static int var;
435
436 #define numvar var
437
438 #endif
439
440 #if (LINUX_VERSION_CODE >= 0x2060a)
441
442 #define numvar NULL
443
444 #endif
445
446 module_param_array(line_speed, int, numvar, 0);
447 module_param_array(auto_speed, int, numvar, 0);
448 module_param_array(full_duplex, int, numvar, 0);
449 module_param_array(rx_flow_control, int, numvar, 0);
450 module_param_array(tx_flow_control, int, numvar, 0);
451 module_param_array(auto_flow_control, int, numvar, 0);
452 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
453 module_param_array(mtu, int, numvar, 0);
454 #endif
455 module_param_array(tx_checksum, int, numvar, 0);
456 module_param_array(rx_checksum, int, numvar, 0);
457 module_param_array(scatter_gather, int, numvar, 0);
458 module_param_array(tx_pkt_desc_cnt, int, numvar, 0);
459 module_param_array(rx_std_desc_cnt, int, numvar, 0);
460 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
461 module_param_array(rx_jumbo_desc_cnt, int, numvar, 0);
462 #endif
463 #ifdef BCM_INT_COAL
464 module_param_array(adaptive_coalesce, int, numvar, 0);
465 module_param_array(rx_coalesce_ticks, int, numvar, 0);
466 module_param_array(rx_max_coalesce_frames, int, numvar, 0);
467 module_param_array(tx_coalesce_ticks, int, numvar, 0);
468 module_param_array(tx_max_coalesce_frames, int, numvar, 0);
469 module_param_array(stats_coalesce_ticks, int, numvar, 0);
470 #endif
471 #ifdef BCM_WOL
472 module_param_array(enable_wol, int, numvar, 0);
473 #endif
474 #ifdef BCM_TSO
475 module_param_array(enable_tso, int, numvar, 0);
476 #endif
477 #ifdef BCM_NIC_SEND_BD
478 module_param_array(nic_tx_bd, int, numvar, 0);
479 #endif
480 #ifdef BCM_ASF
481 module_param_array(vlan_tag_mode, int, numvar, 0);
482 #endif
483 module_param_array(delay_link, int, numvar, 0);
484 module_param_array(disable_d3hot, int, numvar, 0);
485
486 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
487 module_param_array(disable_msi, int, numvar, 0);
488 #endif
489
490
491 #endif /* params */
492
493
494 #endif
495
496 #define RUN_AT(x) (jiffies + (x))
497
498 char kernel_version[] = UTS_RELEASE;
499
500 #define PCI_SUPPORT_VER2
501
502 #if !defined(CAP_NET_ADMIN)
503 #define capable(CAP_XXX) (suser())
504 #endif
505
506 #define tigon3_debug debug
507 #if TIGON3_DEBUG
508 static int tigon3_debug = TIGON3_DEBUG;
509 #else
510 static int tigon3_debug = 0;
511 #endif
512 static int msglevel = 0xdeadbeef;
513 int b57_msg_level;
514
515 int bcm5700_open(struct net_device *dev);
516 STATIC void bcm5700_timer(unsigned long data);
517 STATIC void bcm5700_stats_timer(unsigned long data);
518 STATIC void bcm5700_reset(struct net_device *dev);
519 STATIC int bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev);
520 STATIC irqreturn_t bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
521 #ifdef BCM_TASKLET
522 STATIC void bcm5700_tasklet(unsigned long data);
523 #endif
524 STATIC int bcm5700_close(struct net_device *dev);
525 STATIC struct net_device_stats *bcm5700_get_stats(struct net_device *dev);
526 STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
527 STATIC void bcm5700_do_rx_mode(struct net_device *dev);
528 STATIC void bcm5700_set_rx_mode(struct net_device *dev);
529 STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p);
530 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
531 STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu);
532 #endif
533 #ifdef BCM_NAPI_RXPOLL
534 STATIC int bcm5700_poll(struct net_device *dev, int *budget);
535 #endif
536 STATIC int replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max);
537 STATIC int bcm5700_freemem(struct net_device *dev);
538 #ifdef BCM_INT_COAL
539 #ifndef BCM_NAPI_RXPOLL
540 STATIC int bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice);
541 #endif
542 #endif
543 STATIC void bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice);
544 STATIC int bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice);
545 #ifdef BCM_VLAN
546 STATIC void bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp);
547 STATIC void bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid);
548 #endif
549 void bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice);
550 void bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice);
551 void bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, int *param,
552 char *param_name, int min, int max, int deflt);
553
554 static int bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused);
555 static struct notifier_block bcm5700_reboot_notifier = {
556 bcm5700_notify_reboot,
557 NULL,
558 0
559 };
560
561 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
562 STATIC void poll_bcm5700(struct net_device *dev);
563 #endif
564
565 /* A list of all installed bcm5700 devices. */
566 static struct net_device *root_tigon3_dev = NULL;
567
568 #if defined(CONFIG_SPARC64) || defined(CONFIG_X86_64) ||defined(CONFIG_PPC64)
569
570 #endif
571
572 typedef enum {
573 BCM5700A6 = 0,
574 BCM5700T6,
575 BCM5700A9,
576 BCM5700T9,
577 BCM5700,
578 BCM5701A5,
579 BCM5701T1,
580 BCM5701T8,
581 BCM5701A7,
582 BCM5701A10,
583 BCM5701A12,
584 BCM5701,
585 BCM5702,
586 BCM5703,
587 BCM5703A31,
588 BCM5703ARBUCKLE,
589 TC996T,
590 TC996ST,
591 TC996SSX,
592 TC996SX,
593 TC996BT,
594 TC997T,
595 TC997SX,
596 TC1000T,
597 TC1000BT,
598 TC940BR01,
599 TC942BR01,
600 TC998T,
601 TC998SX,
602 TC999T,
603 NC6770,
604 NC1020,
605 NC150T,
606 NC7760,
607 NC7761,
608 NC7770,
609 NC7771,
610 NC7780,
611 NC7781,
612 NC7772,
613 NC7782,
614 NC7783,
615 NC320T,
616 NC320I,
617 NC325I,
618 NC324I,
619 NC326I,
620 BCM5704CIOBE,
621 BCM5704,
622 BCM5704S,
623 BCM5705,
624 BCM5705M,
625 BCM5705F,
626 BCM5901,
627 BCM5782,
628 BCM5788,
629 BCM5789,
630 BCM5750,
631 BCM5750M,
632 BCM5720,
633 BCM5751,
634 BCM5751M,
635 BCM5751F,
636 BCM5721,
637 BCM5753,
638 BCM5753M,
639 BCM5753F,
640 BCM5781,
641 BCM5752,
642 BCM5752M,
643 BCM5714,
644 BCM5780,
645 BCM5780S,
646 BCM5715,
647 BCM4785,
648 BCM5903M,
649 UNK5788
650 } board_t;
651
652
653 /* indexed by board_t, above */
654 static struct {
655 char *name;
656 } board_info[] __devinitdata = {
657 { "Broadcom BCM5700 1000Base-T" },
658 { "Broadcom BCM5700 1000Base-SX" },
659 { "Broadcom BCM5700 1000Base-SX" },
660 { "Broadcom BCM5700 1000Base-T" },
661 { "Broadcom BCM5700" },
662 { "Broadcom BCM5701 1000Base-T" },
663 { "Broadcom BCM5701 1000Base-T" },
664 { "Broadcom BCM5701 1000Base-T" },
665 { "Broadcom BCM5701 1000Base-SX" },
666 { "Broadcom BCM5701 1000Base-T" },
667 { "Broadcom BCM5701 1000Base-T" },
668 { "Broadcom BCM5701" },
669 { "Broadcom BCM5702 1000Base-T" },
670 { "Broadcom BCM5703 1000Base-T" },
671 { "Broadcom BCM5703 1000Base-SX" },
672 { "Broadcom B5703 1000Base-SX" },
673 { "3Com 3C996 10/100/1000 Server NIC" },
674 { "3Com 3C996 10/100/1000 Server NIC" },
675 { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
676 { "3Com 3C996 Gigabit Fiber-SX Server NIC" },
677 { "3Com 3C996B Gigabit Server NIC" },
678 { "3Com 3C997 Gigabit Server NIC" },
679 { "3Com 3C997 Gigabit Fiber-SX Server NIC" },
680 { "3Com 3C1000 Gigabit NIC" },
681 { "3Com 3C1000B-T 10/100/1000 PCI" },
682 { "3Com 3C940 Gigabit LOM (21X21)" },
683 { "3Com 3C942 Gigabit LOM (31X31)" },
684 { "3Com 3C998-T Dual Port 10/100/1000 PCI-X Server NIC" },
685 { "3Com 3C998-SX Dual Port 1000-SX PCI-X Server NIC" },
686 { "3Com 3C999-T Quad Port 10/100/1000 PCI-X Server NIC" },
687 { "HP NC6770 Gigabit Server Adapter" },
688 { "NC1020 HP ProLiant Gigabit Server Adapter 32 PCI" },
689 { "HP ProLiant NC 150T PCI 4-port Gigabit Combo Switch Adapter" },
690 { "HP NC7760 Gigabit Server Adapter" },
691 { "HP NC7761 Gigabit Server Adapter" },
692 { "HP NC7770 Gigabit Server Adapter" },
693 { "HP NC7771 Gigabit Server Adapter" },
694 { "HP NC7780 Gigabit Server Adapter" },
695 { "HP NC7781 Gigabit Server Adapter" },
696 { "HP NC7772 Gigabit Server Adapter" },
697 { "HP NC7782 Gigabit Server Adapter" },
698 { "HP NC7783 Gigabit Server Adapter" },
699 { "HP ProLiant NC 320T PCI Express Gigabit Server Adapter" },
700 { "HP ProLiant NC 320i PCI Express Gigabit Server Adapter" },
701 { "HP NC325i Integrated Dual Port PCI Express Gigabit Server Adapter" },
702 { "HP NC324i Integrated Dual Port PCI Express Gigabit Server Adapter" },
703 { "HP NC326i Integrated Dual Port PCI Express Gigabit Server Adapter" },
704 { "Broadcom BCM5704 CIOB-E 1000Base-T" },
705 { "Broadcom BCM5704 1000Base-T" },
706 { "Broadcom BCM5704 1000Base-SX" },
707 { "Broadcom BCM5705 1000Base-T" },
708 { "Broadcom BCM5705M 1000Base-T" },
709 { "Broadcom 570x 10/100 Integrated Controller" },
710 { "Broadcom BCM5901 100Base-TX" },
711 { "Broadcom NetXtreme Gigabit Ethernet for hp" },
712 { "Broadcom BCM5788 NetLink 1000Base-T" },
713 { "Broadcom BCM5789 NetLink 1000Base-T PCI Express" },
714 { "Broadcom BCM5750 1000Base-T PCI" },
715 { "Broadcom BCM5750M 1000Base-T PCI" },
716 { "Broadcom BCM5720 1000Base-T PCI" },
717 { "Broadcom BCM5751 1000Base-T PCI Express" },
718 { "Broadcom BCM5751M 1000Base-T PCI Express" },
719 { "Broadcom BCM5751F 100Base-TX PCI Express" },
720 { "Broadcom BCM5721 1000Base-T PCI Express" },
721 { "Broadcom BCM5753 1000Base-T PCI Express" },
722 { "Broadcom BCM5753M 1000Base-T PCI Express" },
723 { "Broadcom BCM5753F 100Base-TX PCI Express" },
724 { "Broadcom BCM5781 NetLink 1000Base-T PCI Express" },
725 { "Broadcom BCM5752 1000Base-T PCI Express" },
726 { "Broadcom BCM5752M 1000Base-T PCI Express" },
727 { "Broadcom BCM5714 1000Base-T " },
728 { "Broadcom BCM5780 1000Base-T" },
729 { "Broadcom BCM5780S 1000Base-SX" },
730 { "Broadcom BCM5715 1000Base-T " },
731 { "Broadcom BCM4785 10/100/1000 Integrated Controller" },
732 { "Broadcom BCM5903M Gigabit Ethernet " },
733 { "Unknown BCM5788 Gigabit Ethernet " },
734 { 0 }
735 };
736
737 static struct pci_device_id bcm5700_pci_tbl[] __devinitdata = {
738 {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 },
739 {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 },
740 {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 },
741 {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 },
742 {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 },
743 {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 },
744 {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 },
745 {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 },
746 {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T },
747 {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST },
748 {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX },
749 {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T },
750 {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX },
751 {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 },
752 {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 },
753 {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 },
754 {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 },
755 {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 },
756 {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 },
757 {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 },
758 {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 },
759 {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 },
760 {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 },
761 {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 },
762 {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 },
763 {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX },
764 {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT },
765 {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T },
766 {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 },
767 {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 },
768 {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 },
769 {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
770 {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 },
771 {0x14e4, 0x16a6, 0x14e4, 0x000c, 0, 0, BCM5702 },
772 {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 },
773 {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
774 {0x14e4, 0x16c6, 0x10b7, 0x1100, 0, 0, TC1000BT },
775 {0x14e4, 0x16c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 },
776 {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 },
777 {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
778 {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 },
779 {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 },
780 {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
781 {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 },
782 {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
783 {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 },
784 {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 },
785 {0x14e4, 0x16a7, 0x0e11, 0xca, 0, 0, NC7771 },
786 {0x14e4, 0x16a7, 0x0e11, 0xcb, 0, 0, NC7781 },
787 {0x14e4, 0x16a7, 0x1014, 0x0281, 0, 0, BCM5703ARBUCKLE },
788 {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
789 {0x14e4, 0x16c7, 0x14e4, 0x000a, 0, 0, BCM5703A31 },
790 {0x14e4, 0x16c7, 0x0e11, 0xca, 0, 0, NC7771 },
791 {0x14e4, 0x16c7, 0x0e11, 0xcb, 0, 0, NC7781 },
792 {0x14e4, 0x16c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 },
793 {0x14e4, 0x1648, 0x0e11, 0xcf, 0, 0, NC7772 },
794 {0x14e4, 0x1648, 0x0e11, 0xd0, 0, 0, NC7782 },
795 {0x14e4, 0x1648, 0x0e11, 0xd1, 0, 0, NC7783 },
796 {0x14e4, 0x1648, 0x10b7, 0x2000, 0, 0, TC998T },
797 {0x14e4, 0x1648, 0x10b7, 0x3000, 0, 0, TC999T },
798 {0x14e4, 0x1648, 0x1166, 0x1648, 0, 0, BCM5704CIOBE },
799 {0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 },
800 {0x14e4, 0x1649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
801 {0x14e4, 0x16a8, 0x14e4, 0x16a8, 0, 0, BCM5704S },
802 {0x14e4, 0x16a8, 0x10b7, 0x2001, 0, 0, TC998SX },
803 {0x14e4, 0x16a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S },
804 {0x14e4, 0x1653, 0x0e11, 0x00e3, 0, 0, NC7761 },
805 {0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
806 {0x14e4, 0x1654, 0x0e11, 0x00e3, 0, 0, NC7761 },
807 {0x14e4, 0x1654, 0x103c, 0x3100, 0, 0, NC1020 },
808 {0x14e4, 0x1654, 0x103c, 0x3226, 0, 0, NC150T },
809 {0x14e4, 0x1654, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 },
810 {0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
811 {0x14e4, 0x165e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M },
812 {0x14e4, 0x166e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705F },
813 {0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 },
814 {0x14e4, 0x169c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5788 },
815 {0x14e4, 0x169d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5789 },
816 {0x14e4, 0x170d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
817 {0x14e4, 0x170e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 },
818 {0x14e4, 0x1676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750 },
819 {0x14e4, 0x167c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750M },
820 {0x14e4, 0x1677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751 },
821 {0x14e4, 0x167d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751M },
822 {0x14e4, 0x167e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751F },
823 {0x14e4, 0x1658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5720 },
824 {0x14e4, 0x1659, 0x103c, 0x7031, 0, 0, NC320T },
825 {0x14e4, 0x1659, 0x103c, 0x7032, 0, 0, NC320T },
826 {0x14e4, 0x166a, 0x103c, 0x7035, 0, 0, NC325I },
827 {0x14e4, 0x166b, 0x103c, 0x7036, 0, 0, NC325I },
828 {0x14e4, 0x1668, 0x103c, 0x7039, 0, 0, NC324I },
829 {0x14e4, 0x1669, 0x103c, 0x703a, 0, 0, NC324I },
830 {0x14e4, 0x1678, 0x103c, 0x703e, 0, 0, NC326I },
831 {0x14e4, 0x1679, 0x103c, 0x703c, 0, 0, NC326I },
832 {0x14e4, 0x1659, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5721 },
833 {0x14e4, 0x16f7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753 },
834 {0x14e4, 0x16fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753M },
835 {0x14e4, 0x16fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5753F },
836 {0x14e4, 0x16dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5781 },
837 {0x14e4, 0x1600, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752 },
838 {0x14e4, 0x1601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5752M },
839 {0x14e4, 0x1668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5714 },
840 {0x14e4, 0x166a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780 },
841 {0x14e4, 0x166b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5780S },
842 {0x14e4, 0x1678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5715 },
843 {0x14e4, 0x471f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM4785 },
844 {0x14e4, 0x16ff, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5903M },
845 {0x173b, 0x03ed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, UNK5788 },
846 {0,}
847 };
848
849 MODULE_DEVICE_TABLE(pci, bcm5700_pci_tbl);
850
851 #if (LINUX_VERSION_CODE >= 0x2060a)
852 static struct pci_device_id pci_AMD762id[]={
853 { PCI_DEVICE(PCI_VENDOR_ID_AMD,
854 PCI_DEVICE_ID_AMD_FE_GATE_700C) },
855 { }
856 };
857 #endif
858
859 static int sbgige = -1;
860
861 /*******************************************************************************
862 *******************************************************************************
863 */
864
865 int get_csum_flag(LM_UINT32 ChipRevId)
866 {
867 return NETIF_F_IP_CSUM;
868 }
869
870 /*******************************************************************************
871 *******************************************************************************
872
873 This function returns true if the device passed to it is attached to an
874 ICH-ICH4. If the chip is not attached to an ICH, or is attached to an ICH5
875 or newer, it returns false.
876
877 This function determines which bridge it is attached to by scaning the pci
878 bus looking for bridge chips (hdr_type=1). When a bridge chip is detected,
879 the bridge's subordinate's secondary bus number is compared with this
880 devices bus number. If they match, then the device is attached to this
881 bridge. The bridge's device id is compared to a list of known device ids for
882 ICH-ICH4. Since many older ICH's (ICH2-ICH7) share the same device id, the
883 chip revision must also be checked to determine if the chip is older than an
884 ICH5.
885
886 To scan the bus, one of two functions is used depending on the kernel
887 version. For 2.4 kernels, the pci_find_device function is used. This
888 function has been depricated in the 2.6 kernel and replaced with the
889 fucntion pci_get_device. The macro walk_pci_bus determines which function to
890 use when the driver is built.
891 */
892
893 #if (LINUX_VERSION_CODE >= 0x2060a)
894 #define walk_pci_bus(d) while ((d = pci_get_device( \
895 PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
896
897 #define unwalk_pci_bus(d) pci_dev_put(d)
898
899 #else
900 #define walk_pci_bus(d) while ((d = pci_find_device( \
901 PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
902 #define unwalk_pci_bus(d)
903
904 #endif
905
906 #define ICH5_CHIP_VERSION 0xc0
907
908 static struct pci_device_id pci_ICHtable[] = {
909 {0x8086, 0x2418}, /* PCI_DEVICE_ID_INTEL_82801AA_8 */
910 {0x8086, 0x2428}, /* PCI_DEVICE_ID_INTEL_82801AB_8 */
911 {0x8086, 0x244e}, /* PCI_DEVICE_ID_INTEL_82801BA_6 */
912 {0x8086, 0x2448}, /* PCI_DEVICE_ID_INTEL_82801BA_11 */
913 {0, 0}
914 };
915
916 int attached_to_ICH4_or_older( struct pci_dev *pdev)
917 {
918 struct pci_dev *tmp_pdev = NULL;
919 struct pci_device_id *ich_table;
920 u8 chip_rev;
921
922 walk_pci_bus (tmp_pdev) {
923 if ((tmp_pdev->hdr_type == 1) &&
924 (tmp_pdev->subordinate != NULL) &&
925 (tmp_pdev->subordinate->secondary == pdev->bus->number)) {
926
927 ich_table = pci_ICHtable;
928
929 while (ich_table->vendor) {
930 if ((ich_table->vendor == tmp_pdev->vendor) &&
931 (ich_table->device == tmp_pdev->device)) {
932
933 pci_read_config_byte( tmp_pdev,
934 PCI_REVISION_ID, &chip_rev);
935
936 if (chip_rev < ICH5_CHIP_VERSION) {
937 unwalk_pci_bus( tmp_pdev);
938 return 1;
939 }
940 }
941 ich_table++;
942 }
943 }
944 }
945 return 0;
946 }
947
948 static void robo_set_power_mode(void *h)
949 {
950 //int status = 0;
951 int i;
952 //uint8 mode8;
953 //uint16 mode16;
954 uint32 flags = 0, temp32 = 0,val32 = 0, savephyaddr = 0;
955 PUM_DEVICE_BLOCK pudev = (PUM_DEVICE_BLOCK)h;
956 PLM_DEVICE_BLOCK pdev = &pudev->lm_dev;
957
958 /*Brcm,Alex,2006.7.20. Adding Phy power mode setting*/
959 BCM5700_PHY_LOCK(pudev, flags);
960 savephyaddr = pdev->PhyAddr;
961
962 for(i = 0; i < 8; i++)
963 {
964 pdev->PhyAddr = i;
965 temp32 = 0x2007;
966 LM_WritePhy(pdev, 0x18, temp32);
967 LM_ReadPhy(pdev, 0x18, &val32);
968 // printk(KERN_DEBUG "Alex: port = %x, read value =%x\n",i, val32);
969 temp32 = 0xc042;
970 LM_WritePhy(pdev, 0x18, temp32);
971 /*Read back*/
972 temp32 = 0x2007;
973 val32 = 0;
974 LM_WritePhy(pdev, 0x18, temp32);
975 LM_ReadPhy(pdev, 0x18, &val32);
976 // printk(KERN_ERR "Alex: read back value =%x\n",val32);
977 }
978
979 pdev->PhyAddr = savephyaddr;
980 BCM5700_PHY_UNLOCK(pudev, flags);
981
982 /*end of Brcm,Alex,2006.7.20. Adding Phy power mode setting*/
983
984 }
985
986 static int
987 __devinit bcm5700_init_board(struct pci_dev *pdev, struct net_device **dev_out, int board_idx)
988 {
989 struct net_device *dev;
990 PUM_DEVICE_BLOCK pUmDevice;
991 PLM_DEVICE_BLOCK pDevice;
992 bool rgmii = FALSE;
993 sb_t *sbh = NULL;
994 int rc;
995
996 *dev_out = NULL;
997
998 /* dev zeroed in init_etherdev */
999 #if (LINUX_VERSION_CODE >= 0x20600)
1000 dev = alloc_etherdev(sizeof(*pUmDevice));
1001 #else
1002 dev = init_etherdev(NULL, sizeof(*pUmDevice));
1003 #endif
1004 if (dev == NULL) {
1005 printk(KERN_ERR "%s: unable to alloc new ethernet\n", bcm5700_driver);
1006 return -ENOMEM;
1007 }
1008 SET_MODULE_OWNER(dev);
1009 #if (LINUX_VERSION_CODE >= 0x20600)
1010 SET_NETDEV_DEV(dev, &pdev->dev);
1011 #endif
1012 pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
1013
1014 /* enable device (incl. PCI PM wakeup), and bus-mastering */
1015 rc = pci_enable_device(pdev);
1016 if (rc)
1017 goto err_out;
1018
1019 /* init core specific stuff */
1020 if (pdev->device == T3_PCI_DEVICE_ID(T3_PCI_ID_BCM471F)) {
1021 sbh = sb_kattach(SB_OSH);
1022 sb_gige_init(sbh, ++sbgige, &rgmii);
1023 }
1024
1025 rc = pci_request_regions(pdev, bcm5700_driver);
1026 if (rc) {
1027 if (!sbh)
1028 goto err_out;
1029 printk(KERN_INFO "bcm5700_init_board: pci_request_regions returned error %d\n"
1030 "This may be because the region is already requested by"
1031 " the SMBus driver. Ignore the PCI error messages.\n", rc);
1032 }
1033
1034 pci_set_master(pdev);
1035
1036 if (pci_set_dma_mask(pdev, BCM_64BIT_DMA_MASK) == 0) {
1037 pUmDevice->using_dac = 1;
1038 if (pci_set_consistent_dma_mask(pdev, BCM_64BIT_DMA_MASK) != 0) {
1039 printk(KERN_ERR "pci_set_consistent_dma_mask failed\n");
1040 pci_release_regions(pdev);
1041 goto err_out;
1042 }
1043 } else if (pci_set_dma_mask(pdev, BCM_32BIT_DMA_MASK) == 0) {
1044 pUmDevice->using_dac = 0;
1045 } else {
1046 printk(KERN_ERR "System does not support DMA\n");
1047 pci_release_regions(pdev);
1048 goto err_out;
1049 }
1050
1051 pUmDevice->dev = dev;
1052 pUmDevice->pdev = pdev;
1053 pUmDevice->mem_list_num = 0;
1054 pUmDevice->next_module = root_tigon3_dev;
1055 pUmDevice->index = board_idx;
1056 pUmDevice->sbh = (void *)sbh;
1057 root_tigon3_dev = dev;
1058
1059 spin_lock_init(&pUmDevice->global_lock);
1060
1061 spin_lock_init(&pUmDevice->undi_lock);
1062
1063 spin_lock_init(&pUmDevice->phy_lock);
1064
1065 pDevice = &pUmDevice->lm_dev;
1066 pDevice->Flags = 0;
1067 pDevice->FunctNum = PCI_FUNC(pUmDevice->pdev->devfn);
1068 pUmDevice->boardflags = getintvar(NULL, "boardflags");
1069 if (sbh) {
1070 if (pUmDevice->boardflags & BFL_ENETROBO)
1071 pDevice->Flags |= ROBO_SWITCH_FLAG;
1072 pDevice->Flags |= rgmii ? RGMII_MODE_FLAG : 0;
1073 if (sb_chip(sbh) == BCM4785_CHIP_ID && sb_chiprev(sbh) < 2)
1074 pDevice->Flags |= ONE_DMA_AT_ONCE_FLAG;
1075 pDevice->Flags |= SB_CORE_FLAG;
1076 if (sb_chip(sbh) == BCM4785_CHIP_ID)
1077 pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
1078 }
1079
1080 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
1081 if (board_idx < MAX_UNITS) {
1082 bcm5700_validate_param_range(pUmDevice, &mtu[board_idx], "mtu", 1500, 9000, 1500);
1083 dev->mtu = mtu[board_idx];
1084 }
1085 #endif
1086
1087 if (attached_to_ICH4_or_older(pdev)) {
1088 pDevice->Flags |= UNDI_FIX_FLAG;
1089 }
1090
1091 #if (LINUX_VERSION_CODE >= 0x2060a)
1092 if (pci_dev_present(pci_AMD762id)) {
1093 pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
1094 pDevice->Flags &= ~NIC_SEND_BD_FLAG;
1095 }
1096 #else
1097 if (pci_find_device(0x1022, 0x700c, NULL)) {
1098 /* AMD762 writes I/O out of order */
1099 /* Setting bit 1 in 762's register 0x4C still doesn't work */
1100 /* in all cases */
1101 pDevice->Flags |= FLUSH_POSTED_WRITE_FLAG;
1102 pDevice->Flags &= ~NIC_SEND_BD_FLAG;
1103 }
1104 #endif
1105 if (LM_GetAdapterInfo(pDevice) != LM_STATUS_SUCCESS) {
1106 rc = -ENODEV;
1107 goto err_out_unmap;
1108 }
1109
1110 if (pDevice->Flags & ROBO_SWITCH_FLAG) {
1111 robo_info_t *robo;
1112
1113 if ((robo = bcm_robo_attach(sbh, pDevice, dev->name, NULL,
1114 robo_miird, robo_miiwr)) == NULL) {
1115 B57_ERR(("robo_setup: failed to attach robo switch \n"));
1116 goto robo_fail;
1117 }
1118
1119 if (bcm_robo_enable_device(robo)) {
1120 B57_ERR(("robo_setup: failed to enable robo switch \n"));
1121 robo_fail:
1122 bcm_robo_detach(robo);
1123 rc = -ENODEV;
1124 goto err_out_unmap;
1125 }
1126
1127 /* 5397 power mode setting */
1128 robo_set_power_mode(robo->h);
1129
1130 pUmDevice->robo = (void *)robo;
1131 }
1132
1133 if ((pDevice->Flags & JUMBO_CAPABLE_FLAG) == 0) {
1134 if (dev->mtu > 1500) {
1135 dev->mtu = 1500;
1136 printk(KERN_WARNING
1137 "%s-%d: Jumbo mtu sizes not supported, using mtu=1500\n",
1138 bcm5700_driver, pUmDevice->index);
1139 }
1140 }
1141
1142 pUmDevice->do_global_lock = 0;
1143 if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
1144 /* The 5700 chip works best without interleaved register */
1145 /* accesses on certain machines. */
1146 pUmDevice->do_global_lock = 1;
1147 }
1148
1149 if ((T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5701) &&
1150 ((pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) == 0)) {
1151
1152 pUmDevice->rx_buf_align = 0;
1153 } else {
1154 pUmDevice->rx_buf_align = 2;
1155 }
1156 dev->mem_start = pci_resource_start(pdev, 0);
1157 dev->mem_end = dev->mem_start + sizeof(T3_STD_MEM_MAP);
1158 dev->irq = pdev->irq;
1159
1160 *dev_out = dev;
1161 return 0;
1162
1163 err_out_unmap:
1164 pci_release_regions(pdev);
1165 bcm5700_freemem(dev);
1166
1167 err_out:
1168 #if (LINUX_VERSION_CODE < 0x020600)
1169 unregister_netdev(dev);
1170 kfree(dev);
1171 #else
1172 free_netdev(dev);
1173 #endif
1174 return rc;
1175 }
1176
1177 static int __devinit
1178 bcm5700_print_ver(void)
1179 {
1180 printk(KERN_INFO "Broadcom Gigabit Ethernet Driver %s ",
1181 bcm5700_driver);
1182 printk("ver. %s %s\n", bcm5700_version, bcm5700_date);
1183 return 0;
1184 }
1185
1186 static int __devinit
1187 bcm5700_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1188 {
1189 struct net_device *dev = NULL;
1190 PUM_DEVICE_BLOCK pUmDevice;
1191 PLM_DEVICE_BLOCK pDevice;
1192 int i;
1193 static int board_idx = -1;
1194 static int printed_version = 0;
1195 struct pci_dev *pci_dev;
1196
1197 board_idx++;
1198
1199 if (!printed_version) {
1200 bcm5700_print_ver();
1201 printed_version = 1;
1202 }
1203
1204 i = bcm5700_init_board(pdev, &dev, board_idx);
1205 if (i < 0) {
1206 return i;
1207 }
1208
1209 if (dev == NULL)
1210 return -ENOMEM;
1211
1212 #ifdef BCM_IOCTL32
1213 if (atomic_read(&bcm5700_load_count) == 0) {
1214 register_ioctl32_conversion(SIOCNICE, bcm5700_ioctl32);
1215 }
1216 atomic_inc(&bcm5700_load_count);
1217 #endif
1218 dev->open = bcm5700_open;
1219 dev->hard_start_xmit = bcm5700_start_xmit;
1220 dev->stop = bcm5700_close;
1221 dev->get_stats = bcm5700_get_stats;
1222 dev->set_multicast_list = bcm5700_set_rx_mode;
1223 dev->do_ioctl = bcm5700_ioctl;
1224 dev->set_mac_address = &bcm5700_set_mac_addr;
1225 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
1226 dev->change_mtu = &bcm5700_change_mtu;
1227 #endif
1228 #if (LINUX_VERSION_CODE >= 0x20400)
1229 dev->tx_timeout = bcm5700_reset;
1230 dev->watchdog_timeo = TX_TIMEOUT;
1231 #endif
1232 #ifdef BCM_VLAN
1233 dev->vlan_rx_register = &bcm5700_vlan_rx_register;
1234 dev->vlan_rx_kill_vid = &bcm5700_vlan_rx_kill_vid;
1235 #endif
1236 #ifdef BCM_NAPI_RXPOLL
1237 dev->poll = bcm5700_poll;
1238 dev->weight = 64;
1239 #endif
1240
1241 pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
1242 pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1243
1244 dev->base_addr = pci_resource_start(pdev, 0);
1245 dev->irq = pdev->irq;
1246 #if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
1247 dev->poll_controller = poll_bcm5700;
1248 #endif
1249
1250 #if (LINUX_VERSION_CODE >= 0x20600)
1251 if ((i = register_netdev(dev))) {
1252 printk(KERN_ERR "%s: Cannot register net device\n",
1253 bcm5700_driver);
1254 if (pUmDevice->lm_dev.pMappedMemBase)
1255 iounmap(pUmDevice->lm_dev.pMappedMemBase);
1256 pci_release_regions(pdev);
1257 bcm5700_freemem(dev);
1258 free_netdev(dev);
1259 return i;
1260 }
1261 #endif
1262
1263
1264 pci_set_drvdata(pdev, dev);
1265
1266 memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
1267 pUmDevice->name = board_info[ent->driver_data].name,
1268 printk(KERN_INFO "%s: %s found at mem %lx, IRQ %d, ",
1269 dev->name, pUmDevice->name, dev->base_addr,
1270 dev->irq);
1271 printk("node addr ");
1272 for (i = 0; i < 6; i++) {
1273 printk("%2.2x", dev->dev_addr[i]);
1274 }
1275 printk("\n");
1276
1277 printk(KERN_INFO "%s: ", dev->name);
1278 if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5400_PHY_ID)
1279 printk("Broadcom BCM5400 Copper ");
1280 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID)
1281 printk("Broadcom BCM5401 Copper ");
1282 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5411_PHY_ID)
1283 printk("Broadcom BCM5411 Copper ");
1284 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5461_PHY_ID)
1285 printk("Broadcom BCM5461 Copper ");
1286 else if (((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5701_PHY_ID) &&
1287 !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
1288 printk("Broadcom BCM5701 Integrated Copper ");
1289 }
1290 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5703_PHY_ID) {
1291 printk("Broadcom BCM5703 Integrated ");
1292 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
1293 printk("SerDes ");
1294 else
1295 printk("Copper ");
1296 }
1297 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5704_PHY_ID) {
1298 printk("Broadcom BCM5704 Integrated ");
1299 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
1300 printk("SerDes ");
1301 else
1302 printk("Copper ");
1303 }
1304 else if (pDevice->PhyFlags & PHY_IS_FIBER){
1305 if(( pDevice->PhyId & PHY_ID_MASK ) == PHY_BCM5780_PHY_ID)
1306 printk("Broadcom BCM5780S Integrated Serdes ");
1307
1308 }
1309 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5705_PHY_ID)
1310 printk("Broadcom BCM5705 Integrated Copper ");
1311 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5750_PHY_ID)
1312 printk("Broadcom BCM5750 Integrated Copper ");
1313
1314 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5714_PHY_ID)
1315 printk("Broadcom BCM5714 Integrated Copper ");
1316 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5780_PHY_ID)
1317 printk("Broadcom BCM5780 Integrated Copper ");
1318
1319 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5752_PHY_ID)
1320 printk("Broadcom BCM5752 Integrated Copper ");
1321 else if ((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM8002_PHY_ID)
1322 printk("Broadcom BCM8002 SerDes ");
1323 else if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
1324 if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) {
1325 printk("Broadcom BCM5703 Integrated SerDes ");
1326 }
1327 else if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
1328 printk("Broadcom BCM5704 Integrated SerDes ");
1329 }
1330 else {
1331 printk("Agilent HDMP-1636 SerDes ");
1332 }
1333 }
1334 else {
1335 printk("Unknown ");
1336 }
1337 printk("transceiver found\n");
1338
1339 #if (LINUX_VERSION_CODE >= 0x20400)
1340 if (scatter_gather[board_idx]) {
1341 dev->features |= NETIF_F_SG;
1342 if (pUmDevice->using_dac && !(pDevice->Flags & BCM5788_FLAG))
1343 dev->features |= NETIF_F_HIGHDMA;
1344 }
1345 if ((pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM) &&
1346 tx_checksum[board_idx]) {
1347
1348 dev->features |= get_csum_flag( pDevice->ChipRevId);
1349 }
1350 #ifdef BCM_VLAN
1351 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
1352 #endif
1353 #ifdef BCM_TSO
1354 /* On 5714/15/80 chips, Jumbo Frames and TSO cannot both be enabled at
1355 the same time. Since only one of these features can be enable at a
1356 time, we'll enable only Jumbo Frames and disable TSO when the user
1357 tries to enable both.
1358 */
1359 dev->features &= ~NETIF_F_TSO;
1360
1361 if ((pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION) &&
1362 (enable_tso[board_idx])) {
1363 if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
1364 (dev->mtu > 1500)) {
1365 printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
1366 } else {
1367 dev->features |= NETIF_F_TSO;
1368 }
1369 }
1370 #endif
1371 printk(KERN_INFO "%s: Scatter-gather %s, 64-bit DMA %s, Tx Checksum %s, ",
1372 dev->name,
1373 (char *) ((dev->features & NETIF_F_SG) ? "ON" : "OFF"),
1374 (char *) ((dev->features & NETIF_F_HIGHDMA) ? "ON" : "OFF"),
1375 (char *) ((dev->features & get_csum_flag( pDevice->ChipRevId)) ? "ON" : "OFF"));
1376 #endif
1377 if ((pDevice->ChipRevId != T3_CHIP_ID_5700_B0) &&
1378 rx_checksum[board_idx])
1379 printk("Rx Checksum ON");
1380 else
1381 printk("Rx Checksum OFF");
1382 #ifdef BCM_VLAN
1383 printk(", 802.1Q VLAN ON");
1384 #endif
1385 #ifdef BCM_TSO
1386 if (dev->features & NETIF_F_TSO) {
1387 printk(", TSO ON");
1388 }
1389 else
1390 #endif
1391 #ifdef BCM_NAPI_RXPOLL
1392 printk(", NAPI ON");
1393 #endif
1394 printk("\n");
1395
1396 register_reboot_notifier(&bcm5700_reboot_notifier);
1397 #ifdef BCM_TASKLET
1398 tasklet_init(&pUmDevice->tasklet, bcm5700_tasklet,
1399 (unsigned long) pUmDevice);
1400 #endif
1401 if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
1402 if ((REG_RD(pDevice, PciCfg.DualMacCtrl) &
1403 T3_DUAL_MAC_CH_CTRL_MASK) == 3) {
1404
1405 printk(KERN_WARNING "%s: Device is configured for Hardware Based Teaming which is not supported with this operating system. Please consult the user diagnostic guide to disable Turbo Teaming.\n", dev->name);
1406 }
1407 }
1408
1409 #if (LINUX_VERSION_CODE > 0x20605)
1410
1411 if ((pci_dev = pci_get_device(0x1022, 0x700c, NULL)))
1412 #else
1413 if ((pci_dev = pci_find_device(0x1022, 0x700c, NULL)))
1414 #endif
1415 {
1416 u32 val;
1417
1418 /* Found AMD 762 North bridge */
1419 pci_read_config_dword(pci_dev, 0x4c, &val);
1420 if ((val & 0x02) == 0) {
1421 pci_write_config_dword(pci_dev, 0x4c, val | 0x02);
1422 printk(KERN_INFO "%s: Setting AMD762 Northbridge to enable PCI ordering compliance\n", bcm5700_driver);
1423 }
1424 }
1425
1426 #if (LINUX_VERSION_CODE > 0x20605)
1427
1428 pci_dev_put(pci_dev);
1429
1430 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1431
1432 if ((pci_dev = pci_get_device(0x1066, 0x0017, NULL))) {
1433 bcm_msi_chipset_bug = 1;
1434 }
1435 pci_dev_put(pci_dev);
1436 #endif
1437 #endif
1438
1439 return 0;
1440 }
1441
1442
1443 static void __devexit
1444 bcm5700_remove_one (struct pci_dev *pdev)
1445 {
1446 struct net_device *dev = pci_get_drvdata (pdev);
1447 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1448
1449 #ifdef BCM_IOCTL32
1450 atomic_dec(&bcm5700_load_count);
1451 if (atomic_read(&bcm5700_load_count) == 0)
1452 unregister_ioctl32_conversion(SIOCNICE);
1453 #endif
1454 unregister_netdev(dev);
1455
1456 if (pUmDevice->lm_dev.pMappedMemBase)
1457 iounmap(pUmDevice->lm_dev.pMappedMemBase);
1458
1459 pci_release_regions(pdev);
1460
1461 #if (LINUX_VERSION_CODE < 0x020600)
1462 kfree(dev);
1463 #else
1464 free_netdev(dev);
1465 #endif
1466
1467 pci_set_drvdata(pdev, NULL);
1468
1469 }
1470
1471 int b57_test_intr(UM_DEVICE_BLOCK *pUmDevice);
1472
1473 #ifdef BCM_WL_EMULATOR
1474 /* new transmit callback */
1475 static int bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev);
1476 /* keep track of the 2 gige devices */
1477 static PLM_DEVICE_BLOCK pDev1;
1478 static PLM_DEVICE_BLOCK pDev2;
1479
1480 static void
1481 bcm5700emu_open(struct net_device *dev)
1482 {
1483 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1484 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1485 static int instance = 0;
1486 static char *wlemu_if = NULL;
1487 char *wlemu_mode = NULL;
1488 //int wlemu_idx = 0;
1489 static int rx_enable = 0;
1490 static int tx_enable = 0;
1491
1492 /* which interface is the emulator ? */
1493 if(instance == 0) {
1494 wlemu_if = nvram_get("wlemu_if");
1495 /* do we emulate rx, tx or both */
1496 wlemu_mode = nvram_get("wlemu_mode");
1497 if(wlemu_mode) {
1498 if (!strcmp(wlemu_mode,"rx"))
1499 {
1500 rx_enable = 1;
1501 }
1502 else if (!strcmp(wlemu_mode,"tx"))
1503 {
1504
1505 tx_enable = 1;
1506
1507 }
1508 else if (!strcmp(wlemu_mode,"rx_tx"))
1509 {
1510
1511 rx_enable = 1;
1512 tx_enable = 1;
1513 }
1514 }
1515 }
1516
1517 instance++;
1518
1519 /* The context is used for accessing the OSL for emulating devices */
1520 pDevice->wlc = NULL;
1521
1522 /* determines if this device is an emulator */
1523 pDevice->wl_emulate_rx = 0;
1524 pDevice->wl_emulate_tx = 0;
1525
1526 if(wlemu_if && !strcmp(dev->name,wlemu_if))
1527 {
1528 /* create an emulator context. */
1529 pDevice->wlc = (void *)wlcemu_wlccreate((void *)dev);
1530 B57_INFO(("Using %s for wl emulation \n", dev->name));
1531 if(rx_enable)
1532 {
1533 B57_INFO(("Enabling wl RX emulation \n"));
1534 pDevice->wl_emulate_rx = 1;
1535 }
1536 /* re-direct transmit callback to emulator */
1537 if(tx_enable)
1538 {
1539 pDevice->wl_emulate_tx = 1;
1540 dev->hard_start_xmit = bcm5700emu_start_xmit;
1541 B57_INFO(("Enabling wl TX emulation \n"));
1542 }
1543 }
1544 /* for debug access to configured devices only */
1545 if(instance == 1)
1546 pDev1 = pDevice;
1547 else if (instance == 2)
1548 pDev2 = pDevice;
1549 }
1550
1551 /* Public API to get current emulation info */
1552 int bcm5700emu_get_info(char *buf)
1553 {
1554 int len = 0;
1555 PLM_DEVICE_BLOCK p;
1556
1557 /* look for an emulating device */
1558 if(pDev1->wlc) {
1559 p = pDev1;
1560 len += sprintf(buf+len,"emulation device : eth0\n");
1561 }
1562 else if (pDev2->wlc) {
1563 p = pDev2;
1564 len += sprintf(buf+len,"emulation device : eth1\n");
1565 }
1566 else {
1567 len += sprintf(buf+len,"emulation not activated\n");
1568 return len;
1569 }
1570 if(p->wl_emulate_rx)
1571 len += sprintf(buf+len,"RX emulation enabled\n");
1572 else
1573 len += sprintf(buf+len,"RX emulation disabled\n");
1574 if(p->wl_emulate_tx)
1575 len += sprintf(buf+len,"TX emulation enabled\n");
1576 else
1577 len += sprintf(buf+len,"TX emulation disabled\n");
1578 return len;
1579
1580 }
1581
1582
1583 /* Public API to access the bcm5700_start_xmit callback */
1584
1585 int
1586 bcm5700emu_forward_xmit(struct sk_buff *skb, struct net_device *dev)
1587 {
1588 return bcm5700_start_xmit(skb, dev);
1589 }
1590
1591
1592 /* hook to kernel txmit callback */
1593 STATIC int
1594 bcm5700emu_start_xmit(struct sk_buff *skb, struct net_device *dev)
1595 {
1596
1597 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1598 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1599 return wlcemu_start_xmit(skb,pDevice->wlc);
1600 }
1601
1602 #endif /* BCM_WL_EMULATOR */
1603
1604 int
1605 bcm5700_open(struct net_device *dev)
1606 {
1607 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1608 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1609 int rc;
1610
1611 if (pUmDevice->suspended){
1612 return -EAGAIN;
1613 }
1614
1615 #ifdef BCM_WL_EMULATOR
1616 bcm5700emu_open(dev);
1617 #endif
1618
1619 /* delay for 6 seconds */
1620 pUmDevice->delayed_link_ind = (6 * HZ) / pUmDevice->timer_interval;
1621
1622 #ifdef BCM_INT_COAL
1623 #ifndef BCM_NAPI_RXPOLL
1624 pUmDevice->adaptive_expiry = HZ / pUmDevice->timer_interval;
1625 #endif
1626 #endif
1627
1628 #ifdef INCLUDE_TBI_SUPPORT
1629 if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
1630 (pDevice->TbiFlags & TBI_POLLING_FLAGS)) {
1631 pUmDevice->poll_tbi_interval = HZ / pUmDevice->timer_interval;
1632 if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) {
1633 pUmDevice->poll_tbi_interval /= 4;
1634 }
1635 pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval;
1636 }
1637 #endif
1638 /* set this timer for 2 seconds */
1639 pUmDevice->asf_heartbeat = (2 * HZ) / pUmDevice->timer_interval;
1640
1641 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1642
1643
1644 if ( ( (T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ) &&
1645 (T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5714_A0 ) &&
1646 (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_AX ) &&
1647 (T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5750_BX ) ) &&
1648 !bcm_msi_chipset_bug ){
1649
1650 if (disable_msi[pUmDevice->index]==1){
1651 /* do nothing-it's not turned on */
1652 }else{
1653 pDevice->Flags |= USING_MSI_FLAG;
1654
1655 REG_WR(pDevice, Msi.Mode, 2 );
1656
1657 rc = pci_enable_msi(pUmDevice->pdev);
1658
1659 if(rc!=0){
1660 pDevice->Flags &= ~ USING_MSI_FLAG;
1661 REG_WR(pDevice, Msi.Mode, 1 );
1662 }
1663 }
1664 }
1665
1666
1667 #endif
1668
1669 if ((rc= request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt, SA_SHIRQ, dev->name, dev)))
1670 {
1671
1672 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1673
1674 if(pDevice->Flags & USING_MSI_FLAG) {
1675
1676 pci_disable_msi(pUmDevice->pdev);
1677 pDevice->Flags &= ~USING_MSI_FLAG;
1678 REG_WR(pDevice, Msi.Mode, 1 );
1679
1680 }
1681 #endif
1682 return rc;
1683 }
1684
1685 pUmDevice->opened = 1;
1686 if (LM_InitializeAdapter(pDevice) != LM_STATUS_SUCCESS) {
1687 pUmDevice->opened = 0;
1688 free_irq(dev->irq, dev);
1689 bcm5700_freemem(dev);
1690 return -EAGAIN;
1691 }
1692
1693 bcm5700_set_vlan_mode(pUmDevice);
1694 bcm5700_init_counters(pUmDevice);
1695
1696 if (pDevice->Flags & UNDI_FIX_FLAG) {
1697 printk(KERN_INFO "%s: Using indirect register access\n", dev->name);
1698 }
1699
1700 if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6))
1701 {
1702 /* Do not use invalid eth addrs: any multicast & all zeros */
1703 if( is_valid_ether_addr(dev->dev_addr) ){
1704 LM_SetMacAddress(pDevice, dev->dev_addr);
1705 }
1706 else
1707 {
1708 printk(KERN_INFO "%s: Invalid administered node address\n",dev->name);
1709 memcpy(dev->dev_addr, pDevice->NodeAddress, 6);
1710 }
1711 }
1712
1713 if (tigon3_debug > 1)
1714 printk(KERN_DEBUG "%s: tigon3_open() irq %d.\n", dev->name, dev->irq);
1715
1716 QQ_InitQueue(&pUmDevice->rx_out_of_buf_q.Container,
1717 MAX_RX_PACKET_DESC_COUNT);
1718
1719
1720 #if (LINUX_VERSION_CODE < 0x020300)
1721 MOD_INC_USE_COUNT;
1722 #endif
1723
1724 atomic_set(&pUmDevice->intr_sem, 0);
1725
1726 LM_EnableInterrupt(pDevice);
1727
1728 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
1729
1730 if (pDevice->Flags & USING_MSI_FLAG){
1731
1732 /* int test to check support on older machines */
1733 if (b57_test_intr(pUmDevice) != 1) {
1734
1735 LM_DisableInterrupt(pDevice);
1736 free_irq(pUmDevice->pdev->irq, dev);
1737 pci_disable_msi(pUmDevice->pdev);
1738 REG_WR(pDevice, Msi.Mode, 1 );
1739 pDevice->Flags &= ~USING_MSI_FLAG;
1740
1741 rc = LM_ResetAdapter(pDevice);
1742 printk(KERN_ALERT " The MSI support in this system is not functional.\n");
1743
1744 if (rc == LM_STATUS_SUCCESS)
1745 rc = 0;
1746 else
1747 rc = -ENODEV;
1748
1749 if(rc == 0){
1750 rc = request_irq(pUmDevice->pdev->irq, &bcm5700_interrupt,
1751 SA_SHIRQ, dev->name, dev);
1752 }
1753
1754 if(rc){
1755 LM_Halt(pDevice);
1756 bcm5700_freemem(dev);
1757 pUmDevice->opened = 0;
1758 return rc;
1759 }
1760
1761
1762 pDevice->InitDone = TRUE;
1763 atomic_set(&pUmDevice->intr_sem, 0);
1764 LM_EnableInterrupt(pDevice);
1765 }
1766 }
1767 #endif
1768
1769 init_timer(&pUmDevice->timer);
1770 pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
1771 pUmDevice->timer.data = (unsigned long)dev;
1772 pUmDevice->timer.function = &bcm5700_timer;
1773 add_timer(&pUmDevice->timer);
1774
1775 if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
1776 init_timer(&pUmDevice->statstimer);
1777 pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval);
1778 pUmDevice->statstimer.data = (unsigned long)dev;
1779 pUmDevice->statstimer.function = &bcm5700_stats_timer;
1780 add_timer(&pUmDevice->statstimer);
1781 }
1782
1783 if(pDevice->Flags & USING_MSI_FLAG)
1784 printk(KERN_INFO "%s: Using Message Signaled Interrupt (MSI) \n", dev->name);
1785 else
1786 printk(KERN_INFO "%s: Using PCI INTX interrupt \n", dev->name);
1787
1788 netif_start_queue(dev);
1789
1790 return 0;
1791 }
1792
1793
1794 STATIC void
1795 bcm5700_stats_timer(unsigned long data)
1796 {
1797 struct net_device *dev = (struct net_device *)data;
1798 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1799 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1800 unsigned long flags = 0;
1801
1802 if (!pUmDevice->opened)
1803 return;
1804
1805 if (!atomic_read(&pUmDevice->intr_sem) &&
1806 !pUmDevice->suspended &&
1807 (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE)) {
1808 BCM5700_LOCK(pUmDevice, flags);
1809 LM_GetStats(pDevice);
1810 BCM5700_UNLOCK(pUmDevice, flags);
1811 }
1812
1813 pUmDevice->statstimer.expires = RUN_AT(pUmDevice->statstimer_interval);
1814
1815 add_timer(&pUmDevice->statstimer);
1816 }
1817
1818
1819 STATIC void
1820 bcm5700_timer(unsigned long data)
1821 {
1822 struct net_device *dev = (struct net_device *)data;
1823 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
1824 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
1825 unsigned long flags = 0;
1826 LM_UINT32 value32;
1827
1828 if (!pUmDevice->opened)
1829 return;
1830
1831 /* BCM4785: Flush posted writes from GbE to host memory. */
1832 if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
1833 REG_RD(pDevice, HostCoalesce.Mode);
1834
1835 if (atomic_read(&pUmDevice->intr_sem) || pUmDevice->suspended) {
1836 pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
1837 add_timer(&pUmDevice->timer);
1838 return;
1839 }
1840
1841 #ifdef INCLUDE_TBI_SUPPORT
1842 if ((pDevice->TbiFlags & TBI_POLLING_FLAGS) &&
1843 (--pUmDevice->poll_tbi_expiry <= 0)) {
1844
1845 BCM5700_PHY_LOCK(pUmDevice, flags);
1846 value32 = REG_RD(pDevice, MacCtrl.Status);
1847 if (((pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) &&
1848 ((value32 & (MAC_STATUS_LINK_STATE_CHANGED |
1849 MAC_STATUS_CFG_CHANGED)) ||
1850 !(value32 & MAC_STATUS_PCS_SYNCED)))
1851 ||
1852 ((pDevice->LinkStatus != LM_STATUS_LINK_ACTIVE) &&
1853 (value32 & (MAC_STATUS_PCS_SYNCED |
1854 MAC_STATUS_SIGNAL_DETECTED))))
1855 {
1856 LM_SetupPhy(pDevice);
1857 }
1858 BCM5700_PHY_UNLOCK(pUmDevice, flags);
1859 pUmDevice->poll_tbi_expiry = pUmDevice->poll_tbi_interval;
1860
1861 }
1862 #endif
1863
1864 if (pUmDevice->delayed_link_ind > 0) {
1865 if (pUmDevice->delayed_link_ind == 1)
1866 MM_IndicateStatus(pDevice, pDevice->LinkStatus);
1867 else
1868 pUmDevice->delayed_link_ind--;
1869 }
1870
1871 if (pUmDevice->crc_counter_expiry > 0)
1872 pUmDevice->crc_counter_expiry--;
1873
1874 if (!pUmDevice->interrupt) {
1875 if (!(pDevice->Flags & USE_TAGGED_STATUS_FLAG)) {
1876 BCM5700_LOCK(pUmDevice, flags);
1877 if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) {
1878 /* This will generate an interrupt */
1879 REG_WR(pDevice, Grc.LocalCtrl,
1880 pDevice->GrcLocalCtrl |
1881 GRC_MISC_LOCAL_CTRL_SET_INT);
1882 }
1883 else {
1884 REG_WR(pDevice, HostCoalesce.Mode,
1885 pDevice->CoalesceMode |
1886 HOST_COALESCE_ENABLE |
1887 HOST_COALESCE_NOW);
1888 }
1889 if (!(REG_RD(pDevice, DmaWrite.Mode) &
1890 DMA_WRITE_MODE_ENABLE)) {
1891 BCM5700_UNLOCK(pUmDevice, flags);
1892 bcm5700_reset(dev);
1893 }
1894 else {
1895 BCM5700_UNLOCK(pUmDevice, flags);
1896 }
1897 if (pUmDevice->tx_queued) {
1898 pUmDevice->tx_queued = 0;
1899 netif_wake_queue(dev);
1900 }
1901 }
1902 #if (LINUX_VERSION_CODE < 0x02032b)
1903 if ((QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) !=
1904 pDevice->TxPacketDescCnt) &&
1905 ((jiffies - dev->trans_start) > TX_TIMEOUT)) {
1906
1907 printk(KERN_WARNING "%s: Tx hung\n", dev->name);
1908 bcm5700_reset(dev);
1909 }
1910 #endif
1911 }
1912 #ifdef BCM_INT_COAL
1913 #ifndef BCM_NAPI_RXPOLL
1914 if (pUmDevice->adaptive_coalesce) {
1915 pUmDevice->adaptive_expiry--;
1916 if (pUmDevice->adaptive_expiry == 0) {
1917 pUmDevice->adaptive_expiry = HZ /
1918 pUmDevice->timer_interval;
1919 bcm5700_adapt_coalesce(pUmDevice);
1920 }
1921 }
1922 #endif
1923 #endif
1924 if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container) >
1925 (unsigned int) pUmDevice->rx_buf_repl_panic_thresh) {
1926 /* Generate interrupt and let isr allocate buffers */
1927 REG_WR(pDevice, HostCoalesce.Mode, pDevice->CoalesceMode |
1928 HOST_COALESCE_ENABLE | HOST_COALESCE_NOW);
1929 }
1930
1931 #ifdef BCM_ASF
1932 if (pDevice->AsfFlags & ASF_ENABLED) {
1933 pUmDevice->asf_heartbeat--;
1934 if (pUmDevice->asf_heartbeat == 0) {
1935 if( (pDevice->Flags & UNDI_FIX_FLAG) ||
1936 (pDevice->Flags & ENABLE_PCIX_FIX_FLAG)) {
1937 MEM_WR_OFFSET(pDevice, T3_CMD_MAILBOX,
1938 T3_CMD_NICDRV_ALIVE2);
1939 MEM_WR_OFFSET(pDevice, T3_CMD_LENGTH_MAILBOX,
1940 4);
1941 MEM_WR_OFFSET(pDevice, T3_CMD_DATA_MAILBOX, 5);
1942 } else {
1943 LM_RegWr(pDevice,
1944 (T3_NIC_MBUF_POOL_ADDR +
1945 T3_CMD_MAILBOX),
1946 T3_CMD_NICDRV_ALIVE2, 1);
1947 LM_RegWr(pDevice,
1948 (T3_NIC_MBUF_POOL_ADDR +
1949 T3_CMD_LENGTH_MAILBOX),4,1);
1950 LM_RegWr(pDevice,
1951 (T3_NIC_MBUF_POOL_ADDR +
1952 T3_CMD_DATA_MAILBOX),5,1);
1953 }
1954
1955 value32 = REG_RD(pDevice, Grc.RxCpuEvent);
1956 REG_WR(pDevice, Grc.RxCpuEvent, value32 | BIT_14);
1957 pUmDevice->asf_heartbeat = (2 * HZ) /
1958 pUmDevice->timer_interval;
1959 }
1960 }
1961 #endif
1962
1963 if (pDevice->PhyFlags & PHY_IS_FIBER){
1964 BCM5700_PHY_LOCK(pUmDevice, flags);
1965 LM_5714_FamFiberCheckLink(pDevice);
1966 BCM5700_PHY_UNLOCK(pUmDevice, flags);
1967 }
1968
1969 pUmDevice->timer.expires = RUN_AT(pUmDevice->timer_interval);
1970 add_timer(&pUmDevice->timer);
1971 }
1972
1973 STATIC int
1974 bcm5700_init_counters(PUM_DEVICE_BLOCK pUmDevice)
1975 {
1976 #ifdef BCM_INT_COAL
1977 #ifndef BCM_NAPI_RXPOLL
1978 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
1979
1980 pUmDevice->rx_curr_coalesce_frames = pDevice->RxMaxCoalescedFrames;
1981 pUmDevice->rx_curr_coalesce_ticks = pDevice->RxCoalescingTicks;
1982 pUmDevice->tx_curr_coalesce_frames = pDevice->TxMaxCoalescedFrames;
1983 pUmDevice->rx_last_cnt = 0;
1984 pUmDevice->tx_last_cnt = 0;
1985 #endif
1986 #endif
1987 pUmDevice->phy_crc_count = 0;
1988 #if TIGON3_DEBUG
1989 pUmDevice->tx_zc_count = 0;
1990 pUmDevice->tx_chksum_count = 0;
1991 pUmDevice->tx_himem_count = 0;
1992 pUmDevice->rx_good_chksum_count = 0;
1993 pUmDevice->rx_bad_chksum_count = 0;
1994 #endif
1995 #ifdef BCM_TSO
1996 pUmDevice->tso_pkt_count = 0;
1997 #endif
1998 return 0;
1999 }
2000
2001 #ifdef BCM_INT_COAL
2002 #ifndef BCM_NAPI_RXPOLL
2003 STATIC int
2004 bcm5700_do_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice,
2005 int rx_frames, int rx_ticks, int tx_frames, int rx_frames_intr)
2006 {
2007 unsigned long flags = 0;
2008 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2009
2010 if (pUmDevice->do_global_lock) {
2011 if (spin_is_locked(&pUmDevice->global_lock))
2012 return 0;
2013 spin_lock_irqsave(&pUmDevice->global_lock, flags);
2014 }
2015 pUmDevice->rx_curr_coalesce_frames = rx_frames;
2016 pUmDevice->rx_curr_coalesce_ticks = rx_ticks;
2017 pUmDevice->tx_curr_coalesce_frames = tx_frames;
2018 pUmDevice->rx_curr_coalesce_frames_intr = rx_frames_intr;
2019 REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames, rx_frames);
2020
2021 REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, rx_ticks);
2022
2023 REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames, tx_frames);
2024
2025 REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt,
2026 rx_frames_intr);
2027
2028 BCM5700_UNLOCK(pUmDevice, flags);
2029 return 0;
2030 }
2031
2032 STATIC int
2033 bcm5700_adapt_coalesce(PUM_DEVICE_BLOCK pUmDevice)
2034 {
2035 PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
2036 uint rx_curr_cnt, tx_curr_cnt, rx_delta, tx_delta, total_delta;
2037
2038 rx_curr_cnt = pDevice->pStatsBlkVirt->ifHCInUcastPkts.Low;
2039 tx_curr_cnt = pDevice->pStatsBlkVirt->ifHCOutUcastPkts.Low;
2040 if ((rx_curr_cnt <= pUmDevice->rx_last_cnt) ||
2041 (tx_curr_cnt < pUmDevice->tx_last_cnt)) {
2042
2043 /* skip if there is counter rollover */
2044 pUmDevice->rx_last_cnt = rx_curr_cnt;
2045 pUmDevice->tx_last_cnt = tx_curr_cnt;
2046 return 0;
2047 }
2048
2049 rx_delta = rx_curr_cnt - pUmDevice->rx_last_cnt;
2050 tx_delta = tx_curr_cnt - pUmDevice->tx_last_cnt;
2051 total_delta = (((rx_delta + rx_delta) + tx_delta) / 3) << 1;
2052
2053 pUmDevice->rx_last_cnt = rx_curr_cnt;
2054 pUmDevice->tx_last_cnt = tx_curr_cnt;
2055
2056 if (total_delta < ADAPTIVE_LO_PKT_THRESH) {
2057 if (pUmDevice->rx_curr_coalesce_frames !=
2058 ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES) {
2059
2060 bcm5700_do_adapt_coalesce(pUmDevice,
2061 ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES,
2062 ADAPTIVE_LO_RX_COALESCING_TICKS,
2063 ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES,
2064 ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES_DURING_INT);
2065 }
2066 }
2067 else if (total_delta < ADAPTIVE_HI_PKT_THRESH) {
2068 if (pUmDevice->rx_curr_coalesce_frames !=
2069 DEFAULT_RX_MAX_COALESCED_FRAMES) {
2070
2071 bcm5700_do_adapt_coalesce(pUmDevice,
2072 DEFAULT_RX_MAX_COALESCED_FRAMES,
2073 DEFAULT_RX_COALESCING_TICKS,
2074 DEFAULT_TX_MAX_COALESCED_FRAMES,
2075 DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT);
2076 }
2077 }
2078 else {
2079 if (pUmDevice->rx_curr_coalesce_frames !=
2080 ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES) {
2081
2082 bcm5700_do_adapt_coalesce(pUmDevice,
2083 ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES,
2084 ADAPTIVE_HI_RX_COALESCING_TICKS,
2085 ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES,
2086 ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES_DURING_INT);
2087 }
2088 }
2089 return 0;
2090 }
2091 #endif
2092 #endif
2093
2094 STATIC void
2095 bcm5700_reset(struct net_device *dev)
2096 {
2097 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2098 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2099 unsigned long flags;
2100
2101 #ifdef BCM_TSO
2102
2103 if( (dev->features & NETIF_F_TSO) &&
2104 (pUmDevice->tx_full) ) {
2105
2106 dev->features &= ~NETIF_F_TSO;
2107 }
2108 #endif
2109
2110 netif_stop_queue(dev);
2111 bcm5700_intr_off(pUmDevice);
2112 BCM5700_PHY_LOCK(pUmDevice, flags);
2113 LM_ResetAdapter(pDevice);
2114 pDevice->InitDone = TRUE;
2115 bcm5700_do_rx_mode(dev);
2116 bcm5700_set_vlan_mode(pUmDevice);
2117 bcm5700_init_counters(pUmDevice);
2118 if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
2119 LM_SetMacAddress(pDevice, dev->dev_addr);
2120 }
2121 BCM5700_PHY_UNLOCK(pUmDevice, flags);
2122 atomic_set(&pUmDevice->intr_sem, 1);
2123 bcm5700_intr_on(pUmDevice);
2124 netif_wake_queue(dev);
2125 }
2126
2127 STATIC void
2128 bcm5700_set_vlan_mode(UM_DEVICE_BLOCK *pUmDevice)
2129 {
2130 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2131 LM_UINT32 ReceiveMask = pDevice->ReceiveMask;
2132 int vlan_tag_mode = pUmDevice->vlan_tag_mode;
2133
2134 if (vlan_tag_mode == VLAN_TAG_MODE_AUTO_STRIP) {
2135 if (pDevice->AsfFlags & ASF_ENABLED) {
2136 vlan_tag_mode = VLAN_TAG_MODE_FORCED_STRIP;
2137 }
2138 else {
2139 vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP;
2140 }
2141 }
2142 if (vlan_tag_mode == VLAN_TAG_MODE_NORMAL_STRIP) {
2143 ReceiveMask |= LM_KEEP_VLAN_TAG;
2144 #ifdef BCM_VLAN
2145 if (pUmDevice->vlgrp)
2146 ReceiveMask &= ~LM_KEEP_VLAN_TAG;
2147 #endif
2148 }
2149 else if (vlan_tag_mode == VLAN_TAG_MODE_FORCED_STRIP) {
2150 ReceiveMask &= ~LM_KEEP_VLAN_TAG;
2151 }
2152 if (ReceiveMask != pDevice->ReceiveMask)
2153 {
2154 LM_SetReceiveMask(pDevice, ReceiveMask);
2155 }
2156 }
2157
2158 static void
2159 bcm5700_poll_wait(UM_DEVICE_BLOCK *pUmDevice)
2160 {
2161 #ifdef BCM_NAPI_RXPOLL
2162 while (pUmDevice->lm_dev.RxPoll) {
2163 current->state = TASK_INTERRUPTIBLE;
2164 schedule_timeout(1);
2165 }
2166 #endif
2167 }
2168
2169
2170 #ifdef BCM_VLAN
2171 STATIC void
2172 bcm5700_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
2173 {
2174 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
2175
2176 bcm5700_intr_off(pUmDevice);
2177 bcm5700_poll_wait(pUmDevice);
2178 pUmDevice->vlgrp = vlgrp;
2179 bcm5700_set_vlan_mode(pUmDevice);
2180 bcm5700_intr_on(pUmDevice);
2181 }
2182
2183 STATIC void
2184 bcm5700_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
2185 {
2186 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
2187
2188 bcm5700_intr_off(pUmDevice);
2189 bcm5700_poll_wait(pUmDevice);
2190 if (pUmDevice->vlgrp) {
2191 pUmDevice->vlgrp->vlan_devices[vid] = NULL;
2192 }
2193 bcm5700_intr_on(pUmDevice);
2194 }
2195 #endif
2196
2197 STATIC int
2198 bcm5700_start_xmit(struct sk_buff *skb, struct net_device *dev)
2199 {
2200 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2201 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2202 PLM_PACKET pPacket;
2203 PUM_PACKET pUmPacket;
2204 unsigned long flags = 0;
2205 int frag_no;
2206 #ifdef BCM_TSO
2207 LM_UINT32 mss = 0 ;
2208 uint16_t ip_tcp_len, tcp_opt_len, tcp_seg_flags;
2209 #endif
2210
2211 if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) ||
2212 !pDevice->InitDone || pUmDevice->suspended)
2213 {
2214 dev_kfree_skb(skb);
2215 return 0;
2216 }
2217
2218 #if (LINUX_VERSION_CODE < 0x02032b)
2219 if (test_and_set_bit(0, &dev->tbusy)) {
2220 return 1;
2221 }
2222 #endif
2223
2224 if (pUmDevice->do_global_lock && pUmDevice->interrupt) {
2225 netif_stop_queue(dev);
2226 pUmDevice->tx_queued = 1;
2227 if (!pUmDevice->interrupt) {
2228 netif_wake_queue(dev);
2229 pUmDevice->tx_queued = 0;
2230 }
2231 return 1;
2232 }
2233
2234 pPacket = (PLM_PACKET)
2235 QQ_PopHead(&pDevice->TxPacketFreeQ.Container);
2236 if (pPacket == 0) {
2237 netif_stop_queue(dev);
2238 pUmDevice->tx_full = 1;
2239 if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container)) {
2240 netif_wake_queue(dev);
2241 pUmDevice->tx_full = 0;
2242 }
2243 return 1;
2244 }
2245 pUmPacket = (PUM_PACKET) pPacket;
2246 pUmPacket->skbuff = skb;
2247 pUmDevice->stats.tx_bytes += skb->len;
2248
2249 if (skb->ip_summed == CHECKSUM_HW) {
2250 pPacket->Flags = SND_BD_FLAG_TCP_UDP_CKSUM;
2251 #if TIGON3_DEBUG
2252 pUmDevice->tx_chksum_count++;
2253 #endif
2254 }
2255 else {
2256 pPacket->Flags = 0;
2257 }
2258 #if MAX_SKB_FRAGS
2259 frag_no = skb_shinfo(skb)->nr_frags;
2260 #else
2261 frag_no = 0;
2262 #endif
2263 if (atomic_read(&pDevice->SendBdLeft) < (frag_no + 1)) {
2264 netif_stop_queue(dev);
2265 pUmDevice->tx_full = 1;
2266 QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket);
2267 if (atomic_read(&pDevice->SendBdLeft) >= (frag_no + 1)) {
2268 netif_wake_queue(dev);
2269 pUmDevice->tx_full = 0;
2270 }
2271 return 1;
2272 }
2273
2274 pPacket->u.Tx.FragCount = frag_no + 1;
2275 #if TIGON3_DEBUG
2276 if (pPacket->u.Tx.FragCount > 1)
2277 pUmDevice->tx_zc_count++;
2278 #endif
2279
2280 #ifdef BCM_VLAN
2281 if (pUmDevice->vlgrp && vlan_tx_tag_present(skb)) {
2282 pPacket->VlanTag = vlan_tx_tag_get(skb);
2283 pPacket->Flags |= SND_BD_FLAG_VLAN_TAG;
2284 }
2285 #endif
2286
2287 #ifdef BCM_TSO
2288 if ((mss = (LM_UINT32) skb_shinfo(skb)->tso_size) &&
2289 (skb->len > pDevice->TxMtu)) {
2290
2291 #if (LINUX_VERSION_CODE >= 0x02060c)
2292
2293 if (skb_header_cloned(skb) &&
2294 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
2295
2296 dev_kfree_skb(skb);
2297 return 0;
2298 }
2299 #endif
2300 pUmDevice->tso_pkt_count++;
2301
2302 pPacket->Flags |= SND_BD_FLAG_CPU_PRE_DMA |
2303 SND_BD_FLAG_CPU_POST_DMA;
2304
2305 tcp_opt_len = 0;
2306 if (skb->h.th->doff > 5) {
2307 tcp_opt_len = (skb->h.th->doff - 5) << 2;
2308 }
2309 ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
2310 skb->nh.iph->check = 0;
2311
2312 if ( T3_ASIC_IS_575X_PLUS(pDevice->ChipRevId) ){
2313 skb->h.th->check = 0;
2314 pPacket->Flags &= ~SND_BD_FLAG_TCP_UDP_CKSUM;
2315 }
2316 else {
2317 skb->h.th->check = ~csum_tcpudp_magic(
2318 skb->nh.iph->saddr, skb->nh.iph->daddr,
2319 0, IPPROTO_TCP, 0);
2320 }
2321
2322 skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
2323 tcp_seg_flags = 0;
2324
2325 if (tcp_opt_len || (skb->nh.iph->ihl > 5)) {
2326 if ( T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId) ){
2327 tcp_seg_flags =
2328 ((skb->nh.iph->ihl - 5) +
2329 (tcp_opt_len >> 2)) << 11;
2330 }
2331 else {
2332 pPacket->Flags |=
2333 ((skb->nh.iph->ihl - 5) +
2334 (tcp_opt_len >> 2)) << 12;
2335 }
2336 }
2337 pPacket->u.Tx.MaxSegmentSize = mss | tcp_seg_flags;
2338 }
2339 else
2340 {
2341 pPacket->u.Tx.MaxSegmentSize = 0;
2342 }
2343 #endif
2344 BCM5700_LOCK(pUmDevice, flags);
2345 LM_SendPacket(pDevice, pPacket);
2346 BCM5700_UNLOCK(pUmDevice, flags);
2347
2348 #if (LINUX_VERSION_CODE < 0x02032b)
2349 netif_wake_queue(dev);
2350 #endif
2351 dev->trans_start = jiffies;
2352
2353
2354 return 0;
2355 }
2356
2357 #ifdef BCM_NAPI_RXPOLL
2358 STATIC int
2359 bcm5700_poll(struct net_device *dev, int *budget)
2360 {
2361 int orig_budget = *budget;
2362 int work_done;
2363 UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) dev->priv;
2364 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2365 unsigned long flags = 0;
2366 LM_UINT32 tag;
2367
2368 if (orig_budget > dev->quota)
2369 orig_budget = dev->quota;
2370
2371 BCM5700_LOCK(pUmDevice, flags);
2372 /* BCM4785: Flush posted writes from GbE to host memory. */
2373 if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
2374 REG_RD(pDevice, HostCoalesce.Mode);
2375 work_done = LM_ServiceRxPoll(pDevice, orig_budget);
2376 *budget -= work_done;
2377 dev->quota -= work_done;
2378
2379 if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
2380 replenish_rx_buffers(pUmDevice, 0);
2381 }
2382 BCM5700_UNLOCK(pUmDevice, flags);
2383 if (work_done) {
2384 MM_IndicateRxPackets(pDevice);
2385 BCM5700_LOCK(pUmDevice, flags);
2386 LM_QueueRxPackets(pDevice);
2387 BCM5700_UNLOCK(pUmDevice, flags);
2388 }
2389 if ((work_done < orig_budget) || atomic_read(&pUmDevice->intr_sem) ||
2390 pUmDevice->suspended) {
2391
2392 netif_rx_complete(dev);
2393 BCM5700_LOCK(pUmDevice, flags);
2394 REG_WR(pDevice, Grc.Mode, pDevice->GrcMode);
2395 pDevice->RxPoll = FALSE;
2396 if (pDevice->RxPoll) {
2397 BCM5700_UNLOCK(pUmDevice, flags);
2398 return 0;
2399 }
2400 /* Take care of possible missed rx interrupts */
2401 REG_RD_BACK(pDevice, Grc.Mode); /* flush the register write */
2402 tag = pDevice->pStatusBlkVirt->StatusTag;
2403 if ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
2404 (pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx !=
2405 pDevice->RcvRetConIdx)) {
2406
2407 REG_WR(pDevice, HostCoalesce.Mode,
2408 pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
2409 HOST_COALESCE_NOW);
2410 }
2411 /* If a new status block is pending in the WDMA state machine */
2412 /* before the register write to enable the rx interrupt, */
2413 /* the new status block may DMA with no interrupt. In this */
2414 /* scenario, the tag read above will be older than the tag in */
2415 /* the pending status block and writing the older tag will */
2416 /* cause interrupt to be generated. */
2417 else if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
2418 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low,
2419 tag << 24);
2420 /* Make sure we service tx in case some tx interrupts */
2421 /* are cleared */
2422 if (atomic_read(&pDevice->SendBdLeft) <
2423 (T3_SEND_RCB_ENTRY_COUNT / 2)) {
2424 REG_WR(pDevice, HostCoalesce.Mode,
2425 pDevice->CoalesceMode |
2426 HOST_COALESCE_ENABLE |
2427 HOST_COALESCE_NOW);
2428 }
2429 }
2430 BCM5700_UNLOCK(pUmDevice, flags);
2431 return 0;
2432 }
2433 return 1;
2434 }
2435 #endif /* BCM_NAPI_RXPOLL */
2436
2437 STATIC irqreturn_t
2438 bcm5700_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
2439 {
2440 struct net_device *dev = (struct net_device *)dev_instance;
2441 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2442 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2443 LM_UINT32 oldtag, newtag;
2444 int i, max_intr_loop;
2445 #ifdef BCM_TASKLET
2446 int repl_buf_count;
2447 #endif
2448 unsigned int handled = 1;
2449
2450 if (!pDevice->InitDone) {
2451 handled = 0;
2452 return IRQ_RETVAL(handled);
2453 }
2454
2455 bcm5700_intr_lock(pUmDevice);
2456 if (atomic_read(&pUmDevice->intr_sem)) {
2457 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
2458 bcm5700_intr_unlock(pUmDevice);
2459 handled = 0;
2460 return IRQ_RETVAL(handled);
2461 }
2462
2463 if (test_and_set_bit(0, (void*)&pUmDevice->interrupt)) {
2464 printk(KERN_ERR "%s: Duplicate entry of the interrupt handler\n",
2465 dev->name);
2466 bcm5700_intr_unlock(pUmDevice);
2467 handled = 0;
2468 return IRQ_RETVAL(handled);
2469 }
2470
2471 /* BCM4785: Flush posted writes from GbE to host memory. */
2472 if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
2473 REG_RD(pDevice, HostCoalesce.Mode);
2474
2475 if ((pDevice->Flags & USING_MSI_FLAG) ||
2476 (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) ||
2477 !(REG_RD(pDevice,PciCfg.PciState) & T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) )
2478 {
2479
2480 if (pUmDevice->intr_test) {
2481 if (!(REG_RD(pDevice, PciCfg.PciState) &
2482 T3_PCI_STATE_INTERRUPT_NOT_ACTIVE) ||
2483 pDevice->Flags & USING_MSI_FLAG ) {
2484 pUmDevice->intr_test_result = 1;
2485 }
2486 pUmDevice->intr_test = 0;
2487 }
2488
2489 #ifdef BCM_NAPI_RXPOLL
2490 max_intr_loop = 1;
2491 #else
2492 max_intr_loop = 50;
2493 #endif
2494 if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) {
2495 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
2496 oldtag = pDevice->pStatusBlkVirt->StatusTag;
2497
2498 for (i = 0; ; i++) {
2499 pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
2500
2501 LM_ServiceInterrupts(pDevice);
2502 /* BCM4785: Flush GbE posted writes to host memory. */
2503 if (pDevice->Flags & FLUSH_POSTED_WRITE_FLAG)
2504 MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
2505 newtag = pDevice->pStatusBlkVirt->StatusTag;
2506 if ((newtag == oldtag) || (i > max_intr_loop)) {
2507 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, oldtag << 24);
2508 pDevice->LastTag = oldtag;
2509 if (pDevice->Flags & UNDI_FIX_FLAG) {
2510 REG_WR(pDevice, Grc.LocalCtrl,
2511 pDevice->GrcLocalCtrl | 0x2);
2512 }
2513 break;
2514 }
2515 oldtag = newtag;
2516 }
2517 }
2518 else
2519 {
2520 i = 0;
2521 do {
2522 uint dummy;
2523
2524 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1);
2525 pDevice->pStatusBlkVirt->Status &= ~STATUS_BLOCK_UPDATED;
2526 LM_ServiceInterrupts(pDevice);
2527 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0);
2528 dummy = MB_REG_RD(pDevice, Mailbox.Interrupt[0].Low);
2529 i++;
2530 }
2531 while ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) &&
2532 (i < max_intr_loop));
2533
2534 if (pDevice->Flags & UNDI_FIX_FLAG) {
2535 REG_WR(pDevice, Grc.LocalCtrl,
2536 pDevice->GrcLocalCtrl | 0x2);
2537 }
2538 }
2539 }
2540 else
2541 {
2542 /* not my interrupt */
2543 handled = 0;
2544 }
2545
2546 #ifdef BCM_TASKLET
2547 repl_buf_count = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
2548 if (((repl_buf_count > pUmDevice->rx_buf_repl_panic_thresh) ||
2549 pDevice->QueueAgain) &&
2550 (!test_and_set_bit(0, &pUmDevice->tasklet_busy))) {
2551
2552 replenish_rx_buffers(pUmDevice, pUmDevice->rx_buf_repl_isr_limit);
2553 clear_bit(0, (void*)&pUmDevice->tasklet_busy);
2554 }
2555 else if ((repl_buf_count > pUmDevice->rx_buf_repl_thresh) &&
2556 !pUmDevice->tasklet_pending) {
2557
2558 pUmDevice->tasklet_pending = 1;
2559 tasklet_schedule(&pUmDevice->tasklet);
2560 }
2561 #else
2562 #ifdef BCM_NAPI_RXPOLL
2563 if (!pDevice->RxPoll &&
2564 QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
2565 pDevice->RxPoll = 1;
2566 MM_ScheduleRxPoll(pDevice);
2567 }
2568 #else
2569 if (QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container)) {
2570 replenish_rx_buffers(pUmDevice, 0);
2571 }
2572
2573 if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container) ||
2574 pDevice->QueueAgain) {
2575
2576 LM_QueueRxPackets(pDevice);
2577 }
2578 #endif
2579 #endif
2580
2581 clear_bit(0, (void*)&pUmDevice->interrupt);
2582 bcm5700_intr_unlock(pUmDevice);
2583 if (pUmDevice->tx_queued) {
2584 pUmDevice->tx_queued = 0;
2585 netif_wake_queue(dev);
2586 }
2587 return IRQ_RETVAL(handled);
2588 }
2589
2590
2591 #ifdef BCM_TASKLET
2592 STATIC void
2593 bcm5700_tasklet(unsigned long data)
2594 {
2595 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)data;
2596 unsigned long flags = 0;
2597
2598 /* RH 7.2 Beta 3 tasklets are reentrant */
2599 if (test_and_set_bit(0, &pUmDevice->tasklet_busy)) {
2600 pUmDevice->tasklet_pending = 0;
2601 return;
2602 }
2603
2604 pUmDevice->tasklet_pending = 0;
2605 if (pUmDevice->opened && !pUmDevice->suspended) {
2606 BCM5700_LOCK(pUmDevice, flags);
2607 replenish_rx_buffers(pUmDevice, 0);
2608 BCM5700_UNLOCK(pUmDevice, flags);
2609 }
2610
2611 clear_bit(0, &pUmDevice->tasklet_busy);
2612 }
2613 #endif
2614
2615 STATIC int
2616 bcm5700_close(struct net_device *dev)
2617 {
2618
2619 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2620 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2621
2622 #if (LINUX_VERSION_CODE < 0x02032b)
2623 dev->start = 0;
2624 #endif
2625 netif_stop_queue(dev);
2626 pUmDevice->opened = 0;
2627
2628 #ifdef BCM_ASF
2629 if( !(pDevice->AsfFlags & ASF_ENABLED) )
2630 #endif
2631 #ifdef BCM_WOL
2632 if( enable_wol[pUmDevice->index] == 0 )
2633 #endif
2634 B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name));
2635
2636 if (tigon3_debug > 1)
2637 printk(KERN_DEBUG "%s: Shutting down Tigon3\n",
2638 dev->name);
2639
2640 LM_MulticastClear(pDevice);
2641 bcm5700_shutdown(pUmDevice);
2642
2643 if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
2644 del_timer_sync(&pUmDevice->statstimer);
2645 }
2646
2647 del_timer_sync(&pUmDevice->timer);
2648
2649 free_irq(pUmDevice->pdev->irq, dev);
2650
2651 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
2652
2653 if(pDevice->Flags & USING_MSI_FLAG) {
2654 pci_disable_msi(pUmDevice->pdev);
2655 REG_WR(pDevice, Msi.Mode, 1 );
2656 pDevice->Flags &= ~USING_MSI_FLAG;
2657 }
2658
2659 #endif
2660
2661
2662 #if (LINUX_VERSION_CODE < 0x020300)
2663 MOD_DEC_USE_COUNT;
2664 #endif
2665 {
2666 /* BCM4785: Don't go to low-power state because it will power down the smbus block. */
2667 if (!(pDevice->Flags & SB_CORE_FLAG))
2668 LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
2669 }
2670
2671 bcm5700_freemem(dev);
2672
2673 QQ_InitQueue(&pDevice->RxPacketFreeQ.Container,
2674 MAX_RX_PACKET_DESC_COUNT);
2675
2676 return 0;
2677 }
2678
2679 STATIC int
2680 bcm5700_freemem(struct net_device *dev)
2681 {
2682 int i;
2683 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2684 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2685
2686 for (i = 0; i < pUmDevice->mem_list_num; i++) {
2687 if (pUmDevice->mem_size_list[i] == 0) {
2688 kfree(pUmDevice->mem_list[i]);
2689 }
2690 else {
2691 pci_free_consistent(pUmDevice->pdev,
2692 (size_t) pUmDevice->mem_size_list[i],
2693 pUmDevice->mem_list[i],
2694 pUmDevice->dma_list[i]);
2695 }
2696 }
2697
2698 pDevice->pStatusBlkVirt = 0;
2699 pDevice->pStatsBlkVirt = 0;
2700 pUmDevice->mem_list_num = 0;
2701
2702 return 0;
2703 }
2704
2705 uint64_t
2706 bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice)
2707 {
2708 PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
2709 LM_UINT32 Value32;
2710 PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
2711 unsigned long flags;
2712
2713 if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 ||
2714 T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) &&
2715 !(pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
2716
2717 if (!pUmDevice->opened || !pDevice->InitDone)
2718 {
2719
2720 return 0;
2721 }
2722
2723 /* regulate MDIO access during run time */
2724 if (pUmDevice->crc_counter_expiry > 0)
2725 return pUmDevice->phy_crc_count;
2726
2727 pUmDevice->crc_counter_expiry = (5 * HZ) /
2728 pUmDevice->timer_interval;
2729
2730 BCM5700_PHY_LOCK(pUmDevice, flags);
2731 LM_ReadPhy(pDevice, 0x1e, &Value32);
2732 if ((Value32 & 0x8000) == 0)
2733 LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000);
2734 LM_ReadPhy(pDevice, 0x14, &Value32);
2735 BCM5700_PHY_UNLOCK(pUmDevice, flags);
2736 /* Sometimes data on the MDIO bus can be corrupted */
2737 if (Value32 != 0xffff)
2738 pUmDevice->phy_crc_count += Value32;
2739 return pUmDevice->phy_crc_count;
2740 }
2741 else if (pStats == 0) {
2742 return 0;
2743 }
2744 else {
2745 return (MM_GETSTATS64(pStats->dot3StatsFCSErrors));
2746 }
2747 }
2748
2749 uint64_t
2750 bcm5700_rx_err_count(UM_DEVICE_BLOCK *pUmDevice)
2751 {
2752 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2753 T3_STATS_BLOCK *pStats = (T3_STATS_BLOCK *) pDevice->pStatsBlkVirt;
2754
2755 if (pStats == 0)
2756 return 0;
2757 return (bcm5700_crc_count(pUmDevice) +
2758 MM_GETSTATS64(pStats->dot3StatsAlignmentErrors) +
2759 MM_GETSTATS64(pStats->etherStatsUndersizePkts) +
2760 MM_GETSTATS64(pStats->etherStatsFragments) +
2761 MM_GETSTATS64(pStats->dot3StatsFramesTooLong) +
2762 MM_GETSTATS64(pStats->etherStatsJabbers));
2763 }
2764
2765 STATIC struct net_device_stats *
2766 bcm5700_get_stats(struct net_device *dev)
2767 {
2768 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
2769 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
2770 PT3_STATS_BLOCK pStats = (PT3_STATS_BLOCK) pDevice->pStatsBlkVirt;
2771 struct net_device_stats *p_netstats = &pUmDevice->stats;
2772
2773 if (pStats == 0)
2774 return p_netstats;
2775
2776 /* Get stats from LM */
2777 p_netstats->rx_packets =
2778 MM_GETSTATS(pStats->ifHCInUcastPkts) +
2779 MM_GETSTATS(pStats->ifHCInMulticastPkts) +
2780 MM_GETSTATS(pStats->ifHCInBroadcastPkts);
2781 p_netstats->tx_packets =
2782 MM_GETSTATS(pStats->ifHCOutUcastPkts) +
2783 MM_GETSTATS(pStats->ifHCOutMulticastPkts) +
2784 MM_GETSTATS(pStats->ifHCOutBroadcastPkts);
2785 /* There counters seem to be innacurate. Use byte number accumulation
2786 instead.
2787 p_netstats->rx_bytes = MM_GETSTATS(pStats->ifHCInOctets);
2788 p_netstats->tx_bytes = MM_GETSTATS(pStats->ifHCOutOctets);
2789 */
2790 p_netstats->tx_errors =
2791 MM_GETSTATS(pStats->dot3StatsInternalMacTransmitErrors) +
2792 MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors) +
2793 MM_GETSTATS(pStats->ifOutDiscards) +
2794 MM_GETSTATS(pStats->ifOutErrors);
2795 p_netstats->multicast = MM_GETSTATS(pStats->ifHCInMulticastPkts);
2796 p_netstats->collisions = MM_GETSTATS(pStats->etherStatsCollisions);
2797 p_netstats->rx_length_errors =
2798 MM_GETSTATS(pStats->dot3StatsFramesTooLong) +
2799 MM_GETSTATS(pStats->etherStatsUndersizePkts);
2800 p_netstats->rx_over_errors = MM_GETSTATS(pStats->nicNoMoreRxBDs);
2801 p_netstats->rx_frame_errors =
2802 MM_GETSTATS(pStats->dot3StatsAlignmentErrors);
2803 p_netstats->rx_crc_errors = (unsigned long)
2804 bcm5700_crc_count(pUmDevice);
2805 p_netstats->rx_errors = (unsigned long)
2806 bcm5700_rx_err_count(pUmDevice);
2807
2808 p_netstats->tx_aborted_errors = MM_GETSTATS(pStats->ifOutDiscards);
2809 p_netstats->tx_carrier_errors =
2810 MM_GETSTATS(pStats->dot3StatsCarrierSenseErrors);
2811
2812 return p_netstats;
2813 }
2814
2815 void
2816 b57_suspend_chip(UM_DEVICE_BLOCK *pUmDevice)
2817 {
2818 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2819
2820 if (pUmDevice->opened) {
2821 bcm5700_intr_off(pUmDevice);
2822 netif_carrier_off(pUmDevice->dev);
2823 netif_stop_queue(pUmDevice->dev);
2824 #ifdef BCM_TASKLET
2825 tasklet_kill(&pUmDevice->tasklet);
2826 #endif
2827 bcm5700_poll_wait(pUmDevice);
2828 }
2829 pUmDevice->suspended = 1;
2830 LM_ShutdownChip(pDevice, LM_SUSPEND_RESET);
2831 }
2832
2833 void
2834 b57_resume_chip(UM_DEVICE_BLOCK *pUmDevice)
2835 {
2836 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2837
2838 if (pUmDevice->suspended) {
2839 pUmDevice->suspended = 0;
2840 if (pUmDevice->opened) {
2841 bcm5700_reset(pUmDevice->dev);
2842 }
2843 else {
2844 LM_ShutdownChip(pDevice, LM_SHUTDOWN_RESET);
2845 }
2846 }
2847 }
2848
2849 /* Returns 0 on failure, 1 on success */
2850 int
2851 b57_test_intr(UM_DEVICE_BLOCK *pUmDevice)
2852 {
2853 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2854 int j;
2855
2856 if (!pUmDevice->opened)
2857 return 0;
2858 pUmDevice->intr_test_result = 0;
2859 pUmDevice->intr_test = 1;
2860
2861 REG_WR(pDevice, HostCoalesce.Mode,
2862 pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
2863 HOST_COALESCE_NOW);
2864
2865 for (j = 0; j < 10; j++) {
2866 if (pUmDevice->intr_test_result){
2867 break;
2868 }
2869
2870 REG_WR(pDevice, HostCoalesce.Mode,
2871 pDevice->CoalesceMode | HOST_COALESCE_ENABLE |
2872 HOST_COALESCE_NOW);
2873
2874 MM_Sleep(pDevice, 1);
2875 }
2876
2877 return pUmDevice->intr_test_result;
2878
2879 }
2880
2881 #ifdef SIOCETHTOOL
2882
2883 #ifdef ETHTOOL_GSTRINGS
2884
2885 #define ETH_NUM_STATS 30
2886 #define RX_CRC_IDX 5
2887 #define RX_MAC_ERR_IDX 14
2888
2889 struct {
2890 char string[ETH_GSTRING_LEN];
2891 } bcm5700_stats_str_arr[ETH_NUM_STATS] = {
2892 { "rx_unicast_packets" },
2893 { "rx_multicast_packets" },
2894 { "rx_broadcast_packets" },
2895 { "rx_bytes" },
2896 { "rx_fragments" },
2897 { "rx_crc_errors" }, /* this needs to be calculated */
2898 { "rx_align_errors" },
2899 { "rx_xon_frames" },
2900 { "rx_xoff_frames" },
2901 { "rx_long_frames" },
2902 { "rx_short_frames" },
2903 { "rx_jabber" },
2904 { "rx_discards" },
2905 { "rx_errors" },
2906 { "rx_mac_errors" }, /* this needs to be calculated */
2907 { "tx_unicast_packets" },
2908 { "tx_multicast_packets" },
2909 { "tx_broadcast_packets" },
2910 { "tx_bytes" },
2911 { "tx_deferred" },
2912 { "tx_single_collisions" },
2913 { "tx_multi_collisions" },
2914 { "tx_total_collisions" },
2915 { "tx_excess_collisions" },
2916 { "tx_late_collisions" },
2917 { "tx_xon_frames" },
2918 { "tx_xoff_frames" },
2919 { "tx_internal_mac_errors" },
2920 { "tx_carrier_errors" },
2921 { "tx_errors" },
2922 };
2923
2924 #define STATS_OFFSET(offset_name) ((OFFSETOF(T3_STATS_BLOCK, offset_name)) / sizeof(uint64_t))
2925
2926 #ifdef __BIG_ENDIAN
2927 #define SWAP_DWORD_64(x) (x)
2928 #else
2929 #define SWAP_DWORD_64(x) ((x << 32) | (x >> 32))
2930 #endif
2931
2932 unsigned long bcm5700_stats_offset_arr[ETH_NUM_STATS] = {
2933 STATS_OFFSET(ifHCInUcastPkts),
2934 STATS_OFFSET(ifHCInMulticastPkts),
2935 STATS_OFFSET(ifHCInBroadcastPkts),
2936 STATS_OFFSET(ifHCInOctets),
2937 STATS_OFFSET(etherStatsFragments),
2938 0,
2939 STATS_OFFSET(dot3StatsAlignmentErrors),
2940 STATS_OFFSET(xonPauseFramesReceived),
2941 STATS_OFFSET(xoffPauseFramesReceived),
2942 STATS_OFFSET(dot3StatsFramesTooLong),
2943 STATS_OFFSET(etherStatsUndersizePkts),
2944 STATS_OFFSET(etherStatsJabbers),
2945 STATS_OFFSET(ifInDiscards),
2946 STATS_OFFSET(ifInErrors),
2947 0,
2948 STATS_OFFSET(ifHCOutUcastPkts),
2949 STATS_OFFSET(ifHCOutMulticastPkts),
2950 STATS_OFFSET(ifHCOutBroadcastPkts),
2951 STATS_OFFSET(ifHCOutOctets),
2952 STATS_OFFSET(dot3StatsDeferredTransmissions),
2953 STATS_OFFSET(dot3StatsSingleCollisionFrames),
2954 STATS_OFFSET(dot3StatsMultipleCollisionFrames),
2955 STATS_OFFSET(etherStatsCollisions),
2956 STATS_OFFSET(dot3StatsExcessiveCollisions),
2957 STATS_OFFSET(dot3StatsLateCollisions),
2958 STATS_OFFSET(outXonSent),
2959 STATS_OFFSET(outXoffSent),
2960 STATS_OFFSET(dot3StatsInternalMacTransmitErrors),
2961 STATS_OFFSET(dot3StatsCarrierSenseErrors),
2962 STATS_OFFSET(ifOutErrors),
2963 };
2964
2965 #endif /* ETHTOOL_GSTRINGS */
2966
2967
2968 #ifdef ETHTOOL_GREGS
2969 #if (LINUX_VERSION_CODE >= 0x02040f)
2970 static void
2971 bcm5700_get_reg_blk(UM_DEVICE_BLOCK *pUmDevice, u32 **buf, u32 start, u32 end,
2972 int reserved)
2973 {
2974 u32 offset;
2975 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
2976
2977 if (reserved) {
2978 memset(*buf, 0, end - start);
2979 *buf = *buf + (end - start)/4;
2980 return;
2981 }
2982 for (offset = start; offset < end; offset+=4, *buf = *buf + 1) {
2983 if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
2984 if (((offset >= 0x3400) && (offset < 0x3c00)) ||
2985 ((offset >= 0x5400) && (offset < 0x5800)) ||
2986 ((offset >= 0x6400) && (offset < 0x6800))) {
2987 **buf = 0;
2988 continue;
2989 }
2990 }
2991 **buf = REG_RD_OFFSET(pDevice, offset);
2992 }
2993 }
2994 #endif
2995 #endif
2996
2997 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
2998 {
2999 struct ethtool_cmd ethcmd;
3000 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
3001 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
3002
3003 if (mm_copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
3004 return -EFAULT;
3005
3006 switch (ethcmd.cmd) {
3007 #ifdef ETHTOOL_GDRVINFO
3008 case ETHTOOL_GDRVINFO: {
3009 struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
3010
3011 strcpy(info.driver, bcm5700_driver);
3012 #ifdef INCLUDE_5701_AX_FIX
3013 if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0) {
3014 extern int t3FwReleaseMajor;
3015 extern int t3FwReleaseMinor;
3016 extern int t3FwReleaseFix;
3017
3018 sprintf(info.fw_version, "%i.%i.%i",
3019 t3FwReleaseMajor, t3FwReleaseMinor,
3020 t3FwReleaseFix);
3021 }
3022 #endif
3023 strcpy(info.fw_version, pDevice->BootCodeVer);
3024 strcpy(info.version, bcm5700_version);
3025 #if (LINUX_VERSION_CODE <= 0x020422)
3026 strcpy(info.bus_info, pUmDevice->pdev->slot_name);
3027 #else
3028 strcpy(info.bus_info, pci_name(pUmDevice->pdev));
3029 #endif
3030
3031
3032
3033 #ifdef ETHTOOL_GEEPROM
3034 BCM_EEDUMP_LEN(&info, pDevice->NvramSize);
3035 #endif
3036 #ifdef ETHTOOL_GREGS
3037 /* dump everything, including holes in the register space */
3038 info.regdump_len = 0x6c00;
3039 #endif
3040 #ifdef ETHTOOL_GSTATS
3041 info.n_stats = ETH_NUM_STATS;
3042 #endif
3043 if (mm_copy_to_user(useraddr, &info, sizeof(info)))
3044 return -EFAULT;
3045 return 0;
3046 }
3047 #endif
3048 case ETHTOOL_GSET: {
3049 if ((pDevice->TbiFlags & ENABLE_TBI_FLAG)||
3050 (pDevice->PhyFlags & PHY_IS_FIBER)) {
3051 ethcmd.supported =
3052 (SUPPORTED_1000baseT_Full |
3053 SUPPORTED_Autoneg);
3054 ethcmd.supported |= SUPPORTED_FIBRE;
3055 ethcmd.port = PORT_FIBRE;
3056 } else {
3057 ethcmd.supported =
3058 (SUPPORTED_10baseT_Half |
3059 SUPPORTED_10baseT_Full |
3060 SUPPORTED_100baseT_Half |
3061 SUPPORTED_100baseT_Full |
3062 SUPPORTED_1000baseT_Half |
3063 SUPPORTED_1000baseT_Full |
3064 SUPPORTED_Autoneg);
3065 ethcmd.supported |= SUPPORTED_TP;
3066 ethcmd.port = PORT_TP;
3067 }
3068
3069 ethcmd.transceiver = XCVR_INTERNAL;
3070 ethcmd.phy_address = 0;
3071
3072 if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS)
3073 ethcmd.speed = SPEED_1000;
3074 else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
3075 ethcmd.speed = SPEED_100;
3076 else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
3077 ethcmd.speed = SPEED_10;
3078 else
3079 ethcmd.speed = 0;
3080
3081 if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
3082 ethcmd.duplex = DUPLEX_FULL;
3083 else
3084 ethcmd.duplex = DUPLEX_HALF;
3085
3086 if (pDevice->DisableAutoNeg == FALSE) {
3087 ethcmd.autoneg = AUTONEG_ENABLE;
3088 ethcmd.advertising = ADVERTISED_Autoneg;
3089 if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) ||
3090 (pDevice->PhyFlags & PHY_IS_FIBER)) {
3091 ethcmd.advertising |=
3092 ADVERTISED_1000baseT_Full |
3093 ADVERTISED_FIBRE;
3094 }
3095 else {
3096 ethcmd.advertising |=
3097 ADVERTISED_TP;
3098 if (pDevice->advertising &
3099 PHY_AN_AD_10BASET_HALF) {
3100
3101 ethcmd.advertising |=
3102 ADVERTISED_10baseT_Half;
3103 }
3104 if (pDevice->advertising &
3105 PHY_AN_AD_10BASET_FULL) {
3106
3107 ethcmd.advertising |=
3108 ADVERTISED_10baseT_Full;
3109 }
3110 if (pDevice->advertising &
3111 PHY_AN_AD_100BASETX_HALF) {
3112
3113 ethcmd.advertising |=
3114 ADVERTISED_100baseT_Half;
3115 }
3116 if (pDevice->advertising &
3117 PHY_AN_AD_100BASETX_FULL) {
3118
3119 ethcmd.advertising |=
3120 ADVERTISED_100baseT_Full;
3121 }
3122 if (pDevice->advertising1000 &
3123 BCM540X_AN_AD_1000BASET_HALF) {
3124
3125 ethcmd.advertising |=
3126 ADVERTISED_1000baseT_Half;
3127 }
3128 if (pDevice->advertising1000 &
3129 BCM540X_AN_AD_1000BASET_FULL) {
3130
3131 ethcmd.advertising |=
3132 ADVERTISED_1000baseT_Full;
3133 }
3134 }
3135 }
3136 else {
3137 ethcmd.autoneg = AUTONEG_DISABLE;
3138 ethcmd.advertising = 0;
3139 }
3140
3141 ethcmd.maxtxpkt = pDevice->TxMaxCoalescedFrames;
3142 ethcmd.maxrxpkt = pDevice->RxMaxCoalescedFrames;
3143
3144 if(mm_copy_to_user(useraddr, &ethcmd, sizeof(ethcmd)))
3145 return -EFAULT;
3146 return 0;
3147 }
3148 case ETHTOOL_SSET: {
3149 unsigned long flags;
3150
3151 if(!capable(CAP_NET_ADMIN))
3152 return -EPERM;
3153 if (ethcmd.autoneg == AUTONEG_ENABLE) {
3154 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
3155 pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_UNKNOWN;
3156 pDevice->DisableAutoNeg = FALSE;
3157 }
3158 else {
3159 if (ethcmd.speed == SPEED_1000 &&
3160 pDevice->PhyFlags & PHY_NO_GIGABIT)
3161 return -EINVAL;
3162
3163 if (ethcmd.speed == SPEED_1000 &&
3164 (pDevice->TbiFlags & ENABLE_TBI_FLAG ||
3165 pDevice->PhyFlags & PHY_IS_FIBER ) ) {
3166
3167 pDevice->RequestedLineSpeed =
3168 LM_LINE_SPEED_1000MBPS;
3169
3170 pDevice->RequestedDuplexMode =
3171 LM_DUPLEX_MODE_FULL;
3172 }
3173 else if (ethcmd.speed == SPEED_100 &&
3174 !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3175 !(pDevice->PhyFlags & PHY_IS_FIBER)) {
3176
3177 pDevice->RequestedLineSpeed =
3178 LM_LINE_SPEED_100MBPS;
3179 }
3180 else if (ethcmd.speed == SPEED_10 &&
3181 !(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3182 !(pDevice->PhyFlags & PHY_IS_FIBER)) {
3183
3184 pDevice->RequestedLineSpeed =
3185 LM_LINE_SPEED_10MBPS;
3186 }
3187 else {
3188 return -EINVAL;
3189 }
3190
3191 pDevice->DisableAutoNeg = TRUE;
3192 if (ethcmd.duplex == DUPLEX_FULL) {
3193 pDevice->RequestedDuplexMode =
3194 LM_DUPLEX_MODE_FULL;
3195 }
3196 else {
3197 if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3198 !(pDevice->PhyFlags & PHY_IS_FIBER) ) {
3199
3200 pDevice->RequestedDuplexMode =
3201 LM_DUPLEX_MODE_HALF;
3202 }
3203 }
3204 }
3205 if (netif_running(dev)) {
3206 BCM5700_PHY_LOCK(pUmDevice, flags);
3207 LM_SetupPhy(pDevice);
3208 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3209 }
3210 return 0;
3211 }
3212 #ifdef ETHTOOL_GWOL
3213 #ifdef BCM_WOL
3214 case ETHTOOL_GWOL: {
3215 struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
3216
3217 if (((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3218 !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) ||
3219 (pDevice->Flags & DISABLE_D3HOT_FLAG)) {
3220 wol.supported = 0;
3221 wol.wolopts = 0;
3222 }
3223 else {
3224 wol.supported = WAKE_MAGIC;
3225 if (pDevice->WakeUpMode == LM_WAKE_UP_MODE_MAGIC_PACKET)
3226 {
3227 wol.wolopts = WAKE_MAGIC;
3228 }
3229 else {
3230 wol.wolopts = 0;
3231 }
3232 }
3233 if (mm_copy_to_user(useraddr, &wol, sizeof(wol)))
3234 return -EFAULT;
3235 return 0;
3236 }
3237 case ETHTOOL_SWOL: {
3238 struct ethtool_wolinfo wol;
3239
3240 if(!capable(CAP_NET_ADMIN))
3241 return -EPERM;
3242 if (mm_copy_from_user(&wol, useraddr, sizeof(wol)))
3243 return -EFAULT;
3244 if ((((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
3245 !(pDevice->Flags & FIBER_WOL_CAPABLE_FLAG)) ||
3246 (pDevice->Flags & DISABLE_D3HOT_FLAG)) &&
3247 wol.wolopts) {
3248 return -EINVAL;
3249 }
3250
3251 if ((wol.wolopts & ~WAKE_MAGIC) != 0) {
3252 return -EINVAL;
3253 }
3254 if (wol.wolopts & WAKE_MAGIC) {
3255 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
3256 pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
3257 }
3258 else {
3259 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
3260 pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE;
3261 }
3262 return 0;
3263 }
3264 #endif
3265 #endif
3266 #ifdef ETHTOOL_GLINK
3267 case ETHTOOL_GLINK: {
3268 struct ethtool_value edata = {ETHTOOL_GLINK};
3269
3270 /* ifup only waits for 5 seconds for link up */
3271 /* NIC may take more than 5 seconds to establish link */
3272 if ((pUmDevice->delayed_link_ind > 0) &&
3273 delay_link[pUmDevice->index])
3274 return -EOPNOTSUPP;
3275
3276 if (pDevice->LinkStatus == LM_STATUS_LINK_ACTIVE) {
3277 edata.data = 1;
3278 }
3279 else {
3280 edata.data = 0;
3281 }
3282 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3283 return -EFAULT;
3284 return 0;
3285 }
3286 #endif
3287 #ifdef ETHTOOL_NWAY_RST
3288 case ETHTOOL_NWAY_RST: {
3289 LM_UINT32 phyctrl;
3290 unsigned long flags;
3291
3292 if(!capable(CAP_NET_ADMIN))
3293 return -EPERM;
3294 if (pDevice->DisableAutoNeg) {
3295 return -EINVAL;
3296 }
3297 if (!netif_running(dev))
3298 return -EAGAIN;
3299 BCM5700_PHY_LOCK(pUmDevice, flags);
3300 if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
3301 pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS;
3302 pDevice->DisableAutoNeg = TRUE;
3303 LM_SetupPhy(pDevice);
3304
3305 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
3306 pDevice->DisableAutoNeg = FALSE;
3307 LM_SetupPhy(pDevice);
3308 }
3309 else {
3310 if ((T3_ASIC_REV(pDevice->ChipRevId) ==
3311 T3_ASIC_REV_5703) ||
3312 (T3_ASIC_REV(pDevice->ChipRevId) ==
3313 T3_ASIC_REV_5704) ||
3314 (T3_ASIC_REV(pDevice->ChipRevId) ==
3315 T3_ASIC_REV_5705))
3316 {
3317 LM_ResetPhy(pDevice);
3318 LM_SetupPhy(pDevice);
3319 }
3320 pDevice->PhyFlags &= ~PHY_FIBER_FALLBACK;
3321 LM_ReadPhy(pDevice, PHY_CTRL_REG, &phyctrl);
3322 LM_WritePhy(pDevice, PHY_CTRL_REG, phyctrl |
3323 PHY_CTRL_AUTO_NEG_ENABLE |
3324 PHY_CTRL_RESTART_AUTO_NEG);
3325 }
3326 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3327 return 0;
3328 }
3329 #endif
3330 #ifdef ETHTOOL_GEEPROM
3331 case ETHTOOL_GEEPROM: {
3332 struct ethtool_eeprom eeprom;
3333 LM_UINT32 *buf = 0;
3334 LM_UINT32 buf1[64/4];
3335 int i, j, offset, len;
3336
3337 if (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
3338 return -EFAULT;
3339
3340 if (eeprom.offset >= pDevice->NvramSize)
3341 return -EFAULT;
3342
3343 /* maximum data limited */
3344 /* to read more, call again with a different offset */
3345 if (eeprom.len > 0x800) {
3346 eeprom.len = 0x800;
3347 if (mm_copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
3348 return -EFAULT;
3349 }
3350
3351 if (eeprom.len > 64) {
3352 buf = kmalloc(eeprom.len, GFP_KERNEL);
3353 if (!buf)
3354 return -ENOMEM;
3355 }
3356 else {
3357 buf = buf1;
3358 }
3359 useraddr += offsetof(struct ethtool_eeprom, data);
3360
3361 offset = eeprom.offset;
3362 len = eeprom.len;
3363 if (offset & 3) {
3364 offset &= 0xfffffffc;
3365 len += (offset & 3);
3366 }
3367 len = (len + 3) & 0xfffffffc;
3368 for (i = 0, j = 0; j < len; i++, j += 4) {
3369 if (LM_NvramRead(pDevice, offset + j, buf + i) !=
3370 LM_STATUS_SUCCESS) {
3371 break;
3372 }
3373 }
3374 if (j >= len) {
3375 buf += (eeprom.offset & 3);
3376 i = mm_copy_to_user(useraddr, buf, eeprom.len);
3377 }
3378 if (eeprom.len > 64) {
3379 kfree(buf);
3380 }
3381 if ((j < len) || i)
3382 return -EFAULT;
3383 return 0;
3384 }
3385 case ETHTOOL_SEEPROM: {
3386 struct ethtool_eeprom eeprom;
3387 LM_UINT32 buf[64/4];
3388 int i, offset, len;
3389
3390 if(!capable(CAP_NET_ADMIN))
3391 return -EPERM;
3392 if (mm_copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
3393 return -EFAULT;
3394
3395 if ((eeprom.offset & 3) || (eeprom.len & 3) ||
3396 (eeprom.offset >= pDevice->NvramSize)) {
3397 return -EFAULT;
3398 }
3399
3400 if ((eeprom.offset + eeprom.len) >= pDevice->NvramSize) {
3401 eeprom.len = pDevice->NvramSize - eeprom.offset;
3402 }
3403
3404 useraddr += offsetof(struct ethtool_eeprom, data);
3405
3406 len = eeprom.len;
3407 offset = eeprom.offset;
3408 for (; len > 0; ) {
3409 if (len < 64)
3410 i = len;
3411 else
3412 i = 64;
3413 if (mm_copy_from_user(&buf, useraddr, i))
3414 return -EFAULT;
3415
3416 bcm5700_intr_off(pUmDevice);
3417 /* Prevent race condition on Grc.Mode register */
3418 bcm5700_poll_wait(pUmDevice);
3419
3420 if (LM_NvramWriteBlock(pDevice, offset, buf, i/4) !=
3421 LM_STATUS_SUCCESS) {
3422 bcm5700_intr_on(pUmDevice);
3423 return -EFAULT;
3424 }
3425 bcm5700_intr_on(pUmDevice);
3426 len -= i;
3427 offset += i;
3428 useraddr += i;
3429 }
3430 return 0;
3431 }
3432 #endif
3433 #ifdef ETHTOOL_GREGS
3434 #if (LINUX_VERSION_CODE >= 0x02040f)
3435 case ETHTOOL_GREGS: {
3436 struct ethtool_regs eregs;
3437 LM_UINT32 *buf, *buf1;
3438 unsigned int i;
3439
3440 if(!capable(CAP_NET_ADMIN))
3441 return -EPERM;
3442 if (pDevice->Flags & UNDI_FIX_FLAG)
3443 return -EOPNOTSUPP;
3444 if (mm_copy_from_user(&eregs, useraddr, sizeof(eregs)))
3445 return -EFAULT;
3446 if (eregs.len > 0x6c00)
3447 eregs.len = 0x6c00;
3448 eregs.version = 0x0;
3449 if (mm_copy_to_user(useraddr, &eregs, sizeof(eregs)))
3450 return -EFAULT;
3451 buf = buf1 = kmalloc(eregs.len, GFP_KERNEL);
3452 if (!buf)
3453 return -ENOMEM;
3454 bcm5700_get_reg_blk(pUmDevice, &buf, 0, 0xb0, 0);
3455 bcm5700_get_reg_blk(pUmDevice, &buf, 0xb0, 0x200, 1);
3456 bcm5700_get_reg_blk(pUmDevice, &buf, 0x200, 0x8f0, 0);
3457 bcm5700_get_reg_blk(pUmDevice, &buf, 0x8f0, 0xc00, 1);
3458 bcm5700_get_reg_blk(pUmDevice, &buf, 0xc00, 0xce0, 0);
3459 bcm5700_get_reg_blk(pUmDevice, &buf, 0xce0, 0x1000, 1);
3460 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1000, 0x1004, 0);
3461 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1004, 0x1400, 1);
3462 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1400, 0x1480, 0);
3463 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1480, 0x1800, 1);
3464 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1800, 0x1848, 0);
3465 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1848, 0x1c00, 1);
3466 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c00, 0x1c04, 0);
3467 bcm5700_get_reg_blk(pUmDevice, &buf, 0x1c04, 0x2000, 1);
3468 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2000, 0x225c, 0);
3469 bcm5700_get_reg_blk(pUmDevice, &buf, 0x225c, 0x2400, 1);
3470 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2400, 0x24c4, 0);
3471 bcm5700_get_reg_blk(pUmDevice, &buf, 0x24c4, 0x2800, 1);
3472 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2800, 0x2804, 0);
3473 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2804, 0x2c00, 1);
3474 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c00, 0x2c20, 0);
3475 bcm5700_get_reg_blk(pUmDevice, &buf, 0x2c20, 0x3000, 1);
3476 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3000, 0x3014, 0);
3477 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3014, 0x3400, 1);
3478 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3400, 0x3408, 0);
3479 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3408, 0x3800, 1);
3480 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3800, 0x3808, 0);
3481 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3808, 0x3c00, 1);
3482 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3c00, 0x3d00, 0);
3483 bcm5700_get_reg_blk(pUmDevice, &buf, 0x3d00, 0x4000, 1);
3484 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4000, 0x4010, 0);
3485 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4010, 0x4400, 1);
3486 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4400, 0x4458, 0);
3487 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4458, 0x4800, 1);
3488 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4800, 0x4808, 0);
3489 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4808, 0x4c00, 1);
3490 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c00, 0x4c08, 0);
3491 bcm5700_get_reg_blk(pUmDevice, &buf, 0x4c08, 0x5000, 1);
3492 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5000, 0x5050, 0);
3493 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5050, 0x5400, 1);
3494 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5400, 0x5450, 0);
3495 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5450, 0x5800, 1);
3496 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5800, 0x5a10, 0);
3497 bcm5700_get_reg_blk(pUmDevice, &buf, 0x5a10, 0x6000, 1);
3498 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6000, 0x600c, 0);
3499 bcm5700_get_reg_blk(pUmDevice, &buf, 0x600c, 0x6400, 1);
3500 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6400, 0x6404, 0);
3501 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6404, 0x6800, 1);
3502 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6800, 0x6848, 0);
3503 bcm5700_get_reg_blk(pUmDevice, &buf, 0x6848, 0x6c00, 1);
3504
3505 i = mm_copy_to_user(useraddr + sizeof(eregs), buf1, eregs.len);
3506 kfree(buf1);
3507 if (i)
3508 return -EFAULT;
3509 return 0;
3510 }
3511 #endif
3512 #endif
3513 #ifdef ETHTOOL_GPAUSEPARAM
3514 case ETHTOOL_GPAUSEPARAM: {
3515 struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
3516
3517 if (!pDevice->DisableAutoNeg) {
3518 epause.autoneg = (pDevice->FlowControlCap &
3519 LM_FLOW_CONTROL_AUTO_PAUSE) != 0;
3520 }
3521 else {
3522 epause.autoneg = 0;
3523 }
3524 epause.rx_pause =
3525 (pDevice->FlowControl &
3526 LM_FLOW_CONTROL_RECEIVE_PAUSE) != 0;
3527 epause.tx_pause =
3528 (pDevice->FlowControl &
3529 LM_FLOW_CONTROL_TRANSMIT_PAUSE) != 0;
3530 if (mm_copy_to_user(useraddr, &epause, sizeof(epause)))
3531 return -EFAULT;
3532
3533 return 0;
3534 }
3535 case ETHTOOL_SPAUSEPARAM: {
3536 struct ethtool_pauseparam epause;
3537 unsigned long flags;
3538
3539 if(!capable(CAP_NET_ADMIN))
3540 return -EPERM;
3541 if (mm_copy_from_user(&epause, useraddr, sizeof(epause)))
3542 return -EFAULT;
3543 pDevice->FlowControlCap = 0;
3544 if (epause.autoneg && !pDevice->DisableAutoNeg) {
3545 pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
3546 }
3547 if (epause.rx_pause) {
3548 pDevice->FlowControlCap |=
3549 LM_FLOW_CONTROL_RECEIVE_PAUSE;
3550 }
3551 if (epause.tx_pause) {
3552 pDevice->FlowControlCap |=
3553 LM_FLOW_CONTROL_TRANSMIT_PAUSE;
3554 }
3555 if (netif_running(dev)) {
3556 BCM5700_PHY_LOCK(pUmDevice, flags);
3557 LM_SetupPhy(pDevice);
3558 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3559 }
3560
3561 return 0;
3562 }
3563 #endif
3564 #ifdef ETHTOOL_GRXCSUM
3565 case ETHTOOL_GRXCSUM: {
3566 struct ethtool_value edata = { ETHTOOL_GRXCSUM };
3567
3568 edata.data =
3569 (pDevice->TaskToOffload &
3570 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM) != 0;
3571 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3572 return -EFAULT;
3573
3574 return 0;
3575 }
3576 case ETHTOOL_SRXCSUM: {
3577 struct ethtool_value edata;
3578
3579 if(!capable(CAP_NET_ADMIN))
3580 return -EPERM;
3581 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3582 return -EFAULT;
3583 if (edata.data) {
3584 if (!(pDevice->TaskOffloadCap &
3585 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
3586
3587 return -EINVAL;
3588 }
3589 pDevice->TaskToOffload |=
3590 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
3591 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
3592 }
3593 else {
3594 pDevice->TaskToOffload &=
3595 ~(LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
3596 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM);
3597 }
3598 return 0;
3599 }
3600 case ETHTOOL_GTXCSUM: {
3601 struct ethtool_value edata = { ETHTOOL_GTXCSUM };
3602
3603 edata.data =
3604 (dev->features & get_csum_flag( pDevice->ChipRevId)) != 0;
3605 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3606 return -EFAULT;
3607
3608 return 0;
3609 }
3610 case ETHTOOL_STXCSUM: {
3611 struct ethtool_value edata;
3612
3613 if(!capable(CAP_NET_ADMIN))
3614 return -EPERM;
3615 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3616 return -EFAULT;
3617 if (edata.data) {
3618 if (!(pDevice->TaskOffloadCap &
3619 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
3620
3621 return -EINVAL;
3622 }
3623 dev->features |= get_csum_flag( pDevice->ChipRevId);
3624 pDevice->TaskToOffload |=
3625 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
3626 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
3627 }
3628 else {
3629 dev->features &= ~get_csum_flag( pDevice->ChipRevId);
3630 pDevice->TaskToOffload &=
3631 ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
3632 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM);
3633 }
3634 return 0;
3635 }
3636 case ETHTOOL_GSG: {
3637 struct ethtool_value edata = { ETHTOOL_GSG };
3638
3639 edata.data =
3640 (dev->features & NETIF_F_SG) != 0;
3641 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3642 return -EFAULT;
3643 return 0;
3644 }
3645 case ETHTOOL_SSG: {
3646 struct ethtool_value edata;
3647
3648 if(!capable(CAP_NET_ADMIN))
3649 return -EPERM;
3650 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3651 return -EFAULT;
3652 if (edata.data) {
3653 dev->features |= NETIF_F_SG;
3654 }
3655 else {
3656 dev->features &= ~NETIF_F_SG;
3657 }
3658 return 0;
3659 }
3660 #endif
3661 #ifdef ETHTOOL_GRINGPARAM
3662 case ETHTOOL_GRINGPARAM: {
3663 struct ethtool_ringparam ering = { ETHTOOL_GRINGPARAM };
3664
3665 ering.rx_max_pending = T3_STD_RCV_RCB_ENTRY_COUNT - 1;
3666 ering.rx_pending = pDevice->RxStdDescCnt;
3667 ering.rx_mini_max_pending = 0;
3668 ering.rx_mini_pending = 0;
3669 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
3670 ering.rx_jumbo_max_pending = T3_JUMBO_RCV_RCB_ENTRY_COUNT - 1;
3671 ering.rx_jumbo_pending = pDevice->RxJumboDescCnt;
3672 #else
3673 ering.rx_jumbo_max_pending = 0;
3674 ering.rx_jumbo_pending = 0;
3675 #endif
3676 ering.tx_max_pending = MAX_TX_PACKET_DESC_COUNT - 1;
3677 ering.tx_pending = pDevice->TxPacketDescCnt;
3678 if (mm_copy_to_user(useraddr, &ering, sizeof(ering)))
3679 return -EFAULT;
3680 return 0;
3681 }
3682 #endif
3683 #ifdef ETHTOOL_PHYS_ID
3684 case ETHTOOL_PHYS_ID: {
3685 struct ethtool_value edata;
3686
3687 if(!capable(CAP_NET_ADMIN))
3688 return -EPERM;
3689 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3690 return -EFAULT;
3691 if (LM_BlinkLED(pDevice, edata.data) == LM_STATUS_SUCCESS)
3692 return 0;
3693 return -EINTR;
3694 }
3695 #endif
3696 #ifdef ETHTOOL_GSTRINGS
3697 case ETHTOOL_GSTRINGS: {
3698 struct ethtool_gstrings egstr = { ETHTOOL_GSTRINGS };
3699
3700 if (mm_copy_from_user(&egstr, useraddr, sizeof(egstr)))
3701 return -EFAULT;
3702 switch(egstr.string_set) {
3703 #ifdef ETHTOOL_GSTATS
3704 case ETH_SS_STATS:
3705 egstr.len = ETH_NUM_STATS;
3706 if (mm_copy_to_user(useraddr, &egstr, sizeof(egstr)))
3707 return -EFAULT;
3708 if (mm_copy_to_user(useraddr + sizeof(egstr),
3709 bcm5700_stats_str_arr,
3710 sizeof(bcm5700_stats_str_arr)))
3711 return -EFAULT;
3712 return 0;
3713 #endif
3714 default:
3715 return -EOPNOTSUPP;
3716 }
3717 }
3718 #endif
3719 #ifdef ETHTOOL_GSTATS
3720 case ETHTOOL_GSTATS: {
3721 struct ethtool_stats estats = { ETHTOOL_GSTATS };
3722 uint64_t stats[ETH_NUM_STATS];
3723 int i;
3724 uint64_t *pStats =
3725 (uint64_t *) pDevice->pStatsBlkVirt;
3726
3727 estats.n_stats = ETH_NUM_STATS;
3728 if (pStats == 0) {
3729 memset(stats, 0, sizeof(stats));
3730 }
3731 else {
3732
3733 for (i = 0; i < ETH_NUM_STATS; i++) {
3734 if (bcm5700_stats_offset_arr[i] != 0) {
3735 stats[i] = SWAP_DWORD_64(*(pStats +
3736 bcm5700_stats_offset_arr[i]));
3737 }
3738 else if (i == RX_CRC_IDX) {
3739 stats[i] =
3740 bcm5700_crc_count(pUmDevice);
3741 }
3742 else if (i == RX_MAC_ERR_IDX) {
3743 stats[i] =
3744 bcm5700_rx_err_count(pUmDevice);
3745 }
3746 }
3747 }
3748 if (mm_copy_to_user(useraddr, &estats, sizeof(estats))) {
3749 return -EFAULT;
3750 }
3751 if (mm_copy_to_user(useraddr + sizeof(estats), &stats,
3752 sizeof(stats))) {
3753 return -EFAULT;
3754 }
3755 return 0;
3756 }
3757 #endif
3758 #ifdef ETHTOOL_GTSO
3759 case ETHTOOL_GTSO: {
3760 struct ethtool_value edata = { ETHTOOL_GTSO };
3761
3762 #ifdef BCM_TSO
3763 edata.data =
3764 (dev->features & NETIF_F_TSO) != 0;
3765 #else
3766 edata.data = 0;
3767 #endif
3768 if (mm_copy_to_user(useraddr, &edata, sizeof(edata)))
3769 return -EFAULT;
3770 return 0;
3771 }
3772 #endif
3773 #ifdef ETHTOOL_STSO
3774 case ETHTOOL_STSO: {
3775 #ifdef BCM_TSO
3776 struct ethtool_value edata;
3777
3778 if (!capable(CAP_NET_ADMIN))
3779 return -EPERM;
3780
3781 if (mm_copy_from_user(&edata, useraddr, sizeof(edata)))
3782 return -EFAULT;
3783
3784 if (!(pDevice->TaskToOffload &
3785 LM_TASK_OFFLOAD_TCP_SEGMENTATION)) {
3786 return -EINVAL;
3787 }
3788
3789 dev->features &= ~NETIF_F_TSO;
3790
3791 if (edata.data) {
3792 if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
3793 (dev->mtu > 1500)) {
3794 printk(KERN_ALERT "%s: Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
3795 return -EINVAL;
3796 } else {
3797 dev->features |= NETIF_F_TSO;
3798 }
3799 }
3800 return 0;
3801 #else
3802 return -EINVAL;
3803 #endif
3804 }
3805 #endif
3806 }
3807
3808 return -EOPNOTSUPP;
3809 }
3810 #endif /* #ifdef SIOCETHTOOL */
3811
3812 #if (LINUX_VERSION_CODE >= 0x20400) && (LINUX_VERSION_CODE < 0x20600)
3813 #include <linux/iobuf.h>
3814 #endif
3815
3816 /* Provide ioctl() calls to examine the MII xcvr state. */
3817 STATIC int bcm5700_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3818 {
3819 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
3820 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
3821 u16 *data = (u16 *)&rq->ifr_data;
3822 u32 value = 0;
3823 u16 page_num =0, addr_num =0, len =0;
3824 unsigned long flags;
3825
3826 switch(cmd) {
3827 case SIOCGREG_STATUS: //Get register
3828 {
3829 struct reg_ioctl_data *rdata =(struct reg_ioctl_data *)rq->ifr_data;
3830 robo_info_t *robo = (robo_info_t *)pUmDevice->robo;
3831 page_num = rdata->page_num;
3832 addr_num = rdata->addr_num;
3833 len = rdata->len;
3834 printk("b57um SIOCGREG_STATUS cmd page[0x%x]addr[0x%x]len[%d].\n",page_num,addr_num,len);
3835 if (len == 6)
3836 {
3837 ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3838 printk("val[0x%04x-0x%04x-0x%04x].\n",rdata->val_out[0],rdata->val_out[1],rdata->val_out[2]);
3839 }
3840 else if (len == 8)
3841 {
3842 ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3843 printk("val[0x%04x%04x-0x%04x%04x].\n",rdata->val_out[0],rdata->val_out[1],
3844 rdata->val_out[2],rdata->val_out[3]);
3845 }
3846 else if (len == 4)
3847 {
3848 ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3849 printk("val[0x%04x%04x].\n",rdata->val_out[0],rdata->val_out[1]);
3850 }
3851 else
3852 {
3853 ReadDataFromRegister(robo,page_num,addr_num,len,(void *)&rdata->val_out);
3854 printk("val[0x%04x].\n",rdata->val_out[0]);
3855
3856 }
3857 if (mm_copy_to_user(rq->ifr_data, rdata, sizeof(struct reg_ioctl_data)))
3858 {
3859 printk("Fail mm_copy_to_user.\n");
3860 return -EFAULT;
3861 }
3862 return 0;
3863 }
3864 break;
3865 case SIOCSREG_STATUS://Set register
3866 {
3867 struct reg_ioctl_data * wdata =(struct reg_ioctl_data *)rq->ifr_data;
3868 len = wdata->len;
3869 page_num = wdata->page_num;
3870 addr_num = wdata->addr_num;
3871 robo_info_t *robo = (robo_info_t *)pUmDevice->robo;
3872 if (len == 6)
3873 {
3874 WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3875 //printk("val[0x%04x-0x%04x-0x%04x].\n",val48[0],val48[1],val48[2]);
3876 }
3877 else if (len == 8)
3878 {
3879 WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3880 //printk("val[0x%04x-0x%04x-0x%04x-0x%04x].\n",val64[0],val64[1],val64[2],val64[3]);
3881 }
3882 else if (len == 4)
3883 {
3884 WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3885 //printk("val[0x%08x].\n",value);
3886 }
3887 else
3888 {
3889 WriteDataToRegister(robo,page_num,addr_num,len,(void *)&wdata->val_in);
3890 //printk("len[%d] val[0x%04x].\n",len,val16);
3891 }
3892
3893 return 0;
3894 }
3895 break;
3896 #ifdef SIOCGMIIPHY
3897 case SIOCGMIIPHY: /* Get the address of the PHY in use. */
3898
3899 data[0] = pDevice->PhyAddr;
3900 return 0;
3901 #endif
3902
3903 #ifdef SIOCGMIIREG
3904 case SIOCGMIIREG: /* Read the specified MII register. */
3905 {
3906 uint32 savephyaddr = 0;
3907
3908 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
3909 return -EOPNOTSUPP;
3910
3911 /* ifup only waits for 5 seconds for link up */
3912 /* NIC may take more than 5 seconds to establish link */
3913 if ((pUmDevice->delayed_link_ind > 0) &&
3914 delay_link[pUmDevice->index]) {
3915 return -EAGAIN;
3916 }
3917
3918 BCM5700_PHY_LOCK(pUmDevice, flags);
3919 if (data[0] != 0xffff) {
3920 savephyaddr = pDevice->PhyAddr;
3921 pDevice->PhyAddr = data[0];
3922 }
3923 LM_ReadPhy(pDevice, data[1] & 0x1f, (LM_UINT32 *)&value);
3924 if (data[0] != 0xffff)
3925 pDevice->PhyAddr = savephyaddr;
3926 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3927 data[3] = value & 0xffff;
3928 return 0;
3929 }
3930 #endif
3931
3932 #ifdef SIOCSMIIREG
3933 case SIOCSMIIREG: /* Write the specified MII register */
3934 {
3935 uint32 savephyaddr = 0;
3936
3937 if (!capable(CAP_NET_ADMIN))
3938 return -EPERM;
3939
3940 if (pDevice->TbiFlags & ENABLE_TBI_FLAG)
3941 return -EOPNOTSUPP;
3942
3943 BCM5700_PHY_LOCK(pUmDevice, flags);
3944 if (data[0] != 0xffff) {
3945 savephyaddr = pDevice->PhyAddr;
3946 pDevice->PhyAddr = data[0];
3947 }
3948 LM_WritePhy(pDevice, data[1] & 0x1f, data[2]);
3949 if (data[0] != 0xffff)
3950 pDevice->PhyAddr = savephyaddr;
3951 BCM5700_PHY_UNLOCK(pUmDevice, flags);
3952 data[3] = 0;
3953 return 0;
3954 }
3955 #endif
3956
3957 #ifdef SIOCETHTOOL
3958 case SIOCETHTOOL:
3959 return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
3960 #endif
3961 default:
3962 return -EOPNOTSUPP;
3963 }
3964 return -EOPNOTSUPP;
3965 }
3966
3967 STATIC void bcm5700_do_rx_mode(struct net_device *dev)
3968 {
3969 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
3970 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
3971 int i;
3972 struct dev_mc_list *mclist;
3973
3974 LM_MulticastClear(pDevice);
3975 for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
3976 i++, mclist = mclist->next) {
3977 LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr);
3978 }
3979 if (dev->flags & IFF_ALLMULTI) {
3980 if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) {
3981 LM_SetReceiveMask(pDevice,
3982 pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
3983 }
3984 }
3985 else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) {
3986 LM_SetReceiveMask(pDevice,
3987 pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST);
3988 }
3989 if (dev->flags & IFF_PROMISC) {
3990 if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) {
3991 LM_SetReceiveMask(pDevice,
3992 pDevice->ReceiveMask | LM_PROMISCUOUS_MODE);
3993 }
3994 }
3995 else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) {
3996 LM_SetReceiveMask(pDevice,
3997 pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE);
3998 }
3999
4000 }
4001
4002 STATIC void bcm5700_set_rx_mode(struct net_device *dev)
4003 {
4004 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
4005 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
4006 int i;
4007 struct dev_mc_list *mclist;
4008 unsigned long flags;
4009
4010 BCM5700_PHY_LOCK(pUmDevice, flags);
4011
4012 LM_MulticastClear(pDevice);
4013 for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
4014 i++, mclist = mclist->next) {
4015 LM_MulticastAdd(pDevice, (PLM_UINT8) &mclist->dmi_addr);
4016 }
4017 if (dev->flags & IFF_ALLMULTI) {
4018 if (!(pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST)) {
4019 LM_SetReceiveMask(pDevice,
4020 pDevice->ReceiveMask | LM_ACCEPT_ALL_MULTICAST);
4021 }
4022 }
4023 else if (pDevice->ReceiveMask & LM_ACCEPT_ALL_MULTICAST) {
4024 LM_SetReceiveMask(pDevice,
4025 pDevice->ReceiveMask & ~LM_ACCEPT_ALL_MULTICAST);
4026 }
4027 if (dev->flags & IFF_PROMISC) {
4028 if (!(pDevice->ReceiveMask & LM_PROMISCUOUS_MODE)) {
4029 LM_SetReceiveMask(pDevice,
4030 pDevice->ReceiveMask | LM_PROMISCUOUS_MODE);
4031 }
4032 }
4033 else if (pDevice->ReceiveMask & LM_PROMISCUOUS_MODE) {
4034 LM_SetReceiveMask(pDevice,
4035 pDevice->ReceiveMask & ~LM_PROMISCUOUS_MODE);
4036 }
4037
4038 BCM5700_PHY_UNLOCK(pUmDevice, flags);
4039 }
4040
4041 /*
4042 * Set the hardware MAC address.
4043 */
4044 STATIC int bcm5700_set_mac_addr(struct net_device *dev, void *p)
4045 {
4046 struct sockaddr *addr=p;
4047 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) dev->priv;
4048 UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4049
4050 if(is_valid_ether_addr(addr->sa_data)){
4051
4052 memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
4053 if (pUmDevice->opened)
4054 LM_SetMacAddress(pDevice, dev->dev_addr);
4055 bcm_robo_set_macaddr(pUmDevice->robo, dev->dev_addr);
4056 return 0;
4057 }
4058 return -EINVAL;
4059 }
4060
4061 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
4062 STATIC int bcm5700_change_mtu(struct net_device *dev, int new_mtu)
4063 {
4064 int pkt_size = new_mtu + ETHERNET_PACKET_HEADER_SIZE;
4065 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK)dev->priv;
4066 PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
4067 unsigned long flags;
4068 int reinit = 0;
4069
4070 if ((pkt_size < MIN_ETHERNET_PACKET_SIZE_NO_CRC) ||
4071 (pkt_size > MAX_ETHERNET_JUMBO_PACKET_SIZE_NO_CRC)) {
4072
4073 return -EINVAL;
4074 }
4075 if ( !(pDevice->Flags & JUMBO_CAPABLE_FLAG) &&
4076 (pkt_size > MAX_ETHERNET_PACKET_SIZE_NO_CRC) ) {
4077
4078 return -EINVAL;
4079 }
4080 if (pUmDevice->suspended)
4081 return -EAGAIN;
4082
4083 if (pUmDevice->opened && (new_mtu != dev->mtu) &&
4084 (pDevice->Flags & JUMBO_CAPABLE_FLAG)) {
4085 reinit = 1;
4086 }
4087
4088 BCM5700_PHY_LOCK(pUmDevice, flags);
4089 if (reinit) {
4090 netif_stop_queue(dev);
4091 bcm5700_shutdown(pUmDevice);
4092 bcm5700_freemem(dev);
4093 }
4094
4095 dev->mtu = new_mtu;
4096 if (pkt_size < MAX_ETHERNET_PACKET_SIZE_NO_CRC) {
4097 pDevice->RxMtu = pDevice->TxMtu =
4098 MAX_ETHERNET_PACKET_SIZE_NO_CRC;
4099 }
4100 else {
4101 pDevice->RxMtu = pDevice->TxMtu = pkt_size;
4102 }
4103
4104 if (dev->mtu <= 1514) {
4105 pDevice->RxJumboDescCnt = 0;
4106 }
4107 else if (pDevice->Flags & JUMBO_CAPABLE_FLAG){
4108 pDevice->RxJumboDescCnt =
4109 rx_jumbo_desc_cnt[pUmDevice->index];
4110 }
4111 pDevice->RxPacketDescCnt = pDevice->RxJumboDescCnt +
4112 pDevice->RxStdDescCnt;
4113
4114 pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ +
4115 COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK;
4116
4117 #ifdef BCM_TSO
4118 if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
4119 (dev->mtu > 1514) ) {
4120 if (dev->features & NETIF_F_TSO) {
4121 dev->features &= ~NETIF_F_TSO;
4122 printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
4123 }
4124 }
4125 #endif
4126
4127 if (reinit) {
4128 LM_InitializeAdapter(pDevice);
4129 bcm5700_do_rx_mode(dev);
4130 bcm5700_set_vlan_mode(pUmDevice);
4131 bcm5700_init_counters(pUmDevice);
4132 if (memcmp(dev->dev_addr, pDevice->NodeAddress, 6)) {
4133 LM_SetMacAddress(pDevice, dev->dev_addr);
4134 }
4135 netif_start_queue(dev);
4136 bcm5700_intr_on(pUmDevice);
4137 }
4138 BCM5700_PHY_UNLOCK(pUmDevice, flags);
4139
4140 return 0;
4141 }
4142 #endif
4143
4144
4145 #if (LINUX_VERSION_CODE < 0x020300)
4146 int
4147 bcm5700_probe(struct net_device *dev)
4148 {
4149 int cards_found = 0;
4150 struct pci_dev *pdev = NULL;
4151 struct pci_device_id *pci_tbl;
4152 u16 ssvid, ssid;
4153
4154 if ( ! pci_present())
4155 return -ENODEV;
4156
4157 pci_tbl = bcm5700_pci_tbl;
4158 while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
4159 int idx;
4160
4161 pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &ssvid);
4162 pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &ssid);
4163 for (idx = 0; pci_tbl[idx].vendor; idx++) {
4164 if ((pci_tbl[idx].vendor == PCI_ANY_ID ||
4165 pci_tbl[idx].vendor == pdev->vendor) &&
4166 (pci_tbl[idx].device == PCI_ANY_ID ||
4167 pci_tbl[idx].device == pdev->device) &&
4168 (pci_tbl[idx].subvendor == PCI_ANY_ID ||
4169 pci_tbl[idx].subvendor == ssvid) &&
4170 (pci_tbl[idx].subdevice == PCI_ANY_ID ||
4171 pci_tbl[idx].subdevice == ssid))
4172 {
4173
4174 break;
4175 }
4176 }
4177 if (pci_tbl[idx].vendor == 0)
4178 continue;
4179
4180
4181 if (bcm5700_init_one(pdev, &pci_tbl[idx]) == 0)
4182 cards_found++;
4183 }
4184
4185 return cards_found ? 0 : -ENODEV;
4186 }
4187
4188 #ifdef MODULE
4189 int init_module(void)
4190 {
4191 return bcm5700_probe(NULL);
4192 }
4193
4194 void cleanup_module(void)
4195 {
4196 struct net_device *next_dev;
4197 PUM_DEVICE_BLOCK pUmDevice;
4198
4199 /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
4200 while (root_tigon3_dev) {
4201 pUmDevice = (PUM_DEVICE_BLOCK)root_tigon3_dev->priv;
4202 next_dev = pUmDevice->next_module;
4203 unregister_netdev(root_tigon3_dev);
4204 if (pUmDevice->lm_dev.pMappedMemBase)
4205 iounmap(pUmDevice->lm_dev.pMappedMemBase);
4206 #if (LINUX_VERSION_CODE < 0x020600)
4207 kfree(root_tigon3_dev);
4208 #else
4209 free_netdev(root_tigon3_dev);
4210 #endif
4211 root_tigon3_dev = next_dev;
4212 }
4213 #ifdef BCM_IOCTL32
4214 unregister_ioctl32_conversion(SIOCNICE);
4215 #endif
4216 }
4217
4218 #endif /* MODULE */
4219 #else /* LINUX_VERSION_CODE < 0x020300 */
4220
4221 #if (LINUX_VERSION_CODE >= 0x020406)
4222 static int bcm5700_suspend (struct pci_dev *pdev, u32 state)
4223 #else
4224 static void bcm5700_suspend (struct pci_dev *pdev)
4225 #endif
4226 {
4227 struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
4228 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
4229 PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
4230
4231 if (!netif_running(dev))
4232 #if (LINUX_VERSION_CODE >= 0x020406)
4233 return 0;
4234 #else
4235 return;
4236 #endif
4237
4238 netif_device_detach (dev);
4239 bcm5700_shutdown(pUmDevice);
4240
4241 LM_SetPowerState(pDevice, LM_POWER_STATE_D3);
4242
4243 /* pci_power_off(pdev, -1);*/
4244 #if (LINUX_VERSION_CODE >= 0x020406)
4245 return 0;
4246 #endif
4247 }
4248
4249
4250 #if (LINUX_VERSION_CODE >= 0x020406)
4251 static int bcm5700_resume(struct pci_dev *pdev)
4252 #else
4253 static void bcm5700_resume(struct pci_dev *pdev)
4254 #endif
4255 {
4256 struct net_device *dev = (struct net_device *) pci_get_drvdata(pdev);
4257 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) dev->priv;
4258 PLM_DEVICE_BLOCK pDevice = &pUmDevice->lm_dev;
4259
4260 if (!netif_running(dev))
4261 #if (LINUX_VERSION_CODE >= 0x020406)
4262 return 0;
4263 #else
4264 return;
4265 #endif
4266 /* pci_power_on(pdev);*/
4267 netif_device_attach(dev);
4268 LM_SetPowerState(pDevice, LM_POWER_STATE_D0);
4269 MM_InitializeUmPackets(pDevice);
4270 bcm5700_reset(dev);
4271 #if (LINUX_VERSION_CODE >= 0x020406)
4272 return 0;
4273 #endif
4274 }
4275
4276
4277 static struct pci_driver bcm5700_pci_driver = {
4278 name: bcm5700_driver,
4279 id_table: bcm5700_pci_tbl,
4280 probe: bcm5700_init_one,
4281 remove: __devexit_p(bcm5700_remove_one),
4282 suspend: bcm5700_suspend,
4283 resume: bcm5700_resume,
4284 };
4285
4286 static int
4287 bcm5700_notify_reboot(struct notifier_block *this, unsigned long event, void *unused)
4288 {
4289 switch (event) {
4290 case SYS_HALT:
4291 case SYS_POWER_OFF:
4292 case SYS_RESTART:
4293 break;
4294 default:
4295 return NOTIFY_DONE;
4296 }
4297
4298 B57_INFO(("bcm5700 reboot notification\n"));
4299 pci_unregister_driver(&bcm5700_pci_driver);
4300 return NOTIFY_DONE;
4301 }
4302
4303 static int __init bcm5700_init_module (void)
4304 {
4305 int pin = 1 << 2;
4306
4307 if (nvram_match("disabled_5397", "1") || (activate_gpio != -1)) {
4308 if ( activate_gpio != -1 ) pin = activate_gpio;
4309 printk("5397 switch GPIO-Reset (pin %d)\n", pin);
4310 sb_t *gpio_sbh;
4311 if (!(gpio_sbh = sb_kattach(SB_OSH))) return -ENODEV;
4312 sb_gpiosetcore(gpio_sbh);
4313 // sb_gpioreserve(gpio_sbh, 0x4, GPIO_HI_PRIORITY);
4314 sb_gpioouten(gpio_sbh, 0x4, 0x4, GPIO_HI_PRIORITY);
4315 sb_gpioout(gpio_sbh, 0x4, 0x4, GPIO_HI_PRIORITY);
4316 sb_detach(gpio_sbh);
4317 }
4318
4319 if (msglevel != 0xdeadbeef) {
4320 b57_msg_level = msglevel;
4321 printf("%s: msglevel set to 0x%x\n", __FUNCTION__, b57_msg_level);
4322 } else
4323 b57_msg_level = B57_ERR_VAL;
4324
4325 return pci_module_init(&bcm5700_pci_driver);
4326 }
4327
4328 static void __exit bcm5700_cleanup_module (void)
4329 {
4330 unregister_reboot_notifier(&bcm5700_reboot_notifier);
4331 pci_unregister_driver(&bcm5700_pci_driver);
4332 }
4333
4334 module_init(bcm5700_init_module);
4335 module_exit(bcm5700_cleanup_module);
4336 #endif
4337
4338 /*
4339 * Middle Module
4340 *
4341 */
4342
4343
4344 #ifdef BCM_NAPI_RXPOLL
4345 LM_STATUS
4346 MM_ScheduleRxPoll(LM_DEVICE_BLOCK *pDevice)
4347 {
4348 struct net_device *dev = ((UM_DEVICE_BLOCK *) pDevice)->dev;
4349
4350 if (netif_rx_schedule_prep(dev)) {
4351 __netif_rx_schedule(dev);
4352 return LM_STATUS_SUCCESS;
4353 }
4354 return LM_STATUS_FAILURE;
4355 }
4356 #endif
4357
4358 LM_STATUS
4359 MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4360 LM_UINT16 *pValue16)
4361 {
4362 UM_DEVICE_BLOCK *pUmDevice;
4363
4364 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4365 pci_read_config_word(pUmDevice->pdev, Offset, (u16 *) pValue16);
4366 return LM_STATUS_SUCCESS;
4367 }
4368
4369 LM_STATUS
4370 MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4371 LM_UINT32 *pValue32)
4372 {
4373 UM_DEVICE_BLOCK *pUmDevice;
4374
4375 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4376 pci_read_config_dword(pUmDevice->pdev, Offset, (u32 *) pValue32);
4377 return LM_STATUS_SUCCESS;
4378 }
4379
4380 LM_STATUS
4381 MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4382 LM_UINT16 Value16)
4383 {
4384 UM_DEVICE_BLOCK *pUmDevice;
4385
4386 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4387 pci_write_config_word(pUmDevice->pdev, Offset, Value16);
4388 return LM_STATUS_SUCCESS;
4389 }
4390
4391 LM_STATUS
4392 MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset,
4393 LM_UINT32 Value32)
4394 {
4395 UM_DEVICE_BLOCK *pUmDevice;
4396
4397 pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
4398 pci_write_config_dword(pUmDevice->pdev, Offset, Value32);
4399 return LM_STATUS_SUCCESS;
4400 }
4401
4402 LM_STATUS
4403 MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
4404 PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy,
4405 LM_BOOL Cached)
4406 {
4407 PLM_VOID pvirt;
4408 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4409 dma_addr_t mapping;
4410
4411 pvirt = pci_alloc_consistent(pUmDevice->pdev, BlockSize,
4412 &mapping);
4413 if (!pvirt) {
4414 return LM_STATUS_FAILURE;
4415 }
4416 pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
4417 pUmDevice->dma_list[pUmDevice->mem_list_num] = mapping;
4418 pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = BlockSize;
4419 memset(pvirt, 0, BlockSize);
4420 *pMemoryBlockVirt = (PLM_VOID) pvirt;
4421 MM_SetAddr(pMemoryBlockPhy, mapping);
4422 return LM_STATUS_SUCCESS;
4423 }
4424
4425 LM_STATUS
4426 MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize,
4427 PLM_VOID *pMemoryBlockVirt)
4428 {
4429 PLM_VOID pvirt;
4430 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4431
4432
4433 /* Maximum in slab.c */
4434 if (BlockSize > 131072) {
4435 goto MM_Alloc_error;
4436 }
4437
4438 pvirt = kmalloc(BlockSize, GFP_ATOMIC);
4439 if (!pvirt) {
4440 goto MM_Alloc_error;
4441 }
4442 pUmDevice->mem_list[pUmDevice->mem_list_num] = pvirt;
4443 pUmDevice->dma_list[pUmDevice->mem_list_num] = 0;
4444 pUmDevice->mem_size_list[pUmDevice->mem_list_num++] = 0;
4445 /* mem_size_list[i] == 0 indicates that the memory should be freed */
4446 /* using kfree */
4447 memset(pvirt, 0, BlockSize);
4448 *pMemoryBlockVirt = pvirt;
4449 return LM_STATUS_SUCCESS;
4450
4451 MM_Alloc_error:
4452 printk(KERN_WARNING "%s: Memory allocation failed - buffer parameters may be set too high\n", pUmDevice->dev->name);
4453 return LM_STATUS_FAILURE;
4454 }
4455
4456 LM_STATUS
4457 MM_MapMemBase(PLM_DEVICE_BLOCK pDevice)
4458 {
4459 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4460
4461 pDevice->pMappedMemBase = ioremap_nocache(
4462 pci_resource_start(pUmDevice->pdev, 0), sizeof(T3_STD_MEM_MAP));
4463 if (pDevice->pMappedMemBase == 0)
4464 return LM_STATUS_FAILURE;
4465
4466 return LM_STATUS_SUCCESS;
4467 }
4468
4469 LM_STATUS
4470 MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice)
4471 {
4472 unsigned int i;
4473 struct sk_buff *skb;
4474 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4475 PUM_PACKET pUmPacket;
4476 PLM_PACKET pPacket;
4477
4478 for (i = 0; i < pDevice->RxPacketDescCnt; i++) {
4479 pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container);
4480 pUmPacket = (PUM_PACKET) pPacket;
4481 if (pPacket == 0) {
4482 printk(KERN_DEBUG "Bad RxPacketFreeQ\n");
4483 }
4484 if (pUmPacket->skbuff == 0) {
4485 #ifdef BCM_WL_EMULATOR
4486 skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2);
4487 #else
4488 skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR);
4489 #endif
4490 if (skb == 0) {
4491 pUmPacket->skbuff = 0;
4492 QQ_PushTail(
4493 &pUmDevice->rx_out_of_buf_q.Container,
4494 pPacket);
4495 continue;
4496 }
4497 pUmPacket->skbuff = skb;
4498 skb->dev = pUmDevice->dev;
4499 #ifndef BCM_WL_EMULATOR
4500 skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
4501 #endif
4502 }
4503 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
4504 }
4505 if (T3_ASIC_REV(pUmDevice->lm_dev.ChipRevId) == T3_ASIC_REV_5700) {
4506 /* reallocate buffers in the ISR */
4507 pUmDevice->rx_buf_repl_thresh = 0;
4508 pUmDevice->rx_buf_repl_panic_thresh = 0;
4509 pUmDevice->rx_buf_repl_isr_limit = 0;
4510 }
4511 else {
4512 pUmDevice->rx_buf_repl_thresh = pDevice->RxPacketDescCnt / 8;
4513 pUmDevice->rx_buf_repl_panic_thresh =
4514 pDevice->RxPacketDescCnt * 7 / 8;
4515
4516 /* This limits the time spent in the ISR when the receiver */
4517 /* is in a steady state of being overrun. */
4518 pUmDevice->rx_buf_repl_isr_limit = pDevice->RxPacketDescCnt / 8;
4519
4520 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
4521 if (pDevice->RxJumboDescCnt != 0) {
4522 if (pUmDevice->rx_buf_repl_thresh >=
4523 pDevice->RxJumboDescCnt) {
4524
4525 pUmDevice->rx_buf_repl_thresh =
4526 pUmDevice->rx_buf_repl_panic_thresh =
4527 pDevice->RxJumboDescCnt - 1;
4528 }
4529 if (pUmDevice->rx_buf_repl_thresh >=
4530 pDevice->RxStdDescCnt) {
4531
4532 pUmDevice->rx_buf_repl_thresh =
4533 pUmDevice->rx_buf_repl_panic_thresh =
4534 pDevice->RxStdDescCnt - 1;
4535 }
4536 }
4537 #endif
4538 }
4539 return LM_STATUS_SUCCESS;
4540 }
4541
4542 LM_STATUS
4543 MM_GetConfig(PLM_DEVICE_BLOCK pDevice)
4544 {
4545 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
4546 int index = pUmDevice->index;
4547 struct net_device *dev = pUmDevice->dev;
4548
4549 if (index >= MAX_UNITS)
4550 return LM_STATUS_SUCCESS;
4551
4552 #if LINUX_KERNEL_VERSION < 0x0020609
4553
4554 bcm5700_validate_param_range(pUmDevice, &auto_speed[index], "auto_speed",
4555 0, 1, 1);
4556 if (auto_speed[index] == 0)
4557 pDevice->DisableAutoNeg = TRUE;
4558 else
4559 pDevice->DisableAutoNeg = FALSE;
4560
4561 if (line_speed[index] == 0) {
4562 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4563 pDevice->DisableAutoNeg = FALSE;
4564 }
4565 else {
4566 bcm5700_validate_param_range(pUmDevice, &full_duplex[index],
4567 "full_duplex", 0, 1, 1);
4568 if (full_duplex[index]) {
4569 pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
4570 }
4571 else {
4572 pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_HALF;
4573 }
4574
4575 if (line_speed[index] == 1000) {
4576 pDevice->RequestedLineSpeed = LM_LINE_SPEED_1000MBPS;
4577 if (pDevice->PhyFlags & PHY_NO_GIGABIT) {
4578 pDevice->RequestedLineSpeed =
4579 LM_LINE_SPEED_100MBPS;
4580 printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (1000), using 100\n", bcm5700_driver, index);
4581 }
4582 else {
4583 if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
4584 !full_duplex[index]) {
4585 printk(KERN_WARNING "%s-%d: Invalid full_duplex parameter (0) for fiber, using 1\n", bcm5700_driver, index);
4586 pDevice->RequestedDuplexMode =
4587 LM_DUPLEX_MODE_FULL;
4588 }
4589
4590 if (!(pDevice->TbiFlags & ENABLE_TBI_FLAG) &&
4591 !auto_speed[index] && !(pDevice->PhyFlags & PHY_IS_FIBER) ) {
4592 printk(KERN_WARNING "%s-%d: Invalid auto_speed parameter (0) for copper, using 1\n", bcm5700_driver, index);
4593 pDevice->DisableAutoNeg = FALSE;
4594 }
4595 }
4596 }
4597 else if ((pDevice->TbiFlags & ENABLE_TBI_FLAG) ||
4598 (pDevice->PhyFlags & PHY_IS_FIBER)){
4599 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4600 pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL;
4601 pDevice->DisableAutoNeg = FALSE;
4602 printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using auto\n", bcm5700_driver, index, line_speed[index]);
4603 }
4604 else if (line_speed[index] == 100) {
4605
4606 pDevice->RequestedLineSpeed = LM_LINE_SPEED_100MBPS;
4607 }
4608 else if (line_speed[index] == 10) {
4609
4610 pDevice->RequestedLineSpeed = LM_LINE_SPEED_10MBPS;
4611 }
4612 else {
4613 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4614 pDevice->DisableAutoNeg = FALSE;
4615 printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n", bcm5700_driver, index, line_speed[index]);
4616 }
4617
4618 }
4619
4620 #endif /* LINUX_KERNEL_VERSION */
4621
4622 /* This is an unmanageable switch nic and will have link problems if
4623 not set to auto
4624 */
4625 if(pDevice->SubsystemVendorId==0x103c && pDevice->SubsystemId==0x3226)
4626 {
4627 if(pDevice->RequestedLineSpeed != LM_LINE_SPEED_AUTO)
4628 {
4629 printk(KERN_WARNING "%s-%d: Invalid line_speed parameter (%d), using 0\n",
4630 bcm5700_driver, index, line_speed[index]);
4631 }
4632 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO;
4633 pDevice->DisableAutoNeg = FALSE;
4634 }
4635
4636 #if LINUX_KERNEL_VERSION < 0x0020609
4637
4638 pDevice->FlowControlCap = 0;
4639 bcm5700_validate_param_range(pUmDevice, &rx_flow_control[index],
4640 "rx_flow_control", 0, 1, 0);
4641 if (rx_flow_control[index] != 0) {
4642 pDevice->FlowControlCap |= LM_FLOW_CONTROL_RECEIVE_PAUSE;
4643 }
4644 bcm5700_validate_param_range(pUmDevice, &tx_flow_control[index],
4645 "tx_flow_control", 0, 1, 0);
4646 if (tx_flow_control[index] != 0) {
4647 pDevice->FlowControlCap |= LM_FLOW_CONTROL_TRANSMIT_PAUSE;
4648 }
4649 bcm5700_validate_param_range(pUmDevice, &auto_flow_control[index],
4650 "auto_flow_control", 0, 1, 0);
4651 if (auto_flow_control[index] != 0) {
4652 if (pDevice->DisableAutoNeg == FALSE) {
4653
4654 pDevice->FlowControlCap |= LM_FLOW_CONTROL_AUTO_PAUSE;
4655 if ((tx_flow_control[index] == 0) &&
4656 (rx_flow_control[index] == 0)) {
4657
4658 pDevice->FlowControlCap |=
4659 LM_FLOW_CONTROL_TRANSMIT_PAUSE |
4660 LM_FLOW_CONTROL_RECEIVE_PAUSE;
4661 }
4662 }
4663 }
4664
4665 if (dev->mtu > 1500) {
4666 #ifdef BCM_TSO
4667 if (T3_ASIC_5714_FAMILY(pDevice->ChipRevId) &&
4668 (dev->features & NETIF_F_TSO)) {
4669 dev->features &= ~NETIF_F_TSO;
4670 printk(KERN_ALERT "%s: TSO previously enabled. Jumbo Frames and TSO cannot simultaneously be enabled. Jumbo Frames enabled. TSO disabled.\n", dev->name);
4671 }
4672 #endif
4673 pDevice->RxMtu = dev->mtu + 14;
4674 }
4675
4676 if ((T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700) &&
4677 !(pDevice->Flags & BCM5788_FLAG)) {
4678 pDevice->Flags |= USE_TAGGED_STATUS_FLAG;
4679 pUmDevice->timer_interval = HZ;
4680 if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) &&
4681 (pDevice->TbiFlags & ENABLE_TBI_FLAG)) {
4682 pUmDevice->timer_interval = HZ/4;
4683 }
4684 }
4685 else {
4686 pUmDevice->timer_interval = HZ/10;
4687 }
4688
4689 bcm5700_validate_param_range(pUmDevice, &tx_pkt_desc_cnt[index],
4690 "tx_pkt_desc_cnt", 1, MAX_TX_PACKET_DESC_COUNT-1, TX_DESC_CNT);
4691 pDevice->TxPacketDescCnt = tx_pkt_desc_cnt[index];
4692 bcm5700_validate_param_range(pUmDevice, &rx_std_desc_cnt[index],
4693 "rx_std_desc_cnt", 1, T3_STD_RCV_RCB_ENTRY_COUNT-1,
4694 RX_DESC_CNT);
4695 pDevice->RxStdDescCnt = rx_std_desc_cnt[index];
4696
4697 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
4698 bcm5700_validate_param_range(pUmDevice, &rx_jumbo_desc_cnt[index],
4699 "rx_jumbo_desc_cnt", 1, T3_JUMBO_RCV_RCB_ENTRY_COUNT-1,
4700 JBO_DESC_CNT);
4701
4702 if (mtu[index] <= 1514)
4703 pDevice->RxJumboDescCnt = 0;
4704 else if(!T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)){
4705 pDevice->RxJumboDescCnt = rx_jumbo_desc_cnt[index];
4706 }
4707 #endif
4708
4709 #ifdef BCM_INT_COAL
4710 bcm5700_validate_param_range(pUmDevice, &adaptive_coalesce[index],
4711 "adaptive_coalesce", 0, 1, 1);
4712 #ifdef BCM_NAPI_RXPOLL
4713 if (adaptive_coalesce[index]) {
4714 printk(KERN_WARNING "%s-%d: adaptive_coalesce not used in NAPI mode\n", bcm5700_driver, index);
4715 adaptive_coalesce[index] = 0;
4716
4717 }
4718 #endif
4719 pUmDevice->adaptive_coalesce = adaptive_coalesce[index];
4720 if (!pUmDevice->adaptive_coalesce) {
4721 bcm5700_validate_param_range(pUmDevice,
4722 &rx_coalesce_ticks[index], "rx_coalesce_ticks", 0,
4723 MAX_RX_COALESCING_TICKS, RX_COAL_TK);
4724 if ((rx_coalesce_ticks[index] == 0) &&
4725 (rx_max_coalesce_frames[index] == 0)) {
4726
4727 printk(KERN_WARNING "%s-%d: Conflicting rx_coalesce_ticks (0) and rx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
4728 bcm5700_driver, index, RX_COAL_TK, RX_COAL_FM);
4729
4730 rx_coalesce_ticks[index] = RX_COAL_TK;
4731 rx_max_coalesce_frames[index] = RX_COAL_FM;
4732 }
4733 pDevice->RxCoalescingTicks = pUmDevice->rx_curr_coalesce_ticks =
4734 rx_coalesce_ticks[index];
4735 #ifdef BCM_NAPI_RXPOLL
4736 pDevice->RxCoalescingTicksDuringInt = rx_coalesce_ticks[index];
4737 #endif
4738
4739 bcm5700_validate_param_range(pUmDevice,
4740 &rx_max_coalesce_frames[index],
4741 "rx_max_coalesce_frames", 0,
4742 MAX_RX_MAX_COALESCED_FRAMES, RX_COAL_FM);
4743
4744 pDevice->RxMaxCoalescedFrames =
4745 pUmDevice->rx_curr_coalesce_frames =
4746 rx_max_coalesce_frames[index];
4747 #ifdef BCM_NAPI_RXPOLL
4748 pDevice->RxMaxCoalescedFramesDuringInt =
4749 rx_max_coalesce_frames[index];
4750 #endif
4751
4752 bcm5700_validate_param_range(pUmDevice,
4753 &tx_coalesce_ticks[index], "tx_coalesce_ticks", 0,
4754 MAX_TX_COALESCING_TICKS, TX_COAL_TK);
4755 if ((tx_coalesce_ticks[index] == 0) &&
4756 (tx_max_coalesce_frames[index] == 0)) {
4757
4758 printk(KERN_WARNING "%s-%d: Conflicting tx_coalesce_ticks (0) and tx_max_coalesce_frames (0) parameters, using %d and %d respectively\n",
4759 bcm5700_driver, index, TX_COAL_TK, TX_COAL_FM);
4760
4761 tx_coalesce_ticks[index] = TX_COAL_TK;
4762 tx_max_coalesce_frames[index] = TX_COAL_FM;
4763 }
4764 pDevice->TxCoalescingTicks = tx_coalesce_ticks[index];
4765 bcm5700_validate_param_range(pUmDevice,
4766 &tx_max_coalesce_frames[index],
4767 "tx_max_coalesce_frames", 0,
4768 MAX_TX_MAX_COALESCED_FRAMES, TX_COAL_FM);
4769 pDevice->TxMaxCoalescedFrames = tx_max_coalesce_frames[index];
4770 pUmDevice->tx_curr_coalesce_frames =
4771 pDevice->TxMaxCoalescedFrames;
4772
4773 bcm5700_validate_param_range(pUmDevice,
4774 &stats_coalesce_ticks[index], "stats_coalesce_ticks",
4775 0, MAX_STATS_COALESCING_TICKS, ST_COAL_TK);
4776 if (adaptive_coalesce[index]) {
4777 printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter set with with adaptive_coalesce parameter. Using adaptive_coalesce.\n", bcm5700_driver, index);
4778 }else{
4779 if ((stats_coalesce_ticks[index] > 0) &&
4780 (stats_coalesce_ticks[index] < 100)) {
4781 printk(KERN_WARNING "%s-%d: Invalid stats_coalesce_ticks parameter (%u), using 100\n", bcm5700_driver, index, (unsigned int) stats_coalesce_ticks[index]);
4782 stats_coalesce_ticks[index] = 100;
4783 pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
4784 pDevice->StatsCoalescingTicks = stats_coalesce_ticks[index];
4785 }
4786 }
4787 }
4788 else {
4789 pUmDevice->rx_curr_coalesce_frames = RX_COAL_FM;
4790 pUmDevice->rx_curr_coalesce_ticks = RX_COAL_TK;
4791 pUmDevice->tx_curr_coalesce_frames = TX_COAL_FM;
4792 }
4793 #endif
4794
4795 if (T3_ASIC_IS_5705_BEYOND(pDevice->ChipRevId)) {
4796 unsigned int tmpvar;
4797
4798 tmpvar = pDevice->StatsCoalescingTicks / BCM_TIMER_GRANULARITY;
4799
4800 /*
4801 * If the result is zero, the request is too demanding.
4802 */
4803 if (tmpvar == 0) {
4804 tmpvar = 1;
4805 }
4806
4807 pDevice->StatsCoalescingTicks = tmpvar * BCM_TIMER_GRANULARITY;
4808
4809 pUmDevice->statstimer_interval = tmpvar;
4810 }
4811
4812 #ifdef BCM_WOL
4813 bcm5700_validate_param_range(pUmDevice, &enable_wol[index],
4814 "enable_wol", 0, 1, 0);
4815 if (enable_wol[index]) {
4816 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_MAGIC_PACKET;
4817 pDevice->WakeUpMode = LM_WAKE_UP_MODE_MAGIC_PACKET;
4818 }
4819 #endif
4820 #ifdef INCLUDE_TBI_SUPPORT
4821 if (pDevice->TbiFlags & ENABLE_TBI_FLAG) {
4822 if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) ||
4823 (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703)) {
4824 /* just poll since we have hardware autoneg. in 5704 */
4825 pDevice->TbiFlags |= TBI_PURE_POLLING_FLAG;
4826 }
4827 else {
4828 pDevice->TbiFlags |= TBI_POLLING_INTR_FLAG;
4829 }
4830 }
4831 #endif
4832 bcm5700_validate_param_range(pUmDevice, &scatter_gather[index],
4833 "scatter_gather", 0, 1, 1);
4834 bcm5700_validate_param_range(pUmDevice, &tx_checksum[index],
4835 "tx_checksum", 0, 1, 1);
4836 bcm5700_validate_param_range(pUmDevice, &rx_checksum[index],
4837 "rx_checksum", 0, 1, 1);
4838 if (!(pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TX_TCP_CHECKSUM)) {
4839 if (tx_checksum[index] || rx_checksum[index]) {
4840
4841 pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE;
4842 printk(KERN_WARNING "%s-%d: Checksum offload not available on this NIC\n", bcm5700_driver, index);
4843 }
4844 }
4845 else {
4846 if (rx_checksum[index]) {
4847 pDevice->TaskToOffload |=
4848 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM |
4849 LM_TASK_OFFLOAD_RX_UDP_CHECKSUM;
4850 }
4851 if (tx_checksum[index]) {
4852 pDevice->TaskToOffload |=
4853 LM_TASK_OFFLOAD_TX_TCP_CHECKSUM |
4854 LM_TASK_OFFLOAD_TX_UDP_CHECKSUM;
4855 pDevice->Flags |= NO_TX_PSEUDO_HDR_CSUM_FLAG;
4856 }
4857 }
4858 #ifdef BCM_TSO
4859 bcm5700_validate_param_range(pUmDevice, &enable_tso[index],
4860 "enable_tso", 0, 1, 1);
4861
4862 /* Always enable TSO firmware if supported */
4863 /* This way we can turn it on or off on the fly */
4864 if (pDevice->TaskOffloadCap & LM_TASK_OFFLOAD_TCP_SEGMENTATION)
4865 {
4866 pDevice->TaskToOffload |=
4867 LM_TASK_OFFLOAD_TCP_SEGMENTATION;
4868 }
4869 if (enable_tso[index] &&
4870 !(pDevice->TaskToOffload & LM_TASK_OFFLOAD_TCP_SEGMENTATION))
4871 {
4872 printk(KERN_WARNING "%s-%d: TSO not available on this NIC\n", bcm5700_driver, index);
4873 }
4874 #endif
4875 #ifdef BCM_ASF
4876 bcm5700_validate_param_range(pUmDevice, &vlan_tag_mode[index],
4877 "vlan_strip_mode", 0, 2, 0);
4878 pUmDevice->vlan_tag_mode = vlan_tag_mode[index];
4879 #else
4880 pUmDevice->vlan_tag_mode = VLAN_TAG_MODE_NORMAL_STRIP;
4881 #endif
4882
4883 #endif /* LINUX_KERNEL_VERSION */
4884
4885 #ifdef BCM_NIC_SEND_BD
4886 bcm5700_validate_param_range(pUmDevice, &nic_tx_bd[index], "nic_tx_bd",
4887 0, 1, 0);
4888 if (nic_tx_bd[index])
4889 pDevice->Flags |= NIC_SEND_BD_FLAG;
4890 if ((pDevice->Flags & ENABLE_PCIX_FIX_FLAG) ||
4891 (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5705)) {
4892 if (pDevice->Flags & NIC_SEND_BD_FLAG) {
4893 pDevice->Flags &= ~NIC_SEND_BD_FLAG;
4894 printk(KERN_WARNING "%s-%d: Nic Send BDs not available on this NIC or not possible on this system\n", bcm5700_driver, index);
4895 }
4896 }
4897 #endif
4898 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_PCI_USE_VECTOR)
4899 bcm5700_validate_param_range(pUmDevice, &disable_msi[pUmDevice->index],
4900 "disable_msi", 0, 1, 0);
4901 #endif
4902
4903 bcm5700_validate_param_range(pUmDevice, &delay_link[index],
4904 "delay_link", 0, 1, 0);
4905
4906 bcm5700_validate_param_range(pUmDevice, &disable_d3hot[index],
4907 "disable_d3hot", 0, 1, 0);
4908 if (disable_d3hot[index]) {
4909
4910 #ifdef BCM_WOL
4911 if (enable_wol[index]) {
4912 pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE;
4913 pDevice->WakeUpMode = LM_WAKE_UP_MODE_NONE;
4914 printk(KERN_WARNING "%s-%d: Wake-On-Lan disabled because D3Hot is disabled\n", bcm5700_driver, index);
4915 }
4916 #endif
4917 pDevice->Flags |= DISABLE_D3HOT_FLAG;
4918 }
4919
4920 return LM_STATUS_SUCCESS;
4921 }
4922
4923 /* From include/proto/ethernet.h */
4924 #define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */
4925
4926 /* From include/proto/vlan.h */
4927 #define VLAN_PRI_MASK 7 /* 3 bits of priority */
4928 #define VLAN_PRI_SHIFT 13
4929
4930 /* Replace the priority in a vlan tag */
4931 #define UPD_VLANTAG_PRIO(tag, prio) do { \
4932 tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); \
4933 tag |= prio << VLAN_PRI_SHIFT; \
4934 } while (0)
4935
4936 /* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
4937 * Also updates the inplace vlan tag if requested.
4938 * For debugging, it returns an indication of what it did.
4939 */
4940 #define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */
4941 #define PKTPRIO_VLAN 0x200 /* VLAN prio found */
4942 #define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */
4943 #define PKTPRIO_DSCP 0x800 /* DSCP prio found */
4944 #define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x))
4945 static uint
4946 pktsetprio(void *pkt, bool update_vtag)
4947 {
4948 struct ether_header *eh;
4949 struct ethervlan_header *evh;
4950 uint8 *pktdata;
4951 int priority = 0;
4952 int rc = 0;
4953
4954 pktdata = (uint8 *) PKTDATA(NULL, pkt);
4955 ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
4956
4957 eh = (struct ether_header *) pktdata;
4958
4959 if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) {
4960 uint16 vlan_tag;
4961 int vlan_prio, dscp_prio = 0;
4962
4963 evh = (struct ethervlan_header *)eh;
4964
4965 vlan_tag = ntoh16(evh->vlan_tag);
4966 vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
4967
4968 if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) {
4969 uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
4970 uint8 tos_tc = IP_TOS(ip_body);
4971 dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
4972 if ((IP_VER(ip_body) == IP_VER_4) && (IPV4_PROT(ip_body) == IP_PROT_TCP)) {
4973 int ip_len;
4974 int src_port;
4975 bool src_port_exc;
4976 uint8 *tcp_hdr;
4977
4978 ip_len = IPV4_PAYLOAD_LEN(ip_body);
4979 tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD(ip_body);
4980 src_port = TCP_SRC_PORT(tcp_hdr);
4981 src_port_exc = (src_port == 10110) || (src_port == 10120) ||
4982 (src_port == 10130) || (src_port == 10140);
4983
4984 if ((ip_len == 40) && src_port_exc && TCP_IS_ACK(tcp_hdr)) {
4985 dscp_prio = 7;
4986 }
4987 }
4988 }
4989
4990 /* DSCP priority gets precedence over 802.1P (vlan tag) */
4991 if (dscp_prio != 0) {
4992 priority = dscp_prio;
4993 rc |= PKTPRIO_VDSCP;
4994 } else {
4995 priority = vlan_prio;
4996 rc |= PKTPRIO_VLAN;
4997 }
4998 /*
4999 * If the DSCP priority is not the same as the VLAN priority,
5000 * then overwrite the priority field in the vlan tag, with the
5001 * DSCP priority value. This is required for Linux APs because
5002 * the VLAN driver on Linux, overwrites the skb->priority field
5003 * with the priority value in the vlan tag
5004 */
5005 if (update_vtag && (priority != vlan_prio)) {
5006 vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
5007 vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
5008 evh->vlan_tag = hton16(vlan_tag);
5009 rc |= PKTPRIO_UPD;
5010 }
5011 } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
5012 uint8 *ip_body = pktdata + sizeof(struct ether_header);
5013 uint8 tos_tc = IP_TOS(ip_body);
5014 priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
5015 rc |= PKTPRIO_DSCP;
5016 if ((IP_VER(ip_body) == IP_VER_4) && (IPV4_PROT(ip_body) == IP_PROT_TCP)) {
5017 int ip_len;
5018 int src_port;
5019 bool src_port_exc;
5020 uint8 *tcp_hdr;
5021
5022 ip_len = IPV4_PAYLOAD_LEN(ip_body);
5023 tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD(ip_body);
5024 src_port = TCP_SRC_PORT(tcp_hdr);
5025 src_port_exc = (src_port == 10110) || (src_port == 10120) ||
5026 (src_port == 10130) || (src_port == 10140);
5027
5028 if ((ip_len == 40) && src_port_exc && TCP_IS_ACK(tcp_hdr)) {
5029 priority = 7;
5030 }
5031 }
5032 }
5033
5034 ASSERT(priority >= 0 && priority <= MAXPRIO);
5035 PKTSETPRIO(pkt, priority);
5036 return (rc | priority);
5037 }
5038
5039 LM_STATUS
5040 MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice)
5041 {
5042 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5043 PLM_PACKET pPacket;
5044 PUM_PACKET pUmPacket;
5045 struct sk_buff *skb;
5046 int size;
5047 int vlan_tag_size = 0;
5048 uint16 dscp_prio;
5049
5050 if (pDevice->ReceiveMask & LM_KEEP_VLAN_TAG)
5051 vlan_tag_size = 4;
5052
5053 while (1) {
5054 pPacket = (PLM_PACKET)
5055 QQ_PopHead(&pDevice->RxPacketReceivedQ.Container);
5056 if (pPacket == 0)
5057 break;
5058 pUmPacket = (PUM_PACKET) pPacket;
5059 #if !defined(NO_PCI_UNMAP)
5060 pci_unmap_single(pUmDevice->pdev,
5061 pci_unmap_addr(pUmPacket, map[0]),
5062 pPacket->u.Rx.RxBufferSize,
5063 PCI_DMA_FROMDEVICE);
5064 #endif
5065 if ((pPacket->PacketStatus != LM_STATUS_SUCCESS) ||
5066 ((size = pPacket->PacketSize) >
5067 (pDevice->RxMtu + vlan_tag_size))) {
5068
5069 /* reuse skb */
5070 #ifdef BCM_TASKLET
5071 QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
5072 #else
5073 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5074 #endif
5075 pUmDevice->rx_misc_errors++;
5076 continue;
5077 }
5078 skb = pUmPacket->skbuff;
5079 skb_put(skb, size);
5080 skb->pkt_type = 0;
5081 /* Extract priority from payload and put it in skb->priority */
5082 dscp_prio = 0;
5083 if (pUmDevice->qos) {
5084 uint rc;
5085
5086 rc = pktsetprio(skb, TRUE);
5087 if (rc & (PKTPRIO_VDSCP | PKTPRIO_DSCP))
5088 dscp_prio = rc & VLAN_PRI_MASK;
5089 if (rc != 0)
5090 B57_INFO(("pktsetprio returned 0x%x, skb->priority: %d\n",
5091 rc, skb->priority));
5092 }
5093 skb->protocol = eth_type_trans(skb, skb->dev);
5094 if (size > pDevice->RxMtu) {
5095 /* Make sure we have a valid VLAN tag */
5096 if (htons(skb->protocol) != ETHER_TYPE_8021Q) {
5097 dev_kfree_skb_irq(skb);
5098 pUmDevice->rx_misc_errors++;
5099 goto drop_rx;
5100 }
5101 }
5102
5103 pUmDevice->stats.rx_bytes += skb->len;
5104
5105 if ((pPacket->Flags & RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD) &&
5106 (pDevice->TaskToOffload &
5107 LM_TASK_OFFLOAD_RX_TCP_CHECKSUM)) {
5108 if (pPacket->u.Rx.TcpUdpChecksum == 0xffff) {
5109
5110 skb->ip_summed = CHECKSUM_UNNECESSARY;
5111 #if TIGON3_DEBUG
5112 pUmDevice->rx_good_chksum_count++;
5113 #endif
5114 }
5115 else {
5116 skb->ip_summed = CHECKSUM_NONE;
5117 pUmDevice->rx_bad_chksum_count++;
5118 }
5119 }
5120 else {
5121 skb->ip_summed = CHECKSUM_NONE;
5122 }
5123 {
5124 #ifdef BCM_VLAN
5125 if (pUmDevice->vlgrp &&
5126 (pPacket->Flags & RCV_BD_FLAG_VLAN_TAG)) {
5127 /* Override vlan priority with dscp priority */
5128 if (dscp_prio)
5129 UPD_VLANTAG_PRIO(pPacket->VlanTag, dscp_prio);
5130 #ifdef BCM_NAPI_RXPOLL
5131 vlan_hwaccel_receive_skb(skb, pUmDevice->vlgrp,
5132 pPacket->VlanTag);
5133 #else
5134 vlan_hwaccel_rx(skb, pUmDevice->vlgrp,
5135 pPacket->VlanTag);
5136 #endif
5137 } else
5138 #endif
5139 {
5140 #ifdef BCM_WL_EMULATOR
5141 if(pDevice->wl_emulate_rx) {
5142 /* bcmstats("emu recv %d %d"); */
5143 wlcemu_receive_skb(pDevice->wlc, skb);
5144 /* bcmstats("emu recv end %d %d"); */
5145 }
5146 else
5147 #endif /* BCM_WL_EMULATOR */
5148 {
5149 #ifdef BCM_NAPI_RXPOLL
5150 netif_receive_skb(skb);
5151 #else
5152 netif_rx(skb);
5153 #endif
5154 }
5155 }
5156 }
5157 pUmDevice->dev->last_rx = jiffies;
5158
5159 drop_rx:
5160 #ifdef BCM_TASKLET
5161 pUmPacket->skbuff = 0;
5162 QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
5163 #else
5164 #ifdef BCM_WL_EMULATOR
5165 skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2);
5166 #else
5167 skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR);
5168 #endif /* BCM_WL_EMULATOR */
5169 if (skb == 0) {
5170 pUmPacket->skbuff = 0;
5171 QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket);
5172 }
5173 else {
5174 pUmPacket->skbuff = skb;
5175 skb->dev = pUmDevice->dev;
5176 #ifndef BCM_WL_EMULATOR
5177 skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
5178 #endif
5179 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5180 }
5181 #endif
5182 }
5183 return LM_STATUS_SUCCESS;
5184 }
5185
5186 LM_STATUS
5187 MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
5188 {
5189 PUM_PACKET pUmPacket = (PUM_PACKET) pPacket;
5190 struct sk_buff *skb = pUmPacket->skbuff;
5191 struct sk_buff *nskb;
5192 #if !defined(NO_PCI_UNMAP)
5193 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5194
5195 pci_unmap_single(pUmDevice->pdev,
5196 pci_unmap_addr(pUmPacket, map[0]),
5197 pci_unmap_len(pUmPacket, map_len[0]),
5198 PCI_DMA_TODEVICE);
5199 #if MAX_SKB_FRAGS
5200 {
5201 int i;
5202
5203 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5204 pci_unmap_page(pUmDevice->pdev,
5205 pci_unmap_addr(pUmPacket, map[i + 1]),
5206 pci_unmap_len(pUmPacket, map_len[i + 1]),
5207 PCI_DMA_TODEVICE);
5208 }
5209 }
5210 #endif
5211 #endif
5212 if ((nskb = skb_copy(skb, GFP_ATOMIC))) {
5213 pUmPacket->lm_packet.u.Tx.FragCount = 1;
5214 dev_kfree_skb(skb);
5215 pUmPacket->skbuff = nskb;
5216 return LM_STATUS_SUCCESS;
5217 }
5218 dev_kfree_skb(skb);
5219 pUmPacket->skbuff = 0;
5220 return LM_STATUS_FAILURE;
5221 }
5222
5223 /* Returns 1 if not all buffers are allocated */
5224 STATIC int
5225 replenish_rx_buffers(PUM_DEVICE_BLOCK pUmDevice, int max)
5226 {
5227 PLM_PACKET pPacket;
5228 PUM_PACKET pUmPacket;
5229 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice;
5230 struct sk_buff *skb;
5231 int queue_rx = 0;
5232 int alloc_cnt = 0;
5233 int ret = 0;
5234
5235 while ((pUmPacket = (PUM_PACKET)
5236 QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container)) != 0) {
5237 pPacket = (PLM_PACKET) pUmPacket;
5238 if (pUmPacket->skbuff) {
5239 /* reuse an old skb */
5240 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5241 queue_rx = 1;
5242 continue;
5243 }
5244 #ifdef BCM_WL_EMULATOR
5245 if ((skb = (struct sk_buff *)wlcemu_pktget(pDevice->wlc,pPacket->u.Rx.RxBufferSize + 2)) == 0)
5246 #else
5247 if ((skb = dev_alloc_skb(pPacket->u.Rx.RxBufferSize + 2 + EXTRA_HDR)) == 0)
5248 #endif /* BCM_WL_EMULATOR */
5249 {
5250 QQ_PushHead(&pUmDevice->rx_out_of_buf_q.Container,
5251 pPacket);
5252 ret = 1;
5253 break;
5254 }
5255 pUmPacket->skbuff = skb;
5256 skb->dev = pUmDevice->dev;
5257 #ifndef BCM_WL_EMULATOR
5258 skb_reserve(skb, EXTRA_HDR - pUmDevice->rx_buf_align);
5259 #endif
5260 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket);
5261 queue_rx = 1;
5262 if (max > 0) {
5263 alloc_cnt++;
5264 if (alloc_cnt >= max)
5265 break;
5266 }
5267 }
5268 if (queue_rx || pDevice->QueueAgain) {
5269 LM_QueueRxPackets(pDevice);
5270 }
5271 return ret;
5272 }
5273
5274 LM_STATUS
5275 MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice)
5276 {
5277 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5278 PLM_PACKET pPacket;
5279 PUM_PACKET pUmPacket;
5280 struct sk_buff *skb;
5281 #if !defined(NO_PCI_UNMAP) && MAX_SKB_FRAGS
5282 int i;
5283 #endif
5284
5285 while (1) {
5286 pPacket = (PLM_PACKET)
5287 QQ_PopHead(&pDevice->TxPacketXmittedQ.Container);
5288 if (pPacket == 0)
5289 break;
5290 pUmPacket = (PUM_PACKET) pPacket;
5291 skb = pUmPacket->skbuff;
5292 #if !defined(NO_PCI_UNMAP)
5293 pci_unmap_single(pUmDevice->pdev,
5294 pci_unmap_addr(pUmPacket, map[0]),
5295 pci_unmap_len(pUmPacket, map_len[0]),
5296 PCI_DMA_TODEVICE);
5297 #if MAX_SKB_FRAGS
5298 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
5299 pci_unmap_page(pUmDevice->pdev,
5300 pci_unmap_addr(pUmPacket, map[i + 1]),
5301 pci_unmap_len(pUmPacket, map_len[i + 1]),
5302 PCI_DMA_TODEVICE);
5303 }
5304 #endif
5305 #endif
5306 dev_kfree_skb_irq(skb);
5307 pUmPacket->skbuff = 0;
5308 QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket);
5309 }
5310 if (pUmDevice->tx_full) {
5311 if (QQ_GetEntryCnt(&pDevice->TxPacketFreeQ.Container) >=
5312 (pDevice->TxPacketDescCnt >> 1)) {
5313
5314 pUmDevice->tx_full = 0;
5315 netif_wake_queue(pUmDevice->dev);
5316 }
5317 }
5318 return LM_STATUS_SUCCESS;
5319 }
5320
5321 LM_STATUS
5322 MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status)
5323 {
5324 PUM_DEVICE_BLOCK pUmDevice = (PUM_DEVICE_BLOCK) pDevice;
5325 struct net_device *dev = pUmDevice->dev;
5326 LM_FLOW_CONTROL flow_control;
5327 int speed = 0;
5328
5329 if (!pUmDevice->opened)
5330 return LM_STATUS_SUCCESS;
5331
5332 if (!pUmDevice->suspended) {
5333 if (Status == LM_STATUS_LINK_DOWN) {
5334 netif_carrier_off(dev);
5335 }
5336 else if (Status == LM_STATUS_LINK_ACTIVE) {
5337 netif_carrier_on(dev);
5338 }
5339 }
5340
5341 if (pUmDevice->delayed_link_ind > 0) {
5342 pUmDevice->delayed_link_ind = 0;
5343 if (Status == LM_STATUS_LINK_DOWN) {
5344 B57_INFO(("%s: %s NIC Link is DOWN\n", bcm5700_driver, dev->name));
5345 }
5346 else if (Status == LM_STATUS_LINK_ACTIVE) {
5347 B57_INFO(("%s: %s NIC Link is UP, ", bcm5700_driver, dev->name));
5348 }
5349 }
5350 else {
5351 if (Status == LM_STATUS_LINK_DOWN) {
5352 B57_INFO(("%s: %s NIC Link is Down\n", bcm5700_driver, dev->name));
5353 }
5354 else if (Status == LM_STATUS_LINK_ACTIVE) {
5355 B57_INFO(("%s: %s NIC Link is Up, ", bcm5700_driver, dev->name));
5356 }
5357 }
5358
5359 if (Status == LM_STATUS_LINK_ACTIVE) {
5360 if (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS)
5361 speed = 1000;
5362 else if (pDevice->LineSpeed == LM_LINE_SPEED_100MBPS)
5363 speed = 100;
5364 else if (pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)
5365 speed = 10;
5366
5367 B57_INFO(("%d Mbps ", speed));
5368
5369 if (pDevice->DuplexMode == LM_DUPLEX_MODE_FULL)
5370 B57_INFO(("full duplex"));
5371 else
5372 B57_INFO(("half duplex"));
5373
5374 flow_control = pDevice->FlowControl &
5375 (LM_FLOW_CONTROL_RECEIVE_PAUSE |
5376 LM_FLOW_CONTROL_TRANSMIT_PAUSE);
5377 if (flow_control) {
5378 if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) {
5379 B57_INFO((", receive "));
5380 if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE)
5381 B57_INFO(("& transmit "));
5382 }
5383 else {
5384 B57_INFO((", transmit "));
5385 }
5386 B57_INFO(("flow control ON"));
5387 }
5388 B57_INFO(("\n"));
5389 }
5390 return LM_STATUS_SUCCESS;
5391 }
5392
5393 void
5394 MM_UnmapRxDma(LM_DEVICE_BLOCK *pDevice, LM_PACKET *pPacket)
5395 {
5396 #if !defined(NO_PCI_UNMAP)
5397 UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
5398 UM_PACKET *pUmPacket = (UM_PACKET *) pPacket;
5399
5400 if (!pUmPacket->skbuff)
5401 return;
5402
5403 pci_unmap_single(pUmDevice->pdev,
5404 pci_unmap_addr(pUmPacket, map[0]),
5405 pPacket->u.Rx.RxBufferSize,
5406 PCI_DMA_FROMDEVICE);
5407 #endif
5408 }
5409
5410 LM_STATUS
5411 MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket)
5412 {
5413 PUM_PACKET pUmPacket;
5414 struct sk_buff *skb;
5415
5416 if (pPacket == 0)
5417 return LM_STATUS_SUCCESS;
5418 pUmPacket = (PUM_PACKET) pPacket;
5419 if ((skb = pUmPacket->skbuff)) {
5420 /* DMA address already unmapped */
5421 dev_kfree_skb(skb);
5422 }
5423 pUmPacket->skbuff = 0;
5424 return LM_STATUS_SUCCESS;
5425 }
5426
5427 LM_STATUS
5428 MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec)
5429 {
5430 current->state = TASK_INTERRUPTIBLE;
5431 if (schedule_timeout(HZ * msec / 1000) != 0) {
5432 return LM_STATUS_FAILURE;
5433 }
5434 if (signal_pending(current))
5435 return LM_STATUS_FAILURE;
5436
5437 return LM_STATUS_SUCCESS;
5438 }
5439
5440 void
5441 bcm5700_shutdown(UM_DEVICE_BLOCK *pUmDevice)
5442 {
5443 LM_DEVICE_BLOCK *pDevice = (LM_DEVICE_BLOCK *) pUmDevice;
5444
5445 bcm5700_intr_off(pUmDevice);
5446 netif_carrier_off(pUmDevice->dev);
5447 #ifdef BCM_TASKLET
5448 tasklet_kill(&pUmDevice->tasklet);
5449 #endif
5450 bcm5700_poll_wait(pUmDevice);
5451
5452 LM_Halt(pDevice);
5453
5454 pDevice->InitDone = 0;
5455 bcm5700_free_remaining_rx_bufs(pUmDevice);
5456 }
5457
5458 void
5459 bcm5700_free_remaining_rx_bufs(UM_DEVICE_BLOCK *pUmDevice)
5460 {
5461 LM_DEVICE_BLOCK *pDevice = &pUmDevice->lm_dev;
5462 UM_PACKET *pUmPacket;
5463 int cnt, i;
5464
5465 cnt = QQ_GetEntryCnt(&pUmDevice->rx_out_of_buf_q.Container);
5466 for (i = 0; i < cnt; i++) {
5467 if ((pUmPacket =
5468 QQ_PopHead(&pUmDevice->rx_out_of_buf_q.Container))
5469 != 0) {
5470
5471 MM_UnmapRxDma(pDevice, (LM_PACKET *) pUmPacket);
5472 MM_FreeRxBuffer(pDevice, &pUmPacket->lm_packet);
5473 QQ_PushTail(&pDevice->RxPacketFreeQ.Container,
5474 pUmPacket);
5475 }
5476 }
5477 }
5478
5479 void
5480 bcm5700_validate_param_range(UM_DEVICE_BLOCK *pUmDevice, int *param,
5481 char *param_name, int min, int max, int deflt)
5482 {
5483 if (((unsigned int) *param < (unsigned int) min) ||
5484 ((unsigned int) *param > (unsigned int) max)) {
5485
5486 printk(KERN_WARNING "%s-%d: Invalid %s parameter (%u), using %u\n", bcm5700_driver, pUmDevice->index, param_name, (unsigned int) *param, (unsigned int) deflt);
5487 *param = deflt;
5488 }
5489 }
5490
5491 struct net_device *
5492 bcm5700_find_peer(struct net_device *dev)
5493 {
5494 struct net_device *tmp_dev;
5495 UM_DEVICE_BLOCK *pUmDevice, *pUmTmp;
5496 LM_DEVICE_BLOCK *pDevice;
5497
5498 tmp_dev = 0;
5499 pUmDevice = (UM_DEVICE_BLOCK *) dev->priv;
5500 pDevice = &pUmDevice->lm_dev;
5501 if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) {
5502 tmp_dev = root_tigon3_dev;
5503 while (tmp_dev) {
5504 pUmTmp = (PUM_DEVICE_BLOCK) tmp_dev->priv;
5505 if ((tmp_dev != dev) &&
5506 (pUmDevice->pdev->bus->number ==
5507 pUmTmp->pdev->bus->number) &&
5508 PCI_SLOT(pUmDevice->pdev->devfn) ==
5509 PCI_SLOT(pUmTmp->pdev->devfn)) {
5510
5511 break;
5512 }
5513 tmp_dev = pUmTmp->next_module;
5514 }
5515 }
5516 return tmp_dev;
5517 }
5518
5519 LM_DEVICE_BLOCK *
5520 MM_FindPeerDev(LM_DEVICE_BLOCK *pDevice)
5521 {
5522 UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
5523 struct net_device *dev = pUmDevice->dev;
5524 struct net_device *peer_dev;
5525
5526 peer_dev = bcm5700_find_peer(dev);
5527 if (!peer_dev)
5528 return 0;
5529 return ((LM_DEVICE_BLOCK *) peer_dev->priv);
5530 }
5531
5532 int MM_FindCapability(LM_DEVICE_BLOCK *pDevice, int capability)
5533 {
5534 UM_DEVICE_BLOCK *pUmDevice = (UM_DEVICE_BLOCK *) pDevice;
5535 return (pci_find_capability(pUmDevice->pdev, capability));
5536 }
5537
5538 #if defined(HAVE_POLL_CONTROLLER)||defined(CONFIG_NET_POLL_CONTROLLER)
5539 STATIC void
5540 poll_bcm5700(struct net_device *dev)
5541 {
5542 UM_DEVICE_BLOCK *pUmDevice = dev->priv;
5543
5544 #if defined(RED_HAT_LINUX_KERNEL) && (LINUX_VERSION_CODE < 0x020605)
5545 if (netdump_mode) {
5546 bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL);
5547 #ifdef BCM_NAPI_RXPOLL
5548 if (dev->poll_list.prev) {
5549 int budget = 64;
5550
5551 bcm5700_poll(dev, &budget);
5552 }
5553 #endif
5554 }
5555 else
5556 #endif
5557 {
5558 disable_irq(pUmDevice->pdev->irq);
5559 bcm5700_interrupt(pUmDevice->pdev->irq, dev, NULL);
5560 enable_irq(pUmDevice->pdev->irq);
5561 }
5562 }
5563 #endif
This page took 0.314212 seconds and 5 git commands to generate.