aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2010-06-17 14:58:43 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-23 15:58:38 -0400
commit0c6bdb3084d015221270b418190b630553a38cf8 (patch)
tree5362357877c998ecd88df96f45e03362a8db727d /drivers
parent69ad78208ecf4c392f3d323ed050423847c24104 (diff)
e1000e: avoid polling h/w registers during link negotiation
Avoid touching hardware registers when possible, otherwise link negotiation can get messed up when user-level scripts are rapidly polling the driver to see if/when link is up. Use the saved link state information instead when possible. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/e1000e/e1000.h1
-rw-r--r--drivers/net/e1000e/ethtool.c54
-rw-r--r--drivers/net/e1000e/netdev.c2
3 files changed, 29 insertions, 28 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 328b7f4a07bc..9ee133f5034e 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -461,7 +461,6 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
461extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); 461extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
462extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); 462extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
463extern void e1000e_update_stats(struct e1000_adapter *adapter); 463extern void e1000e_update_stats(struct e1000_adapter *adapter);
464extern bool e1000e_has_link(struct e1000_adapter *adapter);
465extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); 464extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
466extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); 465extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
467extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); 466extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index db86850b1636..77c5829ab945 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -118,7 +118,6 @@ static int e1000_get_settings(struct net_device *netdev,
118{ 118{
119 struct e1000_adapter *adapter = netdev_priv(netdev); 119 struct e1000_adapter *adapter = netdev_priv(netdev);
120 struct e1000_hw *hw = &adapter->hw; 120 struct e1000_hw *hw = &adapter->hw;
121 u32 status;
122 121
123 if (hw->phy.media_type == e1000_media_type_copper) { 122 if (hw->phy.media_type == e1000_media_type_copper) {
124 123
@@ -156,22 +155,29 @@ static int e1000_get_settings(struct net_device *netdev,
156 ecmd->transceiver = XCVR_EXTERNAL; 155 ecmd->transceiver = XCVR_EXTERNAL;
157 } 156 }
158 157
159 status = er32(STATUS); 158 ecmd->speed = -1;
160 if (status & E1000_STATUS_LU) { 159 ecmd->duplex = -1;
161 if (status & E1000_STATUS_SPEED_1000)
162 ecmd->speed = 1000;
163 else if (status & E1000_STATUS_SPEED_100)
164 ecmd->speed = 100;
165 else
166 ecmd->speed = 10;
167 160
168 if (status & E1000_STATUS_FD) 161 if (netif_running(netdev)) {
169 ecmd->duplex = DUPLEX_FULL; 162 if (netif_carrier_ok(netdev)) {
170 else 163 ecmd->speed = adapter->link_speed;
171 ecmd->duplex = DUPLEX_HALF; 164 ecmd->duplex = adapter->link_duplex - 1;
165 }
172 } else { 166 } else {
173 ecmd->speed = -1; 167 u32 status = er32(STATUS);
174 ecmd->duplex = -1; 168 if (status & E1000_STATUS_LU) {
169 if (status & E1000_STATUS_SPEED_1000)
170 ecmd->speed = 1000;
171 else if (status & E1000_STATUS_SPEED_100)
172 ecmd->speed = 100;
173 else
174 ecmd->speed = 10;
175
176 if (status & E1000_STATUS_FD)
177 ecmd->duplex = DUPLEX_FULL;
178 else
179 ecmd->duplex = DUPLEX_HALF;
180 }
175 } 181 }
176 182
177 ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || 183 ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
@@ -179,7 +185,7 @@ static int e1000_get_settings(struct net_device *netdev,
179 185
180 /* MDI-X => 2; MDI =>1; Invalid =>0 */ 186 /* MDI-X => 2; MDI =>1; Invalid =>0 */
181 if ((hw->phy.media_type == e1000_media_type_copper) && 187 if ((hw->phy.media_type == e1000_media_type_copper) &&
182 !hw->mac.get_link_status) 188 netif_carrier_ok(netdev))
183 ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : 189 ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
184 ETH_TP_MDI; 190 ETH_TP_MDI;
185 else 191 else
@@ -191,19 +197,15 @@ static int e1000_get_settings(struct net_device *netdev,
191static u32 e1000_get_link(struct net_device *netdev) 197static u32 e1000_get_link(struct net_device *netdev)
192{ 198{
193 struct e1000_adapter *adapter = netdev_priv(netdev); 199 struct e1000_adapter *adapter = netdev_priv(netdev);
194 struct e1000_mac_info *mac = &adapter->hw.mac; 200 struct e1000_hw *hw = &adapter->hw;
195 201
196 /* 202 /*
197 * If the link is not reported up to netdev, interrupts are disabled, 203 * Avoid touching hardware registers when possible, otherwise
198 * and so the physical link state may have changed since we last 204 * link negotiation can get messed up when user-level scripts
199 * looked. Set get_link_status to make sure that the true link 205 * are rapidly polling the driver to see if link is up.
200 * state is interrogated, rather than pulling a cached and possibly
201 * stale link state from the driver.
202 */ 206 */
203 if (!netif_carrier_ok(netdev)) 207 return netif_running(netdev) ? netif_carrier_ok(netdev) :
204 mac->get_link_status = 1; 208 !!(er32(STATUS) & E1000_STATUS_LU);
205
206 return e1000e_has_link(adapter);
207} 209}
208 210
209static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) 211static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 8faf2246d89c..2a71889112b6 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3964,7 +3964,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
3964 ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" ))); 3964 ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
3965} 3965}
3966 3966
3967bool e1000e_has_link(struct e1000_adapter *adapter) 3967static bool e1000e_has_link(struct e1000_adapter *adapter)
3968{ 3968{
3969 struct e1000_hw *hw = &adapter->hw; 3969 struct e1000_hw *hw = &adapter->hw;
3970 bool link_active = 0; 3970 bool link_active = 0;