1 /******************************************************************************/
3 /* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 - 2004 Broadcom */
5 /* All rights reserved. */
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. */
11 /* /proc file system handling code. */
13 /******************************************************************************/
18 #define NICINFO_PROC_DIR "nicinfo"
20 static struct proc_dir_entry
*bcm5700_procfs_dir
;
22 extern char bcm5700_driver
[], bcm5700_version
[];
23 extern int bcm5700_open(struct net_device
*dev
);
25 extern uint64_t bcm5700_crc_count(PUM_DEVICE_BLOCK pUmDevice
);
26 extern uint64_t bcm5700_rx_err_count(PUM_DEVICE_BLOCK pUmDevice
);
28 static char *na_str
= "n/a";
29 static char *pause_str
= "pause ";
30 static char *asym_pause_str
= "asym_pause ";
31 static char *on_str
= "on";
32 static char *off_str
= "off";
33 static char *up_str
= "up";
34 static char *down_str
= "down";
36 int bcm5700_proc_create_dev(struct net_device
*dev
);
37 int bcm5700_proc_remove_dev(struct net_device
*dev
);
39 static int bcm5700_netdev_event(struct notifier_block
* this, unsigned long event
, void * ptr
)
41 struct net_device
* event_dev
= (struct net_device
*)ptr
;
43 if (event
== NETDEV_CHANGENAME
) {
44 if (event_dev
->open
== bcm5700_open
) {
45 bcm5700_proc_remove_dev(event_dev
);
46 bcm5700_proc_create_dev(event_dev
);
53 static struct notifier_block bcm5700_netdev_notifier
= {
54 .notifier_call
= bcm5700_netdev_event
57 static struct proc_dir_entry
*
58 proc_getdir(char *name
, struct proc_dir_entry
*proc_dir
)
60 struct proc_dir_entry
*pde
= proc_dir
;
63 for (pde
=pde
->subdir
; pde
; pde
= pde
->next
) {
64 if (pde
->namelen
&& (strcmp(name
, pde
->name
) == 0)) {
65 /* directory exists */
69 if (pde
== (struct proc_dir_entry
*) 0)
71 /* create the directory */
72 #if (LINUX_VERSION_CODE > 0x20300)
73 pde
= proc_mkdir(name
, proc_dir
);
75 pde
= create_proc_entry(name
, S_IFDIR
, proc_dir
);
77 if (pde
== (struct proc_dir_entry
*) 0) {
87 bcm5700_proc_create(void)
89 bcm5700_procfs_dir
= proc_getdir(NICINFO_PROC_DIR
, proc_net
);
91 if (bcm5700_procfs_dir
== (struct proc_dir_entry
*) 0) {
92 printk(KERN_DEBUG
"Could not create procfs nicinfo directory %s\n", NICINFO_PROC_DIR
);
95 register_netdevice_notifier(&bcm5700_netdev_notifier
);
100 bcm5700_proc_remove_notifier(void)
102 unregister_netdevice_notifier(&bcm5700_netdev_notifier
);
107 b57_get_speed_adv(PUM_DEVICE_BLOCK pUmDevice
, char *str
)
109 PLM_DEVICE_BLOCK pDevice
= &pUmDevice
->lm_dev
;
111 if (pDevice
->DisableAutoNeg
== TRUE
) {
115 if (pDevice
->TbiFlags
& ENABLE_TBI_FLAG
) {
116 strcpy(str
, "1000full");
119 if (pDevice
->PhyFlags
& PHY_IS_FIBER
) {
120 if (pDevice
->RequestedDuplexMode
!= LM_DUPLEX_MODE_HALF
)
121 strcpy(str
, "1000full");
123 strcpy(str
, "1000half");
127 if (pDevice
->advertising
& PHY_AN_AD_10BASET_HALF
) {
128 strcat(str
, "10half ");
130 if (pDevice
->advertising
& PHY_AN_AD_10BASET_FULL
) {
131 strcat(str
, "10full ");
133 if (pDevice
->advertising
& PHY_AN_AD_100BASETX_HALF
) {
134 strcat(str
, "100half ");
136 if (pDevice
->advertising
& PHY_AN_AD_100BASETX_FULL
) {
137 strcat(str
, "100full ");
139 if (pDevice
->advertising1000
& BCM540X_AN_AD_1000BASET_HALF
) {
140 strcat(str
, "1000half ");
142 if (pDevice
->advertising1000
& BCM540X_AN_AD_1000BASET_FULL
) {
143 strcat(str
, "1000full ");
148 b57_get_fc_adv(PUM_DEVICE_BLOCK pUmDevice
, char *str
)
150 PLM_DEVICE_BLOCK pDevice
= &pUmDevice
->lm_dev
;
152 if (pDevice
->DisableAutoNeg
== TRUE
) {
157 if (pDevice
->TbiFlags
& ENABLE_TBI_FLAG
) {
158 if(pDevice
->DisableAutoNeg
== FALSE
||
159 pDevice
->RequestedLineSpeed
== LM_LINE_SPEED_AUTO
) {
160 if (pDevice
->FlowControlCap
&
161 LM_FLOW_CONTROL_RECEIVE_PAUSE
) {
163 strcpy(str
, pause_str
);
164 if (!(pDevice
->FlowControlCap
&
165 LM_FLOW_CONTROL_TRANSMIT_PAUSE
)) {
167 strcpy(str
, asym_pause_str
);
170 else if (pDevice
->FlowControlCap
&
171 LM_FLOW_CONTROL_TRANSMIT_PAUSE
) {
173 strcpy(str
, asym_pause_str
);
178 if (pDevice
->advertising
& PHY_AN_AD_PAUSE_CAPABLE
) {
179 strcat(str
, pause_str
);
181 if (pDevice
->advertising
& PHY_AN_AD_ASYM_PAUSE
) {
182 strcat(str
, asym_pause_str
);
187 bcm5700_read_pfs(char *page
, char **start
, off_t off
, int count
,
188 int *eof
, void *data
)
190 struct net_device
*dev
= (struct net_device
*) data
;
191 PUM_DEVICE_BLOCK pUmDevice
= (PUM_DEVICE_BLOCK
) dev
->priv
;
192 PLM_DEVICE_BLOCK pDevice
= &pUmDevice
->lm_dev
;
193 PT3_STATS_BLOCK pStats
= (PT3_STATS_BLOCK
) pDevice
->pStatsBlkVirt
;
195 unsigned long rx_mac_errors
, rx_crc_errors
, rx_align_errors
;
196 unsigned long rx_runt_errors
, rx_frag_errors
, rx_long_errors
;
197 unsigned long rx_overrun_errors
, rx_jabber_errors
;
200 if (pUmDevice
->opened
== 0)
203 len
+= sprintf(page
+len
, "Description\t\t\t%s\n", pUmDevice
->name
);
204 len
+= sprintf(page
+len
, "Driver_Name\t\t\t%s\n", bcm5700_driver
);
205 len
+= sprintf(page
+len
, "Driver_Version\t\t\t%s\n", bcm5700_version
);
206 len
+= sprintf(page
+len
, "Bootcode_Version\t\t%s\n", pDevice
->BootCodeVer
);
207 if( pDevice
->IPMICodeVer
[0] != 0 )
208 len
+= sprintf(page
+len
, "ASF_IPMI_Version\t\t%s\n", pDevice
->IPMICodeVer
);
209 len
+= sprintf(page
+len
, "PCI_Vendor\t\t\t0x%04x\n", pDevice
->PciVendorId
);
210 len
+= sprintf(page
+len
, "PCI_Device_ID\t\t\t0x%04x\n",
211 pDevice
->PciDeviceId
);
212 len
+= sprintf(page
+len
, "PCI_Subsystem_Vendor\t\t0x%04x\n",
213 pDevice
->SubsystemVendorId
);
214 len
+= sprintf(page
+len
, "PCI_Subsystem_ID\t\t0x%04x\n",
215 pDevice
->SubsystemId
);
216 len
+= sprintf(page
+len
, "PCI_Revision_ID\t\t\t0x%02x\n",
218 len
+= sprintf(page
+len
, "PCI_Slot\t\t\t%d\n",
219 PCI_SLOT(pUmDevice
->pdev
->devfn
));
220 if (T3_ASIC_REV(pDevice
->ChipRevId
) == T3_ASIC_REV_5704
)
222 len
+= sprintf(page
+len
, "PCI_Function\t\t\t%d\n",
225 len
+= sprintf(page
+len
, "PCI_Bus\t\t\t\t%d\n",
226 pUmDevice
->pdev
->bus
->number
);
228 len
+= sprintf(page
+len
, "PCI_Bus_Speed\t\t\t%s\n",
229 pDevice
->BusSpeedStr
);
231 len
+= sprintf(page
+len
, "Memory\t\t\t\t0x%lx\n", pUmDevice
->dev
->base_addr
);
232 len
+= sprintf(page
+len
, "IRQ\t\t\t\t%d\n", dev
->irq
);
233 len
+= sprintf(page
+len
, "System_Device_Name\t\t%s\n", dev
->name
);
234 len
+= sprintf(page
+len
, "Current_HWaddr\t\t\t%02x:%02x:%02x:%02x:%02x:%02x\n",
235 dev
->dev_addr
[0], dev
->dev_addr
[1], dev
->dev_addr
[2],
236 dev
->dev_addr
[3], dev
->dev_addr
[4], dev
->dev_addr
[5]);
237 len
+= sprintf(page
+len
,
238 "Permanent_HWaddr\t\t%02x:%02x:%02x:%02x:%02x:%02x\n",
239 pDevice
->NodeAddress
[0], pDevice
->NodeAddress
[1],
240 pDevice
->NodeAddress
[2], pDevice
->NodeAddress
[3],
241 pDevice
->NodeAddress
[4], pDevice
->NodeAddress
[5]);
242 len
+= sprintf(page
+len
, "Part_Number\t\t\t%s\n\n", pDevice
->PartNo
);
244 len
+= sprintf(page
+len
, "Link\t\t\t\t%s\n",
245 (pUmDevice
->opened
== 0) ? "unknown" :
246 ((pDevice
->LinkStatus
== LM_STATUS_LINK_ACTIVE
) ? up_str
:
248 len
+= sprintf(page
+len
, "Auto_Negotiate\t\t\t%s\n",
249 (pDevice
->DisableAutoNeg
== TRUE
) ? off_str
: on_str
);
250 b57_get_speed_adv(pUmDevice
, str
);
251 len
+= sprintf(page
+len
, "Speed_Advertisement\t\t%s\n", str
);
252 b57_get_fc_adv(pUmDevice
, str
);
253 len
+= sprintf(page
+len
, "Flow_Control_Advertisement\t%s\n", str
);
254 len
+= sprintf(page
+len
, "Speed\t\t\t\t%s\n",
255 ((pDevice
->LinkStatus
== LM_STATUS_LINK_DOWN
) ||
256 (pUmDevice
->opened
== 0)) ? na_str
:
257 ((pDevice
->LineSpeed
== LM_LINE_SPEED_1000MBPS
) ? "1000" :
258 ((pDevice
->LineSpeed
== LM_LINE_SPEED_100MBPS
) ? "100" :
259 (pDevice
->LineSpeed
== LM_LINE_SPEED_10MBPS
) ? "10" : na_str
)));
260 len
+= sprintf(page
+len
, "Duplex\t\t\t\t%s\n",
261 ((pDevice
->LinkStatus
== LM_STATUS_LINK_DOWN
) ||
262 (pUmDevice
->opened
== 0)) ? na_str
:
263 ((pDevice
->DuplexMode
== LM_DUPLEX_MODE_FULL
) ? "full" :
265 len
+= sprintf(page
+len
, "Flow_Control\t\t\t%s\n",
266 ((pDevice
->LinkStatus
== LM_STATUS_LINK_DOWN
) ||
267 (pUmDevice
->opened
== 0)) ? na_str
:
268 ((pDevice
->FlowControl
== LM_FLOW_CONTROL_NONE
) ? off_str
:
269 (((pDevice
->FlowControl
& LM_FLOW_CONTROL_RX_TX_PAUSE
) ==
270 LM_FLOW_CONTROL_RX_TX_PAUSE
) ? "receive/transmit" :
271 (pDevice
->FlowControl
& LM_FLOW_CONTROL_RECEIVE_PAUSE
) ?
272 "receive" : "transmit")));
273 len
+= sprintf(page
+len
, "State\t\t\t\t%s\n",
274 (pUmDevice
->suspended
? "suspended" :
275 ((dev
->flags
& IFF_UP
) ? up_str
: down_str
)));
276 len
+= sprintf(page
+len
, "MTU_Size\t\t\t%d\n\n", dev
->mtu
);
277 len
+= sprintf(page
+len
, "Rx_Packets\t\t\t%lu\n",
279 MM_GETSTATS(pStats
->ifHCInUcastPkts
) +
280 MM_GETSTATS(pStats
->ifHCInMulticastPkts
) +
281 MM_GETSTATS(pStats
->ifHCInBroadcastPkts
)));
282 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
283 if ((dev
->mtu
> 1500) && !T3_ASIC_IS_5705_BEYOND(pDevice
->ChipRevId
)) {
284 len
+= sprintf(page
+len
, "Rx_Jumbo_Packets\t\t%lu\n",
287 pStats
->etherStatsPkts1523Octetsto2047Octets
) +
289 pStats
->etherStatsPkts2048Octetsto4095Octets
) +
291 pStats
->etherStatsPkts4096Octetsto8191Octets
) +
293 pStats
->etherStatsPkts8192Octetsto9022Octets
)));
296 len
+= sprintf(page
+len
, "Tx_Packets\t\t\t%lu\n",
298 MM_GETSTATS(pStats
->ifHCOutUcastPkts
) +
299 MM_GETSTATS(pStats
->ifHCOutMulticastPkts
) +
300 MM_GETSTATS(pStats
->ifHCOutBroadcastPkts
)));
302 len
+= sprintf(page
+len
, "TSO_Large_Packets\t\t%lu\n",
303 pUmDevice
->tso_pkt_count
);
305 len
+= sprintf(page
+len
, "Rx_Bytes\t\t\t%lu\n",
307 MM_GETSTATS(pStats
->ifHCInOctets
)));
308 len
+= sprintf(page
+len
, "Tx_Bytes\t\t\t%lu\n",
310 MM_GETSTATS(pStats
->ifHCOutOctets
)));
317 rx_overrun_errors
= 0;
318 rx_jabber_errors
= 0;
321 rx_crc_errors
= (unsigned long) bcm5700_crc_count(pUmDevice
);
322 rx_align_errors
= MM_GETSTATS(pStats
->dot3StatsAlignmentErrors
);
323 rx_runt_errors
= MM_GETSTATS(pStats
->etherStatsUndersizePkts
);
324 rx_frag_errors
= MM_GETSTATS(pStats
->etherStatsFragments
);
325 rx_long_errors
= MM_GETSTATS(pStats
->dot3StatsFramesTooLong
);
326 rx_overrun_errors
= MM_GETSTATS(pStats
->nicNoMoreRxBDs
);
327 rx_jabber_errors
= MM_GETSTATS(pStats
->etherStatsJabbers
);
329 rx_mac_errors
= (unsigned long) bcm5700_rx_err_count(pUmDevice
);
330 len
+= sprintf(page
+len
, "Rx_Errors\t\t\t%lu\n",
332 rx_mac_errors
+ rx_overrun_errors
+ pUmDevice
->rx_misc_errors
));
333 len
+= sprintf(page
+len
, "Tx_Errors\t\t\t%lu\n",
335 MM_GETSTATS(pStats
->ifOutErrors
)));
336 len
+= sprintf(page
+len
, "\nTx_Carrier_Errors\t\t%lu\n",
338 MM_GETSTATS(pStats
->dot3StatsCarrierSenseErrors
)));
339 len
+= sprintf(page
+len
, "Tx_Abort_Excess_Coll\t\t%lu\n",
341 MM_GETSTATS(pStats
->dot3StatsExcessiveCollisions
)));
342 len
+= sprintf(page
+len
, "Tx_Abort_Late_Coll\t\t%lu\n",
344 MM_GETSTATS(pStats
->dot3StatsLateCollisions
)));
345 len
+= sprintf(page
+len
, "Tx_Deferred_Ok\t\t\t%lu\n",
347 MM_GETSTATS(pStats
->dot3StatsDeferredTransmissions
)));
348 len
+= sprintf(page
+len
, "Tx_Single_Coll_Ok\t\t%lu\n",
350 MM_GETSTATS(pStats
->dot3StatsSingleCollisionFrames
)));
351 len
+= sprintf(page
+len
, "Tx_Multi_Coll_Ok\t\t%lu\n",
353 MM_GETSTATS(pStats
->dot3StatsMultipleCollisionFrames
)));
354 len
+= sprintf(page
+len
, "Tx_Total_Coll_Ok\t\t%lu\n",
356 MM_GETSTATS(pStats
->etherStatsCollisions
)));
357 len
+= sprintf(page
+len
, "Tx_XON_Pause_Frames\t\t%lu\n",
359 MM_GETSTATS(pStats
->outXonSent
)));
360 len
+= sprintf(page
+len
, "Tx_XOFF_Pause_Frames\t\t%lu\n",
362 MM_GETSTATS(pStats
->outXoffSent
)));
363 len
+= sprintf(page
+len
, "\nRx_CRC_Errors\t\t\t%lu\n", rx_crc_errors
);
364 len
+= sprintf(page
+len
, "Rx_Short_Fragment_Errors\t%lu\n",
366 len
+= sprintf(page
+len
, "Rx_Short_Length_Errors\t\t%lu\n",
368 len
+= sprintf(page
+len
, "Rx_Long_Length_Errors\t\t%lu\n",
370 len
+= sprintf(page
+len
, "Rx_Align_Errors\t\t\t%lu\n",
372 len
+= sprintf(page
+len
, "Rx_Overrun_Errors\t\t%lu\n",
374 len
+= sprintf(page
+len
, "Rx_XON_Pause_Frames\t\t%lu\n",
376 MM_GETSTATS(pStats
->xonPauseFramesReceived
)));
377 len
+= sprintf(page
+len
, "Rx_XOFF_Pause_Frames\t\t%lu\n",
379 MM_GETSTATS(pStats
->xoffPauseFramesReceived
)));
380 len
+= sprintf(page
+len
, "\nTx_MAC_Errors\t\t\t%lu\n",
382 MM_GETSTATS(pStats
->dot3StatsInternalMacTransmitErrors
)));
383 len
+= sprintf(page
+len
, "Rx_MAC_Errors\t\t\t%lu\n\n",
386 len
+= sprintf(page
+len
, "Tx_Checksum\t\t\t%s\n",
387 ((pDevice
->TaskToOffload
& LM_TASK_OFFLOAD_TX_TCP_CHECKSUM
) ?
389 len
+= sprintf(page
+len
, "Rx_Checksum\t\t\t%s\n",
390 ((pDevice
->TaskToOffload
& LM_TASK_OFFLOAD_RX_TCP_CHECKSUM
) ?
392 len
+= sprintf(page
+len
, "Scatter_Gather\t\t\t%s\n",
393 #if (LINUX_VERSION_CODE >= 0x20400)
394 ((dev
->features
& NETIF_F_SG
) ? on_str
: off_str
));
399 len
+= sprintf(page
+len
, "TSO\t\t\t\t%s\n",
400 ((dev
->features
& NETIF_F_TSO
) ? on_str
: off_str
));
402 len
+= sprintf(page
+len
, "VLAN\t\t\t\t%s\n\n",
403 ((pDevice
->RxMode
& RX_MODE_KEEP_VLAN_TAG
) ? off_str
: on_str
));
405 #ifdef BCM_NIC_SEND_BD
406 len
+= sprintf(page
+len
, "NIC_Tx_BDs\t\t\t%s\n",
407 (pDevice
->Flags
& NIC_SEND_BD_FLAG
) ? on_str
: off_str
);
409 len
+= sprintf(page
+len
, "Tx_Desc_Count\t\t\t%u\n",
410 pDevice
->TxPacketDescCnt
);
411 len
+= sprintf(page
+len
, "Rx_Desc_Count\t\t\t%u\n",
412 pDevice
->RxStdDescCnt
);
413 #if T3_JUMBO_RCV_RCB_ENTRY_COUNT
414 len
+= sprintf(page
+len
, "Rx_Jumbo_Desc_Count\t\t%u\n",
415 pDevice
->RxJumboDescCnt
);
418 len
+= sprintf(page
+len
, "Adaptive_Coalescing\t\t%s\n",
419 (pUmDevice
->adaptive_coalesce
? on_str
: off_str
));
420 len
+= sprintf(page
+len
, "Rx_Coalescing_Ticks\t\t%u\n",
421 pUmDevice
->rx_curr_coalesce_ticks
);
422 len
+= sprintf(page
+len
, "Rx_Coalesced_Frames\t\t%u\n",
423 pUmDevice
->rx_curr_coalesce_frames
);
424 len
+= sprintf(page
+len
, "Tx_Coalescing_Ticks\t\t%u\n",
425 pDevice
->TxCoalescingTicks
);
426 len
+= sprintf(page
+len
, "Tx_Coalesced_Frames\t\t%u\n",
427 pUmDevice
->tx_curr_coalesce_frames
);
428 len
+= sprintf(page
+len
, "Stats_Coalescing_Ticks\t\t%u\n",
429 pDevice
->StatsCoalescingTicks
);
432 len
+= sprintf(page
+len
, "Wake_On_LAN\t\t\t%s\n",
433 ((pDevice
->WakeUpMode
& LM_WAKE_UP_MODE_MAGIC_PACKET
) ?
437 len
+= sprintf(page
+len
, "\nDmaReadWriteCtrl\t\t%x\n",
438 pDevice
->DmaReadWriteCtrl
);
439 len
+= sprintf(page
+len
, "\nTx_Zero_Copy_Packets\t\t%lu\n",
440 pUmDevice
->tx_zc_count
);
441 len
+= sprintf(page
+len
, "Tx_Chksum_Packets\t\t%lu\n",
442 pUmDevice
->tx_chksum_count
);
443 len
+= sprintf(page
+len
, "Tx_Highmem_Fragments\t\t%lu\n",
444 pUmDevice
->tx_himem_count
);
445 len
+= sprintf(page
+len
, "Rx_Good_Chksum_Packets\t\t%lu\n",
446 pUmDevice
->rx_good_chksum_count
);
447 len
+= sprintf(page
+len
, "Rx_Bad_Chksum_Packets\t\t%lu\n",
448 pUmDevice
->rx_bad_chksum_count
);
457 bcm5700_proc_create_dev(struct net_device
*dev
)
459 PUM_DEVICE_BLOCK pUmDevice
= (PUM_DEVICE_BLOCK
) dev
->priv
;
461 if (!bcm5700_procfs_dir
)
464 sprintf(pUmDevice
->pfs_name
, "%s.info", dev
->name
);
465 pUmDevice
->pfs_entry
= create_proc_entry(pUmDevice
->pfs_name
,
466 S_IFREG
, bcm5700_procfs_dir
);
467 if (pUmDevice
->pfs_entry
== 0)
469 pUmDevice
->pfs_entry
->read_proc
= bcm5700_read_pfs
;
470 pUmDevice
->pfs_entry
->data
= dev
;
474 bcm5700_proc_remove_dev(struct net_device
*dev
)
476 PUM_DEVICE_BLOCK pUmDevice
= (PUM_DEVICE_BLOCK
) dev
->priv
;
478 remove_proc_entry(pUmDevice
->pfs_name
, bcm5700_procfs_dir
);