aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2013-06-29 13:23:19 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-01 16:18:19 -0400
commit7ec5689461989fd80f1cf82ae084f5d50a5e63ee (patch)
treebc9c368f432204329568786aa0ef2b4c3a1126f0 /drivers/net/ethernet
parent46ab9b347d677976b2b4072837cb4065839c0b80 (diff)
alx: fix ethtool support code
A number of places treated features wrongly, listing not-supported features instead of supported ones. Also, the get_drvinfo ethtool callback isn't needed, and alx_get_pauseparam can be simplified. Reported-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/atheros/alx/ethtool.c64
1 files changed, 29 insertions, 35 deletions
diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c
index 5e19e08b691b..926100626d60 100644
--- a/drivers/net/ethernet/atheros/alx/ethtool.c
+++ b/drivers/net/ethernet/atheros/alx/ethtool.c
@@ -46,21 +46,37 @@
46#include "reg.h" 46#include "reg.h"
47#include "hw.h" 47#include "hw.h"
48 48
49static u32 alx_get_supported_speeds(struct alx_hw *hw)
50{
51 u32 supported = SUPPORTED_10baseT_Half |
52 SUPPORTED_10baseT_Full |
53 SUPPORTED_100baseT_Half |
54 SUPPORTED_100baseT_Full;
55
56 if (alx_hw_giga(hw))
57 supported |= SUPPORTED_1000baseT_Full;
58
59 BUILD_BUG_ON(SUPPORTED_10baseT_Half != ADVERTISED_10baseT_Half);
60 BUILD_BUG_ON(SUPPORTED_10baseT_Full != ADVERTISED_10baseT_Full);
61 BUILD_BUG_ON(SUPPORTED_100baseT_Half != ADVERTISED_100baseT_Half);
62 BUILD_BUG_ON(SUPPORTED_100baseT_Full != ADVERTISED_100baseT_Full);
63 BUILD_BUG_ON(SUPPORTED_1000baseT_Full != ADVERTISED_1000baseT_Full);
64
65 return supported;
66}
49 67
50static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) 68static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
51{ 69{
52 struct alx_priv *alx = netdev_priv(netdev); 70 struct alx_priv *alx = netdev_priv(netdev);
53 struct alx_hw *hw = &alx->hw; 71 struct alx_hw *hw = &alx->hw;
54 72
55 ecmd->supported = SUPPORTED_10baseT_Half | 73 ecmd->supported = SUPPORTED_Autoneg |
56 SUPPORTED_10baseT_Full |
57 SUPPORTED_100baseT_Half |
58 SUPPORTED_100baseT_Full |
59 SUPPORTED_Autoneg |
60 SUPPORTED_TP | 74 SUPPORTED_TP |
61 SUPPORTED_Pause; 75 SUPPORTED_Pause |
76 SUPPORTED_Asym_Pause;
62 if (alx_hw_giga(hw)) 77 if (alx_hw_giga(hw))
63 ecmd->supported |= SUPPORTED_1000baseT_Full; 78 ecmd->supported |= SUPPORTED_1000baseT_Full;
79 ecmd->supported |= alx_get_supported_speeds(hw);
64 80
65 ecmd->advertising = ADVERTISED_TP; 81 ecmd->advertising = ADVERTISED_TP;
66 if (hw->adv_cfg & ADVERTISED_Autoneg) 82 if (hw->adv_cfg & ADVERTISED_Autoneg)
@@ -68,6 +84,7 @@ static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
68 84
69 ecmd->port = PORT_TP; 85 ecmd->port = PORT_TP;
70 ecmd->phy_address = 0; 86 ecmd->phy_address = 0;
87
71 if (hw->adv_cfg & ADVERTISED_Autoneg) 88 if (hw->adv_cfg & ADVERTISED_Autoneg)
72 ecmd->autoneg = AUTONEG_ENABLE; 89 ecmd->autoneg = AUTONEG_ENABLE;
73 else 90 else
@@ -100,7 +117,7 @@ static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
100 ASSERT_RTNL(); 117 ASSERT_RTNL();
101 118
102 if (ecmd->autoneg == AUTONEG_ENABLE) { 119 if (ecmd->autoneg == AUTONEG_ENABLE) {
103 if (ecmd->advertising & ADVERTISED_1000baseT_Half) 120 if (ecmd->advertising & ~alx_get_supported_speeds(hw))
104 return -EINVAL; 121 return -EINVAL;
105 adv_cfg = ecmd->advertising | ADVERTISED_Autoneg; 122 adv_cfg = ecmd->advertising | ADVERTISED_Autoneg;
106 } else { 123 } else {
@@ -121,21 +138,10 @@ static void alx_get_pauseparam(struct net_device *netdev,
121 struct alx_priv *alx = netdev_priv(netdev); 138 struct alx_priv *alx = netdev_priv(netdev);
122 struct alx_hw *hw = &alx->hw; 139 struct alx_hw *hw = &alx->hw;
123 140
124 if (hw->flowctrl & ALX_FC_ANEG && 141 pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG &&
125 hw->adv_cfg & ADVERTISED_Autoneg) 142 hw->adv_cfg & ADVERTISED_Autoneg);
126 pause->autoneg = AUTONEG_ENABLE; 143 pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX);
127 else 144 pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX);
128 pause->autoneg = AUTONEG_DISABLE;
129
130 if (hw->flowctrl & ALX_FC_TX)
131 pause->tx_pause = 1;
132 else
133 pause->tx_pause = 0;
134
135 if (hw->flowctrl & ALX_FC_RX)
136 pause->rx_pause = 1;
137 else
138 pause->rx_pause = 0;
139} 145}
140 146
141 147
@@ -214,8 +220,7 @@ static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
214 struct alx_priv *alx = netdev_priv(netdev); 220 struct alx_priv *alx = netdev_priv(netdev);
215 struct alx_hw *hw = &alx->hw; 221 struct alx_hw *hw = &alx->hw;
216 222
217 if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | 223 if (wol->wolopts & ~(WAKE_MAGIC | WAKE_PHY))
218 WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
219 return -EOPNOTSUPP; 224 return -EOPNOTSUPP;
220 225
221 hw->sleep_ctrl = 0; 226 hw->sleep_ctrl = 0;
@@ -230,22 +235,11 @@ static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
230 return 0; 235 return 0;
231} 236}
232 237
233static void alx_get_drvinfo(struct net_device *netdev,
234 struct ethtool_drvinfo *drvinfo)
235{
236 struct alx_priv *alx = netdev_priv(netdev);
237
238 strlcpy(drvinfo->driver, alx_drv_name, sizeof(drvinfo->driver));
239 strlcpy(drvinfo->bus_info, pci_name(alx->hw.pdev),
240 sizeof(drvinfo->bus_info));
241}
242
243const struct ethtool_ops alx_ethtool_ops = { 238const struct ethtool_ops alx_ethtool_ops = {
244 .get_settings = alx_get_settings, 239 .get_settings = alx_get_settings,
245 .set_settings = alx_set_settings, 240 .set_settings = alx_set_settings,
246 .get_pauseparam = alx_get_pauseparam, 241 .get_pauseparam = alx_get_pauseparam,
247 .set_pauseparam = alx_set_pauseparam, 242 .set_pauseparam = alx_set_pauseparam,
248 .get_drvinfo = alx_get_drvinfo,
249 .get_msglevel = alx_get_msglevel, 243 .get_msglevel = alx_get_msglevel,
250 .set_msglevel = alx_set_msglevel, 244 .set_msglevel = alx_set_msglevel,
251 .get_wol = alx_get_wol, 245 .get_wol = alx_get_wol,