1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include "e1000.h"
47
48#ifdef CONFIG_PROC_FS
49
50#include <linux/proc_fs.h>
51
52#define ADAPTERS_PROC_DIR "PRO_LAN_Adapters"
53#define TAG_MAX_LENGTH 32
54#define LINE_MAX_LENGTH 80
55#define FIELD_MAX_LENGTH LINE_MAX_LENGTH - TAG_MAX_LENGTH - 3
56
57extern char e1000_driver_name[];
58extern char e1000_driver_version[];
59
60
61
62
63
64
65
66
67struct proc_list {
68 struct list_head list;
69 char tag[TAG_MAX_LENGTH + 1];
70 void *data;
71 size_t len;
72 char *(*func)(void *, size_t, char *);
73};
74
75static int
76e1000_proc_read(char *page, char **start, off_t off, int count, int *eof)
77{
78 int len = strlen(page);
79
80 page[len++] = '\n';
81
82 if(len <= off + count)
83 *eof = 1;
84 *start = page + off;
85 len -= off;
86 if(len > count)
87 len = count;
88 if(len < 0)
89 len = 0;
90
91 return len;
92}
93
94static int
95e1000_proc_info_read(char *page, char **start, off_t off,
96 int count, int *eof, void *data)
97{
98 struct list_head *proc_list_head = data, *curr;
99 struct proc_list *elem;
100 char *p = page;
101 char buf[FIELD_MAX_LENGTH + 1];
102
103 list_for_each(curr, proc_list_head) {
104 elem = list_entry(curr, struct proc_list, list);
105
106 if (p - page + LINE_MAX_LENGTH >= PAGE_SIZE)
107 break;
108
109 if(!strlen(elem->tag))
110 p += sprintf(p, "\n");
111 else
112 p += sprintf(p, "%-*.*s %.*s\n",
113 TAG_MAX_LENGTH, TAG_MAX_LENGTH,
114 elem->tag, FIELD_MAX_LENGTH,
115 elem->func(elem->data, elem->len, buf));
116 }
117
118 *p = '\0';
119
120 return e1000_proc_read(page, start, off, count, eof);
121}
122
123static int
124e1000_proc_single_read(char *page, char **start, off_t off,
125 int count, int *eof, void *data)
126{
127 struct proc_list *elem = data;
128
129 sprintf(page, "%.*s", FIELD_MAX_LENGTH, elem->func(elem->data,
130 elem->len, page));
131
132 return e1000_proc_read(page, start, off, count, eof);
133}
134
135static void __devexit
136e1000_proc_dirs_free(char *name, struct list_head *proc_list_head)
137{
138 struct proc_dir_entry *intel_proc_dir, *proc_dir;
139 char info_name[strlen(name) + strlen(".info")];
140
141 for(intel_proc_dir = proc_net->subdir; intel_proc_dir;
142 intel_proc_dir = intel_proc_dir->next) {
143 if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&
144 !memcmp(intel_proc_dir->name, ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)))
145 break;
146 }
147
148 if(!intel_proc_dir)
149 return;
150
151 for(proc_dir = intel_proc_dir->subdir; proc_dir;
152 proc_dir = proc_dir->next) {
153 if ((proc_dir->namelen == strlen(name)) &&
154 !memcmp(proc_dir->name, name, strlen(name)))
155 break;
156 }
157
158 if(proc_dir) {
159 struct list_head *curr;
160 struct proc_list *elem;
161
162 list_for_each(curr, proc_list_head) {
163 elem = list_entry(curr, struct proc_list, list);
164 remove_proc_entry(elem->tag, proc_dir);
165 }
166
167 strcpy(info_name, name);
168 strcat(info_name, ".info");
169
170 remove_proc_entry(info_name, intel_proc_dir);
171 remove_proc_entry(name, intel_proc_dir);
172 }
173
174
175
176 for(proc_dir = intel_proc_dir->subdir; proc_dir;
177 proc_dir = proc_dir->next) {
178
179
180
181 if(*(proc_dir->name) == '.')
182 continue;
183 break;
184 }
185
186 if(!proc_dir)
187 remove_proc_entry(ADAPTERS_PROC_DIR, proc_net);
188}
189
190
191static int __devinit
192e1000_proc_singles_create(struct proc_dir_entry *parent,
193 struct list_head *proc_list_head)
194{
195 struct list_head *curr;
196 struct proc_list *elem;
197
198 list_for_each(curr, proc_list_head) {
199 struct proc_dir_entry *proc_entry;
200
201 elem = list_entry(curr, struct proc_list, list);
202
203 if(!strlen(elem->tag))
204 continue;
205
206 if(!(proc_entry =
207 create_proc_entry(elem->tag, S_IFREG, parent)))
208 return 0;
209
210 proc_entry->read_proc = e1000_proc_single_read;
211 proc_entry->data = elem;
212 SET_MODULE_OWNER(proc_entry);
213 }
214
215 return 1;
216}
217
218static void __devinit
219e1000_proc_dirs_create(void *data, char *name,
220 struct list_head *proc_list_head)
221{
222 struct proc_dir_entry *intel_proc_dir, *proc_dir, *info_entry;
223 char info_name[strlen(name) + strlen(".info")];
224
225 for(intel_proc_dir = proc_net->subdir; intel_proc_dir;
226 intel_proc_dir = intel_proc_dir->next) {
227 if((intel_proc_dir->namelen == strlen(ADAPTERS_PROC_DIR)) &&
228 !memcmp(intel_proc_dir->name, ADAPTERS_PROC_DIR, strlen(ADAPTERS_PROC_DIR)))
229 break;
230 }
231
232 if(!intel_proc_dir)
233 if(!(intel_proc_dir =
234 create_proc_entry(ADAPTERS_PROC_DIR,
235 S_IFDIR, proc_net)))
236 return;
237
238 if(!(proc_dir =
239 create_proc_entry(name, S_IFDIR, intel_proc_dir)))
240 return;
241 SET_MODULE_OWNER(proc_dir);
242
243 if(!e1000_proc_singles_create(proc_dir, proc_list_head))
244 return;
245
246 strcpy(info_name, name);
247 strcat(info_name, ".info");
248
249 if(!(info_entry =
250 create_proc_entry(info_name, S_IFREG, intel_proc_dir)))
251 return;
252 SET_MODULE_OWNER(info_entry);
253
254 info_entry->read_proc = e1000_proc_info_read;
255 info_entry->data = proc_list_head;
256}
257
258static void __devinit
259e1000_proc_list_add(struct list_head *proc_list_head, char *tag,
260 void *data, size_t len,
261 char *(*func)(void *, size_t, char *))
262{
263 struct proc_list *new = (struct proc_list *)
264 kmalloc(sizeof(struct proc_list), GFP_KERNEL);
265
266 if(!new)
267 return;
268
269 strncpy(new->tag, tag, TAG_MAX_LENGTH);
270 new->data = data;
271 new->len = len;
272 new->func = func;
273
274 list_add_tail(&new->list, proc_list_head);
275}
276
277static void __devexit
278e1000_proc_list_free(struct list_head *proc_list_head)
279{
280 struct proc_list *elem;
281
282 while(!list_empty(proc_list_head)) {
283 elem = list_entry(proc_list_head->next, struct proc_list, list);
284 list_del(&elem->list);
285 kfree(elem);
286 }
287}
288
289
290
291
292
293static char *
294e1000_proc_str(void *data, size_t len, char *buf)
295{
296 sprintf(buf, "%s", (char *)data);
297 return buf;
298}
299
300static char *
301e1000_proc_hex(void *data, size_t len, char *buf)
302{
303 switch(len) {
304 case sizeof(uint8_t):
305 sprintf(buf, "0x%02x", *(uint8_t *)data);
306 break;
307 case sizeof(uint16_t):
308 sprintf(buf, "0x%04x", *(uint16_t *)data);
309 break;
310 case sizeof(uint32_t):
311 sprintf(buf, "0x%08x", *(uint32_t *)data);
312 break;
313 case sizeof(uint64_t):
314 sprintf(buf, "0x%08Lx", (unsigned long long)*(uint64_t *)data);
315 break;
316 }
317 return buf;
318}
319
320static char *
321e1000_proc_unsigned(void *data, size_t len, char *buf)
322{
323 switch(len) {
324 case sizeof(uint8_t):
325 sprintf(buf, "%u", *(uint8_t *)data);
326 break;
327 case sizeof(uint16_t):
328 sprintf(buf, "%u", *(uint16_t *)data);
329 break;
330 case sizeof(uint32_t):
331 sprintf(buf, "%u", *(uint32_t *)data);
332 break;
333 case sizeof(uint64_t):
334 sprintf(buf, "%Lu", (unsigned long long)*(uint64_t *)data);
335 break;
336 }
337 return buf;
338}
339
340
341
342
343
344static char *
345e1000_proc_part_number(void *data, size_t len, char *buf)
346{
347 sprintf(buf, "%06x-%03x", *(uint32_t *)data >> 8,
348 *(uint32_t *)data & 0x000000FF);
349 return buf;
350}
351
352static char *
353e1000_proc_slot(void *data, size_t len, char *buf)
354{
355 struct e1000_adapter *adapter = data;
356 sprintf(buf, "%u", PCI_SLOT(adapter->pdev->devfn));
357 return buf;
358}
359
360static char *
361e1000_proc_bus_type(void *data, size_t len, char *buf)
362{
363 e1000_bus_type bus_type = *(e1000_bus_type *)data;
364 sprintf(buf,
365 bus_type == e1000_bus_type_pci ? "PCI" :
366 bus_type == e1000_bus_type_pcix ? "PCI-X" :
367 "UNKNOWN");
368 return buf;
369}
370
371static char *
372e1000_proc_bus_speed(void *data, size_t len, char *buf)
373{
374 e1000_bus_speed bus_speed = *(e1000_bus_speed *)data;
375 sprintf(buf,
376 bus_speed == e1000_bus_speed_33 ? "33MHz" :
377 bus_speed == e1000_bus_speed_66 ? "66MHz" :
378 bus_speed == e1000_bus_speed_100 ? "100MHz" :
379 bus_speed == e1000_bus_speed_133 ? "133MHz" :
380 "UNKNOWN");
381 return buf;
382}
383
384static char *
385e1000_proc_bus_width(void *data, size_t len, char *buf)
386{
387 e1000_bus_width bus_width = *(e1000_bus_width *)data;
388 sprintf(buf,
389 bus_width == e1000_bus_width_32 ? "32-bit" :
390 bus_width == e1000_bus_width_64 ? "64-bit" :
391 "UNKNOWN");
392 return buf;
393}
394
395static char *
396e1000_proc_hwaddr(void *data, size_t len, char *buf)
397{
398 unsigned char *hwaddr = data;
399 sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
400 hwaddr[0], hwaddr[1], hwaddr[2],
401 hwaddr[3], hwaddr[4], hwaddr[5]);
402 return buf;
403}
404
405static char *
406e1000_proc_link(void *data, size_t len, char *buf)
407{
408 struct e1000_adapter *adapter = data;
409 sprintf(buf, netif_running(adapter->netdev) ?
410 netif_carrier_ok(adapter->netdev) ?
411 "up" : "down" : "N/A");
412 return buf;
413}
414
415static char *
416e1000_proc_link_speed(void *data, size_t len, char *buf)
417{
418 uint16_t link_speed = *(uint16_t *)data;
419 sprintf(buf, link_speed ? "%u" : "N/A", link_speed);
420 return buf;
421}
422
423static char *
424e1000_proc_link_duplex(void *data, size_t len, char *buf)
425{
426 uint16_t link_duplex = *(uint16_t *)data;
427 sprintf(buf,
428 link_duplex == FULL_DUPLEX ? "Full" :
429 link_duplex == HALF_DUPLEX ? "Half" :
430 "N/A");
431 return buf;
432}
433
434static char *
435e1000_proc_state(void *data, size_t len, char *buf)
436{
437 struct e1000_adapter *adapter = data;
438 sprintf(buf, adapter->netdev->flags & IFF_UP ? "up" : "down");
439 return buf;
440}
441
442static char *
443e1000_proc_media_type(void *data, size_t len, char *buf)
444{
445 struct e1000_adapter *adapter = data;
446 sprintf(buf,
447 adapter->hw.media_type == e1000_media_type_copper ?
448 "Copper" : "Fiber");
449 return buf;
450}
451
452static char *
453e1000_proc_cable_length(void *data, size_t len, char *buf)
454{
455 struct e1000_adapter *adapter = data;
456 e1000_cable_length cable_length = adapter->phy_info.cable_length;
457 sprintf(buf, "%s%s",
458 cable_length == e1000_cable_length_50 ? "0-50" :
459 cable_length == e1000_cable_length_50_80 ? "50-80" :
460 cable_length == e1000_cable_length_80_110 ? "80-110" :
461 cable_length == e1000_cable_length_110_140 ? "110-140" :
462 cable_length == e1000_cable_length_140 ? "> 140" :
463 "Unknown",
464 cable_length != e1000_cable_length_undefined ?
465 " Meters (+/- 20 Meters)" : "");
466 return buf;
467}
468
469static char *
470e1000_proc_extended(void *data, size_t len, char *buf)
471{
472 struct e1000_adapter *adapter = data;
473 e1000_10bt_ext_dist_enable dist_enable =
474 adapter->phy_info.extended_10bt_distance;
475 sprintf(buf,
476 dist_enable == e1000_10bt_ext_dist_enable_normal ? "Disabled" :
477 dist_enable == e1000_10bt_ext_dist_enable_lower ? "Enabled" :
478 "Unknown");
479 return buf;
480}
481
482static char *
483e1000_proc_cable_polarity(void *data, size_t len, char *buf)
484{
485 struct e1000_adapter *adapter = data;
486 e1000_rev_polarity polarity = adapter->phy_info.cable_polarity;
487 sprintf(buf,
488 polarity == e1000_rev_polarity_normal ? "Normal" :
489 polarity == e1000_rev_polarity_reversed ? "Reversed" :
490 "Unknown");
491 return buf;
492}
493
494static char *
495e1000_proc_polarity_correction(void *data, size_t len, char *buf)
496{
497 struct e1000_adapter *adapter = data;
498 e1000_polarity_reversal correction =
499 adapter->phy_info.polarity_correction;
500 sprintf(buf,
501 correction == e1000_polarity_reversal_enabled ? "Disabled" :
502 correction == e1000_polarity_reversal_disabled ? "Enabled" :
503 "Unknown");
504 return buf;
505}
506
507static char *
508e1000_proc_mdi_x_enabled(void *data, size_t len, char *buf)
509{
510 struct e1000_adapter *adapter = data;
511 e1000_auto_x_mode mdix_mode = adapter->phy_info.mdix_mode;
512 sprintf(buf,
513 mdix_mode == e1000_auto_x_mode_manual_mdi ? "MDI" :
514 mdix_mode == e1000_auto_x_mode_manual_mdix ? "MDI-X" :
515 "Unknown");
516 return buf;
517}
518
519static char *
520e1000_proc_rx_status(void *data, size_t len, char *buf)
521{
522 e1000_1000t_rx_status rx_status = *(e1000_1000t_rx_status *)data;
523 sprintf(buf,
524 rx_status == e1000_1000t_rx_status_not_ok ? "NOT_OK" :
525 rx_status == e1000_1000t_rx_status_ok ? "OK" :
526 "Unknown");
527 return buf;
528}
529
530
531
532
533
534
535
536
537
538#define LIST_ADD_F(T,D,F) \
539 e1000_proc_list_add(proc_list_head, (T), (D), sizeof(*(D)), (F))
540#define LIST_ADD_BLANK() LIST_ADD_F("", NULL, NULL)
541#define LIST_ADD_S(T,D) LIST_ADD_F((T), (D), e1000_proc_str)
542#define LIST_ADD_H(T,D) LIST_ADD_F((T), (D), e1000_proc_hex)
543#define LIST_ADD_U(T,D) LIST_ADD_F((T), (D), e1000_proc_unsigned)
544
545static void __devinit
546e1000_proc_list_setup(struct e1000_adapter *adapter)
547{
548 struct e1000_hw *hw = &adapter->hw;
549 struct list_head *proc_list_head = &adapter->proc_list_head;
550
551 INIT_LIST_HEAD(proc_list_head);
552
553 LIST_ADD_S("Description", adapter->id_string);
554 LIST_ADD_F("Part_Number", &adapter->part_num, e1000_proc_part_number);
555 LIST_ADD_S("Driver_Name", e1000_driver_name);
556 LIST_ADD_S("Driver_Version", e1000_driver_version);
557 LIST_ADD_H("PCI_Vendor", &hw->vendor_id);
558 LIST_ADD_H("PCI_Device_ID", &hw->device_id);
559 LIST_ADD_H("PCI_Subsystem_Vendor", &hw->subsystem_vendor_id);
560 LIST_ADD_H("PCI_Subsystem_ID", &hw->subsystem_id);
561 LIST_ADD_H("PCI_Revision_ID", &hw->revision_id);
562 LIST_ADD_U("PCI_Bus", &adapter->pdev->bus->number);
563 LIST_ADD_F("PCI_Slot", adapter, e1000_proc_slot);
564
565 if(adapter->hw.mac_type >= e1000_82543) {
566 LIST_ADD_F("PCI_Bus_Type",
567 &hw->bus_type, e1000_proc_bus_type);
568 LIST_ADD_F("PCI_Bus_Speed",
569 &hw->bus_speed, e1000_proc_bus_speed);
570 LIST_ADD_F("PCI_Bus_Width",
571 &hw->bus_width, e1000_proc_bus_width);
572 }
573
574 LIST_ADD_U("IRQ", &adapter->pdev->irq);
575 LIST_ADD_S("System_Device_Name", adapter->netdev->name);
576 LIST_ADD_F("Current_HWaddr",
577 adapter->netdev->dev_addr, e1000_proc_hwaddr);
578 LIST_ADD_F("Permanent_HWaddr",
579 adapter->hw.perm_mac_addr, e1000_proc_hwaddr);
580
581 LIST_ADD_BLANK();
582
583 LIST_ADD_F("Link", adapter, e1000_proc_link);
584 LIST_ADD_F("Speed", &adapter->link_speed, e1000_proc_link_speed);
585 LIST_ADD_F("Duplex", &adapter->link_duplex, e1000_proc_link_duplex);
586 LIST_ADD_F("State", adapter, e1000_proc_state);
587
588 LIST_ADD_BLANK();
589
590
591 LIST_ADD_U("Rx_Packets", &adapter->net_stats.rx_packets);
592 LIST_ADD_U("Tx_Packets", &adapter->net_stats.tx_packets);
593 LIST_ADD_U("Rx_Bytes", &adapter->net_stats.rx_bytes);
594 LIST_ADD_U("Tx_Bytes", &adapter->net_stats.tx_bytes);
595 LIST_ADD_U("Rx_Errors", &adapter->net_stats.rx_errors);
596 LIST_ADD_U("Tx_Errors", &adapter->net_stats.tx_errors);
597 LIST_ADD_U("Rx_Dropped", &adapter->net_stats.rx_dropped);
598 LIST_ADD_U("Tx_Dropped", &adapter->net_stats.tx_dropped);
599
600 LIST_ADD_U("Multicast", &adapter->net_stats.multicast);
601 LIST_ADD_U("Collisions", &adapter->net_stats.collisions);
602
603 LIST_ADD_U("Rx_Length_Errors", &adapter->net_stats.rx_length_errors);
604 LIST_ADD_U("Rx_Over_Errors", &adapter->net_stats.rx_over_errors);
605 LIST_ADD_U("Rx_CRC_Errors", &adapter->net_stats.rx_crc_errors);
606 LIST_ADD_U("Rx_Frame_Errors", &adapter->net_stats.rx_frame_errors);
607 LIST_ADD_U("Rx_FIFO_Errors", &adapter->net_stats.rx_fifo_errors);
608 LIST_ADD_U("Rx_Missed_Errors", &adapter->net_stats.rx_missed_errors);
609
610 LIST_ADD_U("Tx_Aborted_Errors", &adapter->net_stats.tx_aborted_errors);
611 LIST_ADD_U("Tx_Carrier_Errors", &adapter->net_stats.tx_carrier_errors);
612 LIST_ADD_U("Tx_FIFO_Errors", &adapter->net_stats.tx_fifo_errors);
613 LIST_ADD_U("Tx_Heartbeat_Errors",
614 &adapter->net_stats.tx_heartbeat_errors);
615 LIST_ADD_U("Tx_Window_Errors", &adapter->net_stats.tx_window_errors);
616
617
618 LIST_ADD_U("Tx_Abort_Late_Coll", &adapter->stats.latecol);
619 LIST_ADD_U("Tx_Deferred_Ok", &adapter->stats.dc);
620 LIST_ADD_U("Tx_Single_Coll_Ok", &adapter->stats.scc);
621 LIST_ADD_U("Tx_Multi_Coll_Ok", &adapter->stats.mcc);
622 LIST_ADD_U("Rx_Long_Length_Errors", &adapter->stats.roc);
623 LIST_ADD_U("Rx_Short_Length_Errors", &adapter->stats.ruc);
624
625
626 if(adapter->hw.mac_type >= e1000_82543) {
627 LIST_ADD_U("Rx_Align_Errors", &adapter->stats.algnerrc);
628 LIST_ADD_U("Tx_TCP_Seg_Good", &adapter->stats.tsctc);
629 LIST_ADD_U("Tx_TCP_Seg_Failed", &adapter->stats.tsctfc);
630 }
631
632 LIST_ADD_U("Rx_Flow_Control_XON", &adapter->stats.xonrxc);
633 LIST_ADD_U("Rx_Flow_Control_XOFF", &adapter->stats.xoffrxc);
634 LIST_ADD_U("Tx_Flow_Control_XON", &adapter->stats.xontxc);
635 LIST_ADD_U("Tx_Flow_Control_XOFF", &adapter->stats.xofftxc);
636 LIST_ADD_U("Rx_CSum_Offload_Good", &adapter->hw_csum_good);
637 LIST_ADD_U("Rx_CSum_Offload_Errors", &adapter->hw_csum_err);
638
639 LIST_ADD_BLANK();
640
641
642 LIST_ADD_F("PHY_Media_Type", adapter, e1000_proc_media_type);
643 if(adapter->hw.media_type == e1000_media_type_copper) {
644 LIST_ADD_F("PHY_Cable_Length",
645 adapter, e1000_proc_cable_length);
646 LIST_ADD_F("PHY_Extended_10Base_T_Distance",
647 adapter, e1000_proc_extended);
648 LIST_ADD_F("PHY_Cable_Polarity",
649 adapter, e1000_proc_cable_polarity);
650 LIST_ADD_F("PHY_Disable_Polarity_Correction",
651 adapter, e1000_proc_polarity_correction);
652 LIST_ADD_U("PHY_Idle_Errors",
653 &adapter->phy_stats.idle_errors);
654 LIST_ADD_U("PHY_Receive_Errors",
655 &adapter->phy_stats.receive_errors);
656 LIST_ADD_F("PHY_MDI_X_Enabled",
657 adapter, e1000_proc_mdi_x_enabled);
658 LIST_ADD_F("PHY_Local_Receiver_Status",
659 &adapter->phy_info.local_rx,
660 e1000_proc_rx_status);
661 LIST_ADD_F("PHY_Remote_Receiver_Status",
662 &adapter->phy_info.remote_rx,
663 e1000_proc_rx_status);
664 }
665
666}
667
668
669
670
671
672
673void __devinit
674e1000_proc_dev_setup(struct e1000_adapter *adapter)
675{
676 e1000_proc_list_setup(adapter);
677
678 e1000_proc_dirs_create(adapter,
679 adapter->netdev->name,
680 &adapter->proc_list_head);
681}
682
683
684
685
686
687
688void __devexit
689e1000_proc_dev_free(struct e1000_adapter *adapter)
690{
691 e1000_proc_dirs_free(adapter->netdev->name, &adapter->proc_list_head);
692
693 e1000_proc_list_free(&adapter->proc_list_head);
694}
695
696#else
697
698void __devinit e1000_proc_dev_setup(struct e1000_adapter *adapter) {}
699void __devexit e1000_proc_dev_free(struct e1000_adapter *adapter) {}
700
701#endif
702
703