diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/e1000e/ethtool.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/e1000e/ethtool.c')
-rw-r--r-- | drivers/net/e1000e/ethtool.c | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index e82638ecae88..983493f2330c 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | 2 | ||
3 | Intel PRO/1000 Linux driver | 3 | Intel PRO/1000 Linux driver |
4 | Copyright(c) 1999 - 2008 Intel Corporation. | 4 | Copyright(c) 1999 - 2009 Intel Corporation. |
5 | 5 | ||
6 | This program is free software; you can redistribute it and/or modify it | 6 | This program is free software; you can redistribute it and/or modify it |
7 | under the terms and conditions of the GNU General Public License, | 7 | under the terms and conditions of the GNU General Public License, |
@@ -31,18 +31,27 @@ | |||
31 | #include <linux/netdevice.h> | 31 | #include <linux/netdevice.h> |
32 | #include <linux/ethtool.h> | 32 | #include <linux/ethtool.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/slab.h> | ||
34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
35 | 36 | ||
36 | #include "e1000.h" | 37 | #include "e1000.h" |
37 | 38 | ||
39 | enum {NETDEV_STATS, E1000_STATS}; | ||
40 | |||
38 | struct e1000_stats { | 41 | struct e1000_stats { |
39 | char stat_string[ETH_GSTRING_LEN]; | 42 | char stat_string[ETH_GSTRING_LEN]; |
43 | int type; | ||
40 | int sizeof_stat; | 44 | int sizeof_stat; |
41 | int stat_offset; | 45 | int stat_offset; |
42 | }; | 46 | }; |
43 | 47 | ||
44 | #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ | 48 | #define E1000_STAT(m) E1000_STATS, \ |
45 | offsetof(struct e1000_adapter, m) | 49 | sizeof(((struct e1000_adapter *)0)->m), \ |
50 | offsetof(struct e1000_adapter, m) | ||
51 | #define E1000_NETDEV_STAT(m) NETDEV_STATS, \ | ||
52 | sizeof(((struct net_device *)0)->m), \ | ||
53 | offsetof(struct net_device, m) | ||
54 | |||
46 | static const struct e1000_stats e1000_gstrings_stats[] = { | 55 | static const struct e1000_stats e1000_gstrings_stats[] = { |
47 | { "rx_packets", E1000_STAT(stats.gprc) }, | 56 | { "rx_packets", E1000_STAT(stats.gprc) }, |
48 | { "tx_packets", E1000_STAT(stats.gptc) }, | 57 | { "tx_packets", E1000_STAT(stats.gptc) }, |
@@ -52,21 +61,21 @@ static const struct e1000_stats e1000_gstrings_stats[] = { | |||
52 | { "tx_broadcast", E1000_STAT(stats.bptc) }, | 61 | { "tx_broadcast", E1000_STAT(stats.bptc) }, |
53 | { "rx_multicast", E1000_STAT(stats.mprc) }, | 62 | { "rx_multicast", E1000_STAT(stats.mprc) }, |
54 | { "tx_multicast", E1000_STAT(stats.mptc) }, | 63 | { "tx_multicast", E1000_STAT(stats.mptc) }, |
55 | { "rx_errors", E1000_STAT(net_stats.rx_errors) }, | 64 | { "rx_errors", E1000_NETDEV_STAT(stats.rx_errors) }, |
56 | { "tx_errors", E1000_STAT(net_stats.tx_errors) }, | 65 | { "tx_errors", E1000_NETDEV_STAT(stats.tx_errors) }, |
57 | { "tx_dropped", E1000_STAT(net_stats.tx_dropped) }, | 66 | { "tx_dropped", E1000_NETDEV_STAT(stats.tx_dropped) }, |
58 | { "multicast", E1000_STAT(stats.mprc) }, | 67 | { "multicast", E1000_STAT(stats.mprc) }, |
59 | { "collisions", E1000_STAT(stats.colc) }, | 68 | { "collisions", E1000_STAT(stats.colc) }, |
60 | { "rx_length_errors", E1000_STAT(net_stats.rx_length_errors) }, | 69 | { "rx_length_errors", E1000_NETDEV_STAT(stats.rx_length_errors) }, |
61 | { "rx_over_errors", E1000_STAT(net_stats.rx_over_errors) }, | 70 | { "rx_over_errors", E1000_NETDEV_STAT(stats.rx_over_errors) }, |
62 | { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, | 71 | { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, |
63 | { "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) }, | 72 | { "rx_frame_errors", E1000_NETDEV_STAT(stats.rx_frame_errors) }, |
64 | { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, | 73 | { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, |
65 | { "rx_missed_errors", E1000_STAT(stats.mpc) }, | 74 | { "rx_missed_errors", E1000_STAT(stats.mpc) }, |
66 | { "tx_aborted_errors", E1000_STAT(stats.ecol) }, | 75 | { "tx_aborted_errors", E1000_STAT(stats.ecol) }, |
67 | { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, | 76 | { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, |
68 | { "tx_fifo_errors", E1000_STAT(net_stats.tx_fifo_errors) }, | 77 | { "tx_fifo_errors", E1000_NETDEV_STAT(stats.tx_fifo_errors) }, |
69 | { "tx_heartbeat_errors", E1000_STAT(net_stats.tx_heartbeat_errors) }, | 78 | { "tx_heartbeat_errors", E1000_NETDEV_STAT(stats.tx_heartbeat_errors) }, |
70 | { "tx_window_errors", E1000_STAT(stats.latecol) }, | 79 | { "tx_window_errors", E1000_STAT(stats.latecol) }, |
71 | { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, | 80 | { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, |
72 | { "tx_deferred_ok", E1000_STAT(stats.dc) }, | 81 | { "tx_deferred_ok", E1000_STAT(stats.dc) }, |
@@ -182,8 +191,19 @@ static int e1000_get_settings(struct net_device *netdev, | |||
182 | static u32 e1000_get_link(struct net_device *netdev) | 191 | static u32 e1000_get_link(struct net_device *netdev) |
183 | { | 192 | { |
184 | struct e1000_adapter *adapter = netdev_priv(netdev); | 193 | struct e1000_adapter *adapter = netdev_priv(netdev); |
194 | struct e1000_mac_info *mac = &adapter->hw.mac; | ||
195 | |||
196 | /* | ||
197 | * If the link is not reported up to netdev, interrupts are disabled, | ||
198 | * and so the physical link state may have changed since we last | ||
199 | * looked. Set get_link_status to make sure that the true link | ||
200 | * state is interrogated, rather than pulling a cached and possibly | ||
201 | * stale link state from the driver. | ||
202 | */ | ||
203 | if (!netif_carrier_ok(netdev)) | ||
204 | mac->get_link_status = 1; | ||
185 | 205 | ||
186 | return e1000_has_link(adapter); | 206 | return e1000e_has_link(adapter); |
187 | } | 207 | } |
188 | 208 | ||
189 | static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) | 209 | static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) |
@@ -516,7 +536,8 @@ static int e1000_get_eeprom(struct net_device *netdev, | |||
516 | 536 | ||
517 | if (ret_val) { | 537 | if (ret_val) { |
518 | /* a read error occurred, throw away the result */ | 538 | /* a read error occurred, throw away the result */ |
519 | memset(eeprom_buff, 0xff, sizeof(eeprom_buff)); | 539 | memset(eeprom_buff, 0xff, sizeof(u16) * |
540 | (last_word - first_word + 1)); | ||
520 | } else { | 541 | } else { |
521 | /* Device's eeprom is always little-endian, word addressable */ | 542 | /* Device's eeprom is always little-endian, word addressable */ |
522 | for (i = 0; i < last_word - first_word + 1; i++) | 543 | for (i = 0; i < last_word - first_word + 1; i++) |
@@ -596,7 +617,9 @@ static int e1000_set_eeprom(struct net_device *netdev, | |||
596 | * and flush shadow RAM for applicable controllers | 617 | * and flush shadow RAM for applicable controllers |
597 | */ | 618 | */ |
598 | if ((first_word <= NVM_CHECKSUM_REG) || | 619 | if ((first_word <= NVM_CHECKSUM_REG) || |
599 | (hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82573)) | 620 | (hw->mac.type == e1000_82583) || |
621 | (hw->mac.type == e1000_82574) || | ||
622 | (hw->mac.type == e1000_82573)) | ||
600 | ret_val = e1000e_update_nvm_checksum(hw); | 623 | ret_val = e1000e_update_nvm_checksum(hw); |
601 | 624 | ||
602 | out: | 625 | out: |
@@ -929,10 +952,10 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) | |||
929 | e1000e_set_interrupt_capability(adapter); | 952 | e1000e_set_interrupt_capability(adapter); |
930 | } | 953 | } |
931 | /* Hook up test interrupt handler just for this test */ | 954 | /* Hook up test interrupt handler just for this test */ |
932 | if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, | 955 | if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, |
933 | netdev)) { | 956 | netdev)) { |
934 | shared_int = 0; | 957 | shared_int = 0; |
935 | } else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED, | 958 | } else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, |
936 | netdev->name, netdev)) { | 959 | netdev->name, netdev)) { |
937 | *data = 1; | 960 | *data = 1; |
938 | ret_val = -1; | 961 | ret_val = -1; |
@@ -1239,6 +1262,10 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) | |||
1239 | 1262 | ||
1240 | hw->mac.autoneg = 0; | 1263 | hw->mac.autoneg = 0; |
1241 | 1264 | ||
1265 | /* Workaround: K1 must be disabled for stable 1Gbps operation */ | ||
1266 | if (hw->mac.type == e1000_pchlan) | ||
1267 | e1000_configure_k1_ich8lan(hw, false); | ||
1268 | |||
1242 | if (hw->phy.type == e1000_phy_m88) { | 1269 | if (hw->phy.type == e1000_phy_m88) { |
1243 | /* Auto-MDI/MDIX Off */ | 1270 | /* Auto-MDI/MDIX Off */ |
1244 | e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); | 1271 | e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); |
@@ -1769,12 +1796,11 @@ static int e1000_set_wol(struct net_device *netdev, | |||
1769 | { | 1796 | { |
1770 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1797 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1771 | 1798 | ||
1772 | if (wol->wolopts & WAKE_MAGICSECURE) | ||
1773 | return -EOPNOTSUPP; | ||
1774 | |||
1775 | if (!(adapter->flags & FLAG_HAS_WOL) || | 1799 | if (!(adapter->flags & FLAG_HAS_WOL) || |
1776 | !device_can_wakeup(&adapter->pdev->dev)) | 1800 | !device_can_wakeup(&adapter->pdev->dev) || |
1777 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1801 | (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | |
1802 | WAKE_MAGIC | WAKE_PHY | WAKE_ARP))) | ||
1803 | return -EOPNOTSUPP; | ||
1778 | 1804 | ||
1779 | /* these settings will always override what we currently have */ | 1805 | /* these settings will always override what we currently have */ |
1780 | adapter->wol = 0; | 1806 | adapter->wol = 0; |
@@ -1832,6 +1858,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) | |||
1832 | 1858 | ||
1833 | if ((hw->phy.type == e1000_phy_ife) || | 1859 | if ((hw->phy.type == e1000_phy_ife) || |
1834 | (hw->mac.type == e1000_pchlan) || | 1860 | (hw->mac.type == e1000_pchlan) || |
1861 | (hw->mac.type == e1000_82583) || | ||
1835 | (hw->mac.type == e1000_82574)) { | 1862 | (hw->mac.type == e1000_82574)) { |
1836 | INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); | 1863 | INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); |
1837 | if (!adapter->blink_timer.function) { | 1864 | if (!adapter->blink_timer.function) { |
@@ -1912,10 +1939,21 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, | |||
1912 | { | 1939 | { |
1913 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1940 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1914 | int i; | 1941 | int i; |
1942 | char *p = NULL; | ||
1915 | 1943 | ||
1916 | e1000e_update_stats(adapter); | 1944 | e1000e_update_stats(adapter); |
1917 | for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { | 1945 | for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { |
1918 | char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; | 1946 | switch (e1000_gstrings_stats[i].type) { |
1947 | case NETDEV_STATS: | ||
1948 | p = (char *) netdev + | ||
1949 | e1000_gstrings_stats[i].stat_offset; | ||
1950 | break; | ||
1951 | case E1000_STATS: | ||
1952 | p = (char *) adapter + | ||
1953 | e1000_gstrings_stats[i].stat_offset; | ||
1954 | break; | ||
1955 | } | ||
1956 | |||
1919 | data[i] = (e1000_gstrings_stats[i].sizeof_stat == | 1957 | data[i] = (e1000_gstrings_stats[i].sizeof_stat == |
1920 | sizeof(u64)) ? *(u64 *)p : *(u32 *)p; | 1958 | sizeof(u64)) ? *(u64 *)p : *(u32 *)p; |
1921 | } | 1959 | } |
@@ -1975,6 +2013,8 @@ static const struct ethtool_ops e1000_ethtool_ops = { | |||
1975 | .get_sset_count = e1000e_get_sset_count, | 2013 | .get_sset_count = e1000e_get_sset_count, |
1976 | .get_coalesce = e1000_get_coalesce, | 2014 | .get_coalesce = e1000_get_coalesce, |
1977 | .set_coalesce = e1000_set_coalesce, | 2015 | .set_coalesce = e1000_set_coalesce, |
2016 | .get_flags = ethtool_op_get_flags, | ||
2017 | .set_flags = ethtool_op_set_flags, | ||
1978 | }; | 2018 | }; |
1979 | 2019 | ||
1980 | void e1000e_set_ethtool_ops(struct net_device *netdev) | 2020 | void e1000e_set_ethtool_ops(struct net_device *netdev) |