make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / net / e1000 / e1000_ethtool.c
1 /*******************************************************************************
2
3   
4   Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
5   
6   This program is free software; you can redistribute it and/or modify it 
7   under the terms of the GNU General Public License as published by the Free 
8   Software Foundation; either version 2 of the License, or (at your option) 
9   any later version.
10   
11   This program is distributed in the hope that it will be useful, but WITHOUT 
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
14   more details.
15   
16   You should have received a copy of the GNU General Public License along with
17   this program; if not, write to the Free Software Foundation, Inc., 59 
18   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19   
20   The full GNU General Public License is included in this distribution in the
21   file called LICENSE.
22   
23   Contact Information:
24   Linux NICS <linux.nics@intel.com>
25   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26
27 *******************************************************************************/
28
29 /* ethtool support for e1000 */
30
31 #include "e1000.h"
32
33 #include <asm/uaccess.h>
34
35 extern char e1000_driver_name[];
36 extern char e1000_driver_version[];
37
38 extern int e1000_up(struct e1000_adapter *adapter);
39 extern void e1000_down(struct e1000_adapter *adapter);
40 extern void e1000_reset(struct e1000_adapter *adapter);
41
42 static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = {
43         "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
44         "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
45         "rx_length_errors", "rx_over_errors", "rx_crc_errors",
46         "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
47         "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
48         "tx_heartbeat_errors", "tx_window_errors",
49 };
50 #define E1000_STATS_LEN sizeof(e1000_gstrings_stats) / ETH_GSTRING_LEN
51
52 static void
53 e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
54 {
55         struct e1000_hw *hw = &adapter->hw;
56
57         if(hw->media_type == e1000_media_type_copper) {
58
59                 ecmd->supported = (SUPPORTED_10baseT_Half |
60                                    SUPPORTED_10baseT_Full |
61                                    SUPPORTED_100baseT_Half |
62                                    SUPPORTED_100baseT_Full |
63                                    SUPPORTED_1000baseT_Full|
64                                    SUPPORTED_Autoneg |
65                                    SUPPORTED_TP);
66
67                 ecmd->advertising = ADVERTISED_TP;
68
69                 if(hw->autoneg == 1) {
70                         ecmd->advertising |= ADVERTISED_Autoneg;
71
72                         /* the e1000 autoneg seems to match ethtool nicely */
73
74                         ecmd->advertising |= hw->autoneg_advertised;
75                 }
76
77                 ecmd->port = PORT_TP;
78                 ecmd->phy_address = hw->phy_addr;
79
80                 if(hw->mac_type == e1000_82543)
81                         ecmd->transceiver = XCVR_EXTERNAL;
82                 else
83                         ecmd->transceiver = XCVR_INTERNAL;
84
85         } else {
86                 ecmd->supported   = (SUPPORTED_1000baseT_Full |
87                                      SUPPORTED_FIBRE |
88                                      SUPPORTED_Autoneg);
89
90                 ecmd->advertising = (SUPPORTED_1000baseT_Full |
91                                      SUPPORTED_FIBRE |
92                                      SUPPORTED_Autoneg);
93
94                 ecmd->port = PORT_FIBRE;
95
96                 if(hw->mac_type >= e1000_82545)
97                         ecmd->transceiver = XCVR_INTERNAL;
98                 else
99                         ecmd->transceiver = XCVR_EXTERNAL;
100         }
101
102         if(netif_carrier_ok(adapter->netdev)) {
103
104                 e1000_get_speed_and_duplex(hw, &adapter->link_speed,
105                                                    &adapter->link_duplex);
106                 ecmd->speed = adapter->link_speed;
107
108                 /* unfortunatly FULL_DUPLEX != DUPLEX_FULL
109                  *          and HALF_DUPLEX != DUPLEX_HALF */
110
111                 if(adapter->link_duplex == FULL_DUPLEX)
112                         ecmd->duplex = DUPLEX_FULL;
113                 else
114                         ecmd->duplex = DUPLEX_HALF;
115         } else {
116                 ecmd->speed = -1;
117                 ecmd->duplex = -1;
118         }
119
120         ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
121 }
122
123 static int
124 e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
125 {
126         struct e1000_hw *hw = &adapter->hw;
127
128         if(ecmd->autoneg == AUTONEG_ENABLE) {
129                 hw->autoneg = 1;
130                 hw->autoneg_advertised = 0x002F;
131                 ecmd->advertising = 0x002F;
132         } else {
133                 hw->autoneg = 0;
134                 switch(ecmd->speed + ecmd->duplex) {
135                 case SPEED_10 + DUPLEX_HALF:
136                         hw->forced_speed_duplex = e1000_10_half;
137                         break;
138                 case SPEED_10 + DUPLEX_FULL:
139                         hw->forced_speed_duplex = e1000_10_full;
140                         break;
141                 case SPEED_100 + DUPLEX_HALF:
142                         hw->forced_speed_duplex = e1000_100_half;
143                         break;
144                 case SPEED_100 + DUPLEX_FULL:
145                         hw->forced_speed_duplex = e1000_100_full;
146                         break;
147                 case SPEED_1000 + DUPLEX_FULL:
148                         hw->autoneg = 1;
149                         hw->autoneg_advertised = ADVERTISE_1000_FULL;
150                         break;
151                 case SPEED_1000 + DUPLEX_HALF: /* not supported */
152                 default:
153                         return -EINVAL;
154                 }
155         }
156
157         /* reset the link */
158
159         if(netif_running(adapter->netdev)) {
160                 e1000_down(adapter);
161                 e1000_up(adapter);
162         } else
163                 e1000_reset(adapter);
164
165         return 0;
166 }
167
168 static inline int
169 e1000_eeprom_size(struct e1000_hw *hw)
170 {
171         if((hw->mac_type > e1000_82544) &&
172            (E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE))
173                 return 512;
174         else
175                 return 128;
176 }
177
178 static void
179 e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
180                        struct ethtool_drvinfo *drvinfo)
181 {
182         strncpy(drvinfo->driver,  e1000_driver_name, 32);
183         strncpy(drvinfo->version, e1000_driver_version, 32);
184         strncpy(drvinfo->fw_version, "N/A", 32);
185         strncpy(drvinfo->bus_info, adapter->pdev->slot_name, 32);
186         drvinfo->n_stats = E1000_STATS_LEN;
187 #define E1000_REGS_LEN 32
188         drvinfo->regdump_len  = E1000_REGS_LEN * sizeof(uint32_t);
189         drvinfo->eedump_len  = e1000_eeprom_size(&adapter->hw);
190 }
191
192 static void
193 e1000_ethtool_gregs(struct e1000_adapter *adapter,
194                     struct ethtool_regs *regs, uint32_t *regs_buff)
195 {
196         struct e1000_hw *hw = &adapter->hw;
197
198         regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
199
200         regs_buff[0]  = E1000_READ_REG(hw, CTRL);
201         regs_buff[1]  = E1000_READ_REG(hw, STATUS);
202
203         regs_buff[2]  = E1000_READ_REG(hw, RCTL);
204         regs_buff[3]  = E1000_READ_REG(hw, RDLEN);
205         regs_buff[4]  = E1000_READ_REG(hw, RDH);
206         regs_buff[5]  = E1000_READ_REG(hw, RDT);
207         regs_buff[6]  = E1000_READ_REG(hw, RDTR);
208
209         regs_buff[7]  = E1000_READ_REG(hw, TCTL);
210         regs_buff[8]  = E1000_READ_REG(hw, TDLEN);
211         regs_buff[9]  = E1000_READ_REG(hw, TDH);
212         regs_buff[10] = E1000_READ_REG(hw, TDT);
213         regs_buff[11] = E1000_READ_REG(hw, TIDV);
214
215         return;
216 }
217
218 static int
219 e1000_ethtool_geeprom(struct e1000_adapter *adapter,
220                       struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
221 {
222         struct e1000_hw *hw = &adapter->hw;
223         int max_len, first_word, last_word;
224         int ret_val = 0;
225         int i;
226
227         if(eeprom->len == 0) {
228                 ret_val = -EINVAL;
229                 goto geeprom_error;
230         }
231
232         eeprom->magic = hw->vendor_id | (hw->device_id << 16);
233
234         max_len = e1000_eeprom_size(hw);
235
236         if(eeprom->offset > eeprom->offset + eeprom->len) {
237                 ret_val = -EINVAL;
238                 goto geeprom_error;
239         }
240
241         if((eeprom->offset + eeprom->len) > max_len)
242                 eeprom->len = (max_len - eeprom->offset);
243
244         first_word = eeprom->offset >> 1;
245         last_word = (eeprom->offset + eeprom->len - 1) >> 1;
246
247         for(i = 0; i <= (last_word - first_word); i++)
248                 e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]);
249
250 geeprom_error:
251         return ret_val;
252 }
253
254 static int
255 e1000_ethtool_seeprom(struct e1000_adapter *adapter,
256                       struct ethtool_eeprom *eeprom, void *user_data)
257 {
258         struct e1000_hw *hw = &adapter->hw;
259         uint16_t *eeprom_buff;
260         int max_len, first_word, last_word;
261         void *ptr;
262         int i;
263
264         if(eeprom->len == 0)
265                 return -EOPNOTSUPP;
266
267         if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
268                 return -EFAULT;
269
270         max_len = e1000_eeprom_size(hw);
271
272         if((eeprom->offset + eeprom->len) > max_len)
273                 eeprom->len = (max_len - eeprom->offset);
274
275         first_word = eeprom->offset >> 1;
276         last_word = (eeprom->offset + eeprom->len - 1) >> 1;
277         eeprom_buff = kmalloc(max_len, GFP_KERNEL);
278         if(eeprom_buff == NULL)
279                 return -ENOMEM;
280
281         ptr = (void *)eeprom_buff;
282
283         if(eeprom->offset & 1) {
284                 /* need read/modify/write of first changed EEPROM word */
285                 /* only the second byte of the word is being modified */
286                 e1000_read_eeprom(hw, first_word, &eeprom_buff[0]);
287                 ptr++;
288         }
289         if((eeprom->offset + eeprom->len) & 1) {
290                 /* need read/modify/write of last changed EEPROM word */
291                 /* only the first byte of the word is being modified */
292                 e1000_read_eeprom(hw, last_word,
293                                   &eeprom_buff[last_word - first_word]);
294         }
295         if(copy_from_user(ptr, user_data, eeprom->len)) {
296                 kfree(eeprom_buff);
297                 return -EFAULT;
298         }
299
300         for(i = 0; i <= (last_word - first_word); i++)
301                 e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]);
302
303         /* Update the checksum over the first part of the EEPROM if needed */
304         if(first_word <= EEPROM_CHECKSUM_REG)
305                 e1000_update_eeprom_checksum(hw);
306
307         kfree(eeprom_buff);
308
309         return 0;
310 }
311
312 static void
313 e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
314 {
315         struct e1000_hw *hw = &adapter->hw;
316
317         switch(adapter->hw.device_id) {
318         case E1000_DEV_ID_82542:
319         case E1000_DEV_ID_82543GC_FIBER:
320         case E1000_DEV_ID_82543GC_COPPER:
321         case E1000_DEV_ID_82544EI_FIBER:
322                 wol->supported = 0;
323                 wol->wolopts   = 0;
324                 return;
325
326         case E1000_DEV_ID_82546EB_FIBER:
327                 /* Wake events only supported on port A for dual fiber */
328                 if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
329                         wol->supported = 0;
330                         wol->wolopts   = 0;
331                         return;
332                 }
333                 /* Fall Through */
334
335         default:
336                 wol->supported = WAKE_UCAST | WAKE_MCAST
337                                  | WAKE_BCAST | WAKE_MAGIC;
338
339                 wol->wolopts = 0;
340                 if(adapter->wol & E1000_WUFC_EX)
341                         wol->wolopts |= WAKE_UCAST;
342                 if(adapter->wol & E1000_WUFC_MC)
343                         wol->wolopts |= WAKE_MCAST;
344                 if(adapter->wol & E1000_WUFC_BC)
345                         wol->wolopts |= WAKE_BCAST;
346                 if(adapter->wol & E1000_WUFC_MAG)
347                         wol->wolopts |= WAKE_MAGIC;
348                 return;
349         }
350 }
351
352 static int
353 e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
354 {
355         struct e1000_hw *hw = &adapter->hw;
356
357         switch(adapter->hw.device_id) {
358         case E1000_DEV_ID_82542:
359         case E1000_DEV_ID_82543GC_FIBER:
360         case E1000_DEV_ID_82543GC_COPPER:
361         case E1000_DEV_ID_82544EI_FIBER:
362                 return wol->wolopts ? -EOPNOTSUPP : 0;
363
364         case E1000_DEV_ID_82546EB_FIBER:
365                 /* Wake events only supported on port A for dual fiber */
366                 if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
367                         return wol->wolopts ? -EOPNOTSUPP : 0;
368                 /* Fall Through */
369
370         default:
371                 if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY))
372                         return -EOPNOTSUPP;
373
374                 adapter->wol = 0;
375
376                 if(wol->wolopts & WAKE_UCAST)
377                         adapter->wol |= E1000_WUFC_EX;
378                 if(wol->wolopts & WAKE_MCAST)
379                         adapter->wol |= E1000_WUFC_MC;
380                 if(wol->wolopts & WAKE_BCAST)
381                         adapter->wol |= E1000_WUFC_BC;
382                 if(wol->wolopts & WAKE_MAGIC)
383                         adapter->wol |= E1000_WUFC_MAG;
384         }
385
386         return 0;
387 }
388
389
390 /* toggle LED 4 times per second = 2 "blinks" per second */
391 #define E1000_ID_INTERVAL       (HZ/4)
392
393 /* bit defines for adapter->led_status */
394 #define E1000_LED_ON            0
395
396 static void
397 e1000_led_blink_callback(unsigned long data)
398 {
399         struct e1000_adapter *adapter = (struct e1000_adapter *) data;
400
401         if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
402                 e1000_led_off(&adapter->hw);
403         else
404                 e1000_led_on(&adapter->hw);
405
406         mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
407 }
408
409 static int
410 e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
411 {
412         if(!adapter->blink_timer.function) {
413                 init_timer(&adapter->blink_timer);
414                 adapter->blink_timer.function = e1000_led_blink_callback;
415                 adapter->blink_timer.data = (unsigned long) adapter;
416         }
417
418         e1000_setup_led(&adapter->hw);
419         mod_timer(&adapter->blink_timer, jiffies);
420
421         set_current_state(TASK_INTERRUPTIBLE);
422         if(id->data)
423                 schedule_timeout(id->data * HZ);
424         else
425                 schedule_timeout(MAX_SCHEDULE_TIMEOUT);
426
427         del_timer_sync(&adapter->blink_timer);
428         e1000_led_off(&adapter->hw);
429         clear_bit(E1000_LED_ON, &adapter->led_status);
430         e1000_cleanup_led(&adapter->hw);
431
432         return 0;
433 }
434
435 int
436 e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
437 {
438         struct e1000_adapter *adapter = netdev->priv;
439         void *addr = ifr->ifr_data;
440         uint32_t cmd;
441
442         if(get_user(cmd, (uint32_t *) addr))
443                 return -EFAULT;
444
445         switch(cmd) {
446         case ETHTOOL_GSET: {
447                 struct ethtool_cmd ecmd = {ETHTOOL_GSET};
448                 e1000_ethtool_gset(adapter, &ecmd);
449                 if(copy_to_user(addr, &ecmd, sizeof(ecmd)))
450                         return -EFAULT;
451                 return 0;
452         }
453         case ETHTOOL_SSET: {
454                 struct ethtool_cmd ecmd;
455                 if(!capable(CAP_NET_ADMIN))
456                         return -EPERM;
457                 if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
458                         return -EFAULT;
459                 return e1000_ethtool_sset(adapter, &ecmd);
460         }
461         case ETHTOOL_GDRVINFO: {
462                 struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO};
463                 e1000_ethtool_gdrvinfo(adapter, &drvinfo);
464                 if(copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
465                         return -EFAULT;
466                 return 0;
467         }
468         case ETHTOOL_GSTRINGS: {
469                 struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
470                 char *strings = NULL;
471
472                 if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
473                         return -EFAULT;
474                 switch(gstrings.string_set) {
475                 case ETH_SS_STATS:
476                         gstrings.len = E1000_STATS_LEN;
477                         strings = *e1000_gstrings_stats;
478                         break;
479                 default:
480                         return -EOPNOTSUPP;
481                 }
482                 if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
483                         return -EFAULT;
484                 addr += offsetof(struct ethtool_gstrings, data);
485                 if(copy_to_user(addr, strings,
486                    gstrings.len * ETH_GSTRING_LEN))
487                         return -EFAULT;
488                 return 0;
489         }
490         case ETHTOOL_GREGS: {
491                 struct ethtool_regs regs = {ETHTOOL_GREGS};
492                 uint32_t regs_buff[E1000_REGS_LEN];
493
494                 if(copy_from_user(&regs, addr, sizeof(regs)))
495                         return -EFAULT;
496                 e1000_ethtool_gregs(adapter, &regs, regs_buff);
497                 if(copy_to_user(addr, &regs, sizeof(regs)))
498                         return -EFAULT;
499
500                 addr += offsetof(struct ethtool_regs, data);
501                 if(copy_to_user(addr, regs_buff, regs.len))
502                         return -EFAULT;
503
504                 return 0;
505         }
506         case ETHTOOL_NWAY_RST: {
507                 if(!capable(CAP_NET_ADMIN))
508                         return -EPERM;
509                 if(netif_running(netdev)) {
510                         e1000_down(adapter);
511                         e1000_up(adapter);
512                 }
513                 return 0;
514         }
515         case ETHTOOL_PHYS_ID: {
516                 struct ethtool_value id;
517                 if(copy_from_user(&id, addr, sizeof(id)))
518                         return -EFAULT;
519                 return e1000_ethtool_led_blink(adapter, &id);
520         }
521         case ETHTOOL_GLINK: {
522                 struct ethtool_value link = {ETHTOOL_GLINK};
523                 link.data = netif_carrier_ok(netdev);
524                 if(copy_to_user(addr, &link, sizeof(link)))
525                         return -EFAULT;
526                 return 0;
527         }
528         case ETHTOOL_GWOL: {
529                 struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
530                 e1000_ethtool_gwol(adapter, &wol);
531                 if(copy_to_user(addr, &wol, sizeof(wol)) != 0)
532                         return -EFAULT;
533                 return 0;
534         }
535         case ETHTOOL_SWOL: {
536                 struct ethtool_wolinfo wol;
537                 if(!capable(CAP_NET_ADMIN))
538                         return -EPERM;
539                 if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
540                         return -EFAULT;
541                 return e1000_ethtool_swol(adapter, &wol);
542         }
543         case ETHTOOL_GEEPROM: {
544                 struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
545                 uint16_t *eeprom_buff;
546                 void *ptr;
547                 int max_len, err = 0;
548
549                 max_len = e1000_eeprom_size(&adapter->hw);
550
551                 eeprom_buff = kmalloc(max_len, GFP_KERNEL);
552
553                 if(eeprom_buff == NULL)
554                         return -ENOMEM;
555
556                 if(copy_from_user(&eeprom, addr, sizeof(eeprom))) {
557                         err = -EFAULT;
558                         goto err_geeprom_ioctl;
559                 }
560
561                 if((err = e1000_ethtool_geeprom(adapter, &eeprom,
562                                                 eeprom_buff)))
563                         goto err_geeprom_ioctl;
564
565                 if(copy_to_user(addr, &eeprom, sizeof(eeprom))) {
566                         err = -EFAULT;
567                         goto err_geeprom_ioctl;
568                 }
569
570                 addr += offsetof(struct ethtool_eeprom, data);
571                 ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
572
573                 if(copy_to_user(addr, ptr, eeprom.len))
574                         err = -EFAULT;
575
576 err_geeprom_ioctl:
577                 kfree(eeprom_buff);
578                 return err;
579         }
580         case ETHTOOL_SEEPROM: {
581                 struct ethtool_eeprom eeprom;
582
583                 if(!capable(CAP_NET_ADMIN))
584                         return -EPERM;
585
586                 if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
587                         return -EFAULT;
588
589                 addr += offsetof(struct ethtool_eeprom, data);
590                 return e1000_ethtool_seeprom(adapter, &eeprom, addr);
591         }
592         case ETHTOOL_GSTATS: {
593                 struct {
594                         struct ethtool_stats cmd;
595                         uint64_t data[E1000_STATS_LEN];
596                 } stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
597                 int i;
598
599                 for(i = 0; i < E1000_STATS_LEN; i++)
600                         stats.data[i] =
601                                 ((unsigned long *)&adapter->net_stats)[i];
602                 if(copy_to_user(addr, &stats, sizeof(stats)))
603                         return -EFAULT;
604                 return 0;
605         }
606         default:
607                 return -EOPNOTSUPP;
608         }
609 }
610
611