aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2008-11-22 00:30:24 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-22 00:30:24 -0500
commitf5f4cf08467db10de061a1b90037a56a360d3554 (patch)
treef590f5a39dca1a57012f5eb62302ca56b7d3e27a
parent21fc578dcaa66dd30bad3c2f2cd7578e2865e8f2 (diff)
igb: do not use phy ops in ethtool test cleanup for non-copper parts
Currently the igb driver is experiencing a panic due to a null function pointer being used during the cleanup of the ethtool looback test on fiber/serdes parts. This patch prevents that and adds a check prior to calling any phy function. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/igb/igb.h32
-rw-r--r--drivers/net/igb/igb_ethtool.c20
-rw-r--r--drivers/net/igb/igb_main.c20
3 files changed, 50 insertions, 22 deletions
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index acf2569b98f4..2121b8bc6ea7 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -332,4 +332,36 @@ extern void igb_free_rx_resources(struct igb_ring *);
332extern void igb_update_stats(struct igb_adapter *); 332extern void igb_update_stats(struct igb_adapter *);
333extern void igb_set_ethtool_ops(struct net_device *); 333extern void igb_set_ethtool_ops(struct net_device *);
334 334
335static inline s32 igb_reset_phy(struct e1000_hw *hw)
336{
337 if (hw->phy.ops.reset_phy)
338 return hw->phy.ops.reset_phy(hw);
339
340 return 0;
341}
342
343static inline s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
344{
345 if (hw->phy.ops.read_phy_reg)
346 return hw->phy.ops.read_phy_reg(hw, offset, data);
347
348 return 0;
349}
350
351static inline s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
352{
353 if (hw->phy.ops.write_phy_reg)
354 return hw->phy.ops.write_phy_reg(hw, offset, data);
355
356 return 0;
357}
358
359static inline s32 igb_get_phy_info(struct e1000_hw *hw)
360{
361 if (hw->phy.ops.get_phy_info)
362 return hw->phy.ops.get_phy_info(hw);
363
364 return 0;
365}
366
335#endif /* _IGB_H_ */ 367#endif /* _IGB_H_ */
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index a661159a097b..8e9d295034ff 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1376,10 +1376,10 @@ static void igb_phy_disable_receiver(struct igb_adapter *adapter)
1376 struct e1000_hw *hw = &adapter->hw; 1376 struct e1000_hw *hw = &adapter->hw;
1377 1377
1378 /* Write out to PHY registers 29 and 30 to disable the Receiver. */ 1378 /* Write out to PHY registers 29 and 30 to disable the Receiver. */
1379 hw->phy.ops.write_phy_reg(hw, 29, 0x001F); 1379 igb_write_phy_reg(hw, 29, 0x001F);
1380 hw->phy.ops.write_phy_reg(hw, 30, 0x8FFC); 1380 igb_write_phy_reg(hw, 30, 0x8FFC);
1381 hw->phy.ops.write_phy_reg(hw, 29, 0x001A); 1381 igb_write_phy_reg(hw, 29, 0x001A);
1382 hw->phy.ops.write_phy_reg(hw, 30, 0x8FF0); 1382 igb_write_phy_reg(hw, 30, 0x8FF0);
1383} 1383}
1384 1384
1385static int igb_integrated_phy_loopback(struct igb_adapter *adapter) 1385static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
@@ -1392,17 +1392,17 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
1392 1392
1393 if (hw->phy.type == e1000_phy_m88) { 1393 if (hw->phy.type == e1000_phy_m88) {
1394 /* Auto-MDI/MDIX Off */ 1394 /* Auto-MDI/MDIX Off */
1395 hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); 1395 igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
1396 /* reset to update Auto-MDI/MDIX */ 1396 /* reset to update Auto-MDI/MDIX */
1397 hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, 0x9140); 1397 igb_write_phy_reg(hw, PHY_CONTROL, 0x9140);
1398 /* autoneg off */ 1398 /* autoneg off */
1399 hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, 0x8140); 1399 igb_write_phy_reg(hw, PHY_CONTROL, 0x8140);
1400 } 1400 }
1401 1401
1402 ctrl_reg = rd32(E1000_CTRL); 1402 ctrl_reg = rd32(E1000_CTRL);
1403 1403
1404 /* force 1000, set loopback */ 1404 /* force 1000, set loopback */
1405 hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, 0x4140); 1405 igb_write_phy_reg(hw, PHY_CONTROL, 0x4140);
1406 1406
1407 /* Now set up the MAC to the same speed/duplex as the PHY. */ 1407 /* Now set up the MAC to the same speed/duplex as the PHY. */
1408 ctrl_reg = rd32(E1000_CTRL); 1408 ctrl_reg = rd32(E1000_CTRL);
@@ -1496,10 +1496,10 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter)
1496 wr32(E1000_RCTL, rctl); 1496 wr32(E1000_RCTL, rctl);
1497 1497
1498 hw->mac.autoneg = true; 1498 hw->mac.autoneg = true;
1499 hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_reg); 1499 igb_read_phy_reg(hw, PHY_CONTROL, &phy_reg);
1500 if (phy_reg & MII_CR_LOOPBACK) { 1500 if (phy_reg & MII_CR_LOOPBACK) {
1501 phy_reg &= ~MII_CR_LOOPBACK; 1501 phy_reg &= ~MII_CR_LOOPBACK;
1502 hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_reg); 1502 igb_write_phy_reg(hw, PHY_CONTROL, phy_reg);
1503 igb_phy_sw_reset(hw); 1503 igb_phy_sw_reset(hw);
1504 } 1504 }
1505} 1505}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index eca5684d5655..b64c41a44dfc 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -931,8 +931,7 @@ void igb_reset(struct igb_adapter *adapter)
931 wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); 931 wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
932 932
933 igb_reset_adaptive(&adapter->hw); 933 igb_reset_adaptive(&adapter->hw);
934 if (adapter->hw.phy.ops.get_phy_info) 934 igb_get_phy_info(&adapter->hw);
935 adapter->hw.phy.ops.get_phy_info(&adapter->hw);
936} 935}
937 936
938/** 937/**
@@ -1305,7 +1304,7 @@ err_register:
1305 igb_release_hw_control(adapter); 1304 igb_release_hw_control(adapter);
1306err_eeprom: 1305err_eeprom:
1307 if (!igb_check_reset_block(hw)) 1306 if (!igb_check_reset_block(hw))
1308 hw->phy.ops.reset_phy(hw); 1307 igb_reset_phy(hw);
1309 1308
1310 if (hw->flash_address) 1309 if (hw->flash_address)
1311 iounmap(hw->flash_address); 1310 iounmap(hw->flash_address);
@@ -1365,9 +1364,8 @@ static void __devexit igb_remove(struct pci_dev *pdev)
1365 1364
1366 unregister_netdev(netdev); 1365 unregister_netdev(netdev);
1367 1366
1368 if (adapter->hw.phy.ops.reset_phy && 1367 if (!igb_check_reset_block(&adapter->hw))
1369 !igb_check_reset_block(&adapter->hw)) 1368 igb_reset_phy(&adapter->hw);
1370 adapter->hw.phy.ops.reset_phy(&adapter->hw);
1371 1369
1372 igb_remove_device(&adapter->hw); 1370 igb_remove_device(&adapter->hw);
1373 igb_reset_interrupt_capability(adapter); 1371 igb_reset_interrupt_capability(adapter);
@@ -2283,8 +2281,7 @@ static void igb_set_multi(struct net_device *netdev)
2283static void igb_update_phy_info(unsigned long data) 2281static void igb_update_phy_info(unsigned long data)
2284{ 2282{
2285 struct igb_adapter *adapter = (struct igb_adapter *) data; 2283 struct igb_adapter *adapter = (struct igb_adapter *) data;
2286 if (adapter->hw.phy.ops.get_phy_info) 2284 igb_get_phy_info(&adapter->hw);
2287 adapter->hw.phy.ops.get_phy_info(&adapter->hw);
2288} 2285}
2289 2286
2290/** 2287/**
@@ -3258,7 +3255,7 @@ void igb_update_stats(struct igb_adapter *adapter)
3258 /* Phy Stats */ 3255 /* Phy Stats */
3259 if (hw->phy.media_type == e1000_media_type_copper) { 3256 if (hw->phy.media_type == e1000_media_type_copper) {
3260 if ((adapter->link_speed == SPEED_1000) && 3257 if ((adapter->link_speed == SPEED_1000) &&
3261 (!hw->phy.ops.read_phy_reg(hw, PHY_1000T_STATUS, 3258 (!igb_read_phy_reg(hw, PHY_1000T_STATUS,
3262 &phy_tmp))) { 3259 &phy_tmp))) {
3263 phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; 3260 phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
3264 adapter->phy_stats.idle_errors += phy_tmp; 3261 adapter->phy_stats.idle_errors += phy_tmp;
@@ -4111,9 +4108,8 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
4111 case SIOCGMIIREG: 4108 case SIOCGMIIREG:
4112 if (!capable(CAP_NET_ADMIN)) 4109 if (!capable(CAP_NET_ADMIN))
4113 return -EPERM; 4110 return -EPERM;
4114 if (adapter->hw.phy.ops.read_phy_reg(&adapter->hw, 4111 if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
4115 data->reg_num 4112 &data->val_out))
4116 & 0x1F, &data->val_out))
4117 return -EIO; 4113 return -EIO;
4118 break; 4114 break;
4119 case SIOCSMIIREG: 4115 case SIOCSMIIREG: