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