aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c13
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h5
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_hw.h1
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h10
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c193
6 files changed, 226 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index fe9db48f9084..06df6928f44c 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -441,6 +441,19 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw)
441 ? igb_setup_copper_link_82575 441 ? igb_setup_copper_link_82575
442 : igb_setup_serdes_link_82575; 442 : igb_setup_serdes_link_82575;
443 443
444 if (mac->type == e1000_82580) {
445 switch (hw->device_id) {
446 /* feature not supported on these id's */
447 case E1000_DEV_ID_DH89XXCC_SGMII:
448 case E1000_DEV_ID_DH89XXCC_SERDES:
449 case E1000_DEV_ID_DH89XXCC_BACKPLANE:
450 case E1000_DEV_ID_DH89XXCC_SFP:
451 break;
452 default:
453 hw->dev_spec._82575.mas_capable = true;
454 break;
455 }
456 }
444 return 0; 457 return 0;
445} 458}
446 459
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 378ca21aa647..0571b973be80 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -205,6 +205,11 @@
205 */ 205 */
206 206
207#define E1000_CONNSW_ENRGSRC 0x4 207#define E1000_CONNSW_ENRGSRC 0x4
208#define E1000_CONNSW_PHYSD 0x400
209#define E1000_CONNSW_PHY_PDN 0x800
210#define E1000_CONNSW_SERDESD 0x200
211#define E1000_CONNSW_AUTOSENSE_CONF 0x2
212#define E1000_CONNSW_AUTOSENSE_EN 0x1
208#define E1000_PCS_CFG_PCS_EN 8 213#define E1000_PCS_CFG_PCS_EN 8
209#define E1000_PCS_LCTL_FLV_LINK_UP 1 214#define E1000_PCS_LCTL_FLV_LINK_UP 1
210#define E1000_PCS_LCTL_FSV_100 2 215#define E1000_PCS_LCTL_FSV_100 2
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index 5f9758f3206e..ab99e2b582a8 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -535,6 +535,7 @@ struct e1000_dev_spec_82575 {
535 bool module_plugged; 535 bool module_plugged;
536 u8 media_port; 536 u8 media_port;
537 bool media_changed; 537 bool media_changed;
538 bool mas_capable;
538}; 539};
539 540
540struct e1000_hw { 541struct e1000_hw {
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 6c807927171f..11173f46f436 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -450,6 +450,8 @@ struct igb_adapter {
450 u8 rss_indir_tbl[IGB_RETA_SIZE]; 450 u8 rss_indir_tbl[IGB_RETA_SIZE];
451 451
452 unsigned long link_check_timeout; 452 unsigned long link_check_timeout;
453 int copper_tries;
454 struct e1000_info ei;
453}; 455};
454 456
455#define IGB_FLAG_HAS_MSI (1 << 0) 457#define IGB_FLAG_HAS_MSI (1 << 0)
@@ -463,6 +465,14 @@ struct igb_adapter {
463#define IGB_FLAG_WOL_SUPPORTED (1 << 8) 465#define IGB_FLAG_WOL_SUPPORTED (1 << 8)
464#define IGB_FLAG_NEED_LINK_UPDATE (1 << 9) 466#define IGB_FLAG_NEED_LINK_UPDATE (1 << 9)
465#define IGB_FLAG_MEDIA_RESET (1 << 10) 467#define IGB_FLAG_MEDIA_RESET (1 << 10)
468#define IGB_FLAG_MAS_CAPABLE (1 << 11)
469#define IGB_FLAG_MAS_ENABLE (1 << 12)
470
471/* Media Auto Sense */
472#define IGB_MAS_ENABLE_0 0X0001
473#define IGB_MAS_ENABLE_1 0X0002
474#define IGB_MAS_ENABLE_2 0X0004
475#define IGB_MAS_ENABLE_3 0X0008
466 476
467/* DMA Coalescing defines */ 477/* DMA Coalescing defines */
468#define IGB_MIN_TXPBSIZE 20408 478#define IGB_MIN_TXPBSIZE 20408
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index c3143da497c8..1c7d2381af8c 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -1983,6 +1983,10 @@ static void igb_diag_test(struct net_device *netdev,
1983 bool if_running = netif_running(netdev); 1983 bool if_running = netif_running(netdev);
1984 1984
1985 set_bit(__IGB_TESTING, &adapter->state); 1985 set_bit(__IGB_TESTING, &adapter->state);
1986
1987 /* can't do offline tests on media switching devices */
1988 if (adapter->hw.dev_spec._82575.mas_capable)
1989 eth_test->flags &= ~ETH_TEST_FL_OFFLINE;
1986 if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 1990 if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
1987 /* Offline tests */ 1991 /* Offline tests */
1988 1992
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index ed129f1c5c3e..3bc10bd5bbc1 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -1607,6 +1607,73 @@ static void igb_power_down_link(struct igb_adapter *adapter)
1607} 1607}
1608 1608
1609/** 1609/**
1610 * Detect and switch function for Media Auto Sense
1611 * @adapter: address of the board private structure
1612 **/
1613static void igb_check_swap_media(struct igb_adapter *adapter)
1614{
1615 struct e1000_hw *hw = &adapter->hw;
1616 u32 ctrl_ext, connsw;
1617 bool swap_now = false;
1618
1619 ctrl_ext = rd32(E1000_CTRL_EXT);
1620 connsw = rd32(E1000_CONNSW);
1621
1622 /* need to live swap if current media is copper and we have fiber/serdes
1623 * to go to.
1624 */
1625
1626 if ((hw->phy.media_type == e1000_media_type_copper) &&
1627 (!(connsw & E1000_CONNSW_AUTOSENSE_EN))) {
1628 swap_now = true;
1629 } else if (!(connsw & E1000_CONNSW_SERDESD)) {
1630 /* copper signal takes time to appear */
1631 if (adapter->copper_tries < 4) {
1632 adapter->copper_tries++;
1633 connsw |= E1000_CONNSW_AUTOSENSE_CONF;
1634 wr32(E1000_CONNSW, connsw);
1635 return;
1636 } else {
1637 adapter->copper_tries = 0;
1638 if ((connsw & E1000_CONNSW_PHYSD) &&
1639 (!(connsw & E1000_CONNSW_PHY_PDN))) {
1640 swap_now = true;
1641 connsw &= ~E1000_CONNSW_AUTOSENSE_CONF;
1642 wr32(E1000_CONNSW, connsw);
1643 }
1644 }
1645 }
1646
1647 if (!swap_now)
1648 return;
1649
1650 switch (hw->phy.media_type) {
1651 case e1000_media_type_copper:
1652 netdev_info(adapter->netdev,
1653 "MAS: changing media to fiber/serdes\n");
1654 ctrl_ext |=
1655 E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
1656 adapter->flags |= IGB_FLAG_MEDIA_RESET;
1657 adapter->copper_tries = 0;
1658 break;
1659 case e1000_media_type_internal_serdes:
1660 case e1000_media_type_fiber:
1661 netdev_info(adapter->netdev,
1662 "MAS: changing media to copper\n");
1663 ctrl_ext &=
1664 ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
1665 adapter->flags |= IGB_FLAG_MEDIA_RESET;
1666 break;
1667 default:
1668 /* shouldn't get here during regular operation */
1669 netdev_err(adapter->netdev,
1670 "AMS: Invalid media type found, returning\n");
1671 break;
1672 }
1673 wr32(E1000_CTRL_EXT, ctrl_ext);
1674}
1675
1676/**
1610 * igb_up - Open the interface and prepare it to handle traffic 1677 * igb_up - Open the interface and prepare it to handle traffic
1611 * @adapter: board private structure 1678 * @adapter: board private structure
1612 **/ 1679 **/
@@ -1719,6 +1786,37 @@ void igb_reinit_locked(struct igb_adapter *adapter)
1719 clear_bit(__IGB_RESETTING, &adapter->state); 1786 clear_bit(__IGB_RESETTING, &adapter->state);
1720} 1787}
1721 1788
1789/** igb_enable_mas - Media Autosense re-enable after swap
1790 *
1791 * @adapter: adapter struct
1792 **/
1793static s32 igb_enable_mas(struct igb_adapter *adapter)
1794{
1795 struct e1000_hw *hw = &adapter->hw;
1796 u32 connsw;
1797 s32 ret_val = 0;
1798
1799 connsw = rd32(E1000_CONNSW);
1800 if (!(hw->phy.media_type == e1000_media_type_copper))
1801 return ret_val;
1802
1803 /* configure for SerDes media detect */
1804 if (!(connsw & E1000_CONNSW_SERDESD)) {
1805 connsw |= E1000_CONNSW_ENRGSRC;
1806 connsw |= E1000_CONNSW_AUTOSENSE_EN;
1807 wr32(E1000_CONNSW, connsw);
1808 wrfl();
1809 } else if (connsw & E1000_CONNSW_SERDESD) {
1810 /* already SerDes, no need to enable anything */
1811 return ret_val;
1812 } else {
1813 netdev_info(adapter->netdev,
1814 "MAS: Unable to configure feature, disabling..\n");
1815 adapter->flags &= ~IGB_FLAG_MAS_ENABLE;
1816 }
1817 return ret_val;
1818}
1819
1722void igb_reset(struct igb_adapter *adapter) 1820void igb_reset(struct igb_adapter *adapter)
1723{ 1821{
1724 struct pci_dev *pdev = adapter->pdev; 1822 struct pci_dev *pdev = adapter->pdev;
@@ -1830,6 +1928,16 @@ void igb_reset(struct igb_adapter *adapter)
1830 hw->mac.ops.reset_hw(hw); 1928 hw->mac.ops.reset_hw(hw);
1831 wr32(E1000_WUC, 0); 1929 wr32(E1000_WUC, 0);
1832 1930
1931 if (adapter->flags & IGB_FLAG_MEDIA_RESET) {
1932 /* need to resetup here after media swap */
1933 adapter->ei.get_invariants(hw);
1934 adapter->flags &= ~IGB_FLAG_MEDIA_RESET;
1935 }
1936 if (adapter->flags & IGB_FLAG_MAS_ENABLE) {
1937 if (igb_enable_mas(adapter))
1938 dev_err(&pdev->dev,
1939 "Error enabling Media Auto Sense\n");
1940 }
1833 if (hw->mac.ops.init_hw(hw)) 1941 if (hw->mac.ops.init_hw(hw))
1834 dev_err(&pdev->dev, "Hardware Error\n"); 1942 dev_err(&pdev->dev, "Hardware Error\n");
1835 1943
@@ -1976,6 +2084,58 @@ void igb_set_fw_version(struct igb_adapter *adapter)
1976} 2084}
1977 2085
1978/** 2086/**
2087 * igb_init_mas - init Media Autosense feature if enabled in the NVM
2088 *
2089 * @adapter: adapter struct
2090 **/
2091static void igb_init_mas(struct igb_adapter *adapter)
2092{
2093 struct e1000_hw *hw = &adapter->hw;
2094 u16 eeprom_data;
2095
2096 hw->nvm.ops.read(hw, NVM_COMPAT, 1, &eeprom_data);
2097 switch (hw->bus.func) {
2098 case E1000_FUNC_0:
2099 if (eeprom_data & IGB_MAS_ENABLE_0) {
2100 adapter->flags |= IGB_FLAG_MAS_ENABLE;
2101 netdev_info(adapter->netdev,
2102 "MAS: Enabling Media Autosense for port %d\n",
2103 hw->bus.func);
2104 }
2105 break;
2106 case E1000_FUNC_1:
2107 if (eeprom_data & IGB_MAS_ENABLE_1) {
2108 adapter->flags |= IGB_FLAG_MAS_ENABLE;
2109 netdev_info(adapter->netdev,
2110 "MAS: Enabling Media Autosense for port %d\n",
2111 hw->bus.func);
2112 }
2113 break;
2114 case E1000_FUNC_2:
2115 if (eeprom_data & IGB_MAS_ENABLE_2) {
2116 adapter->flags |= IGB_FLAG_MAS_ENABLE;
2117 netdev_info(adapter->netdev,
2118 "MAS: Enabling Media Autosense for port %d\n",
2119 hw->bus.func);
2120 }
2121 break;
2122 case E1000_FUNC_3:
2123 if (eeprom_data & IGB_MAS_ENABLE_3) {
2124 adapter->flags |= IGB_FLAG_MAS_ENABLE;
2125 netdev_info(adapter->netdev,
2126 "MAS: Enabling Media Autosense for port %d\n",
2127 hw->bus.func);
2128 }
2129 break;
2130 default:
2131 /* Shouldn't get here */
2132 netdev_err(adapter->netdev,
2133 "MAS: Invalid port configuration, returning\n");
2134 break;
2135 }
2136}
2137
2138/**
1979 * igb_init_i2c - Init I2C interface 2139 * igb_init_i2c - Init I2C interface
1980 * @adapter: pointer to adapter structure 2140 * @adapter: pointer to adapter structure
1981 **/ 2141 **/
@@ -2346,6 +2506,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2346 adapter->ets = false; 2506 adapter->ets = false;
2347 } 2507 }
2348#endif 2508#endif
2509 /* Check if Media Autosense is enabled */
2510 adapter->ei = *ei;
2511 if (hw->dev_spec._82575.mas_capable)
2512 igb_init_mas(adapter);
2513
2349 /* do hw tstamp init after resetting */ 2514 /* do hw tstamp init after resetting */
2350 igb_ptp_init(adapter); 2515 igb_ptp_init(adapter);
2351 2516
@@ -3931,6 +4096,7 @@ static void igb_watchdog_task(struct work_struct *work)
3931 struct net_device *netdev = adapter->netdev; 4096 struct net_device *netdev = adapter->netdev;
3932 u32 link; 4097 u32 link;
3933 int i; 4098 int i;
4099 u32 connsw;
3934 4100
3935 link = igb_has_link(adapter); 4101 link = igb_has_link(adapter);
3936 4102
@@ -3941,6 +4107,14 @@ static void igb_watchdog_task(struct work_struct *work)
3941 link = false; 4107 link = false;
3942 } 4108 }
3943 4109
4110 /* Force link down if we have fiber to swap to */
4111 if (adapter->flags & IGB_FLAG_MAS_ENABLE) {
4112 if (hw->phy.media_type == e1000_media_type_copper) {
4113 connsw = rd32(E1000_CONNSW);
4114 if (!(connsw & E1000_CONNSW_AUTOSENSE_EN))
4115 link = 0;
4116 }
4117 }
3944 if (link) { 4118 if (link) {
3945 /* Perform a reset if the media type changed. */ 4119 /* Perform a reset if the media type changed. */
3946 if (hw->dev_spec._82575.media_changed) { 4120 if (hw->dev_spec._82575.media_changed) {
@@ -4028,8 +4202,27 @@ static void igb_watchdog_task(struct work_struct *work)
4028 mod_timer(&adapter->phy_info_timer, 4202 mod_timer(&adapter->phy_info_timer,
4029 round_jiffies(jiffies + 2 * HZ)); 4203 round_jiffies(jiffies + 2 * HZ));
4030 4204
4205 /* link is down, time to check for alternate media */
4206 if (adapter->flags & IGB_FLAG_MAS_ENABLE) {
4207 igb_check_swap_media(adapter);
4208 if (adapter->flags & IGB_FLAG_MEDIA_RESET) {
4209 schedule_work(&adapter->reset_task);
4210 /* return immediately */
4211 return;
4212 }
4213 }
4031 pm_schedule_suspend(netdev->dev.parent, 4214 pm_schedule_suspend(netdev->dev.parent,
4032 MSEC_PER_SEC * 5); 4215 MSEC_PER_SEC * 5);
4216
4217 /* also check for alternate media here */
4218 } else if (!netif_carrier_ok(netdev) &&
4219 (adapter->flags & IGB_FLAG_MAS_ENABLE)) {
4220 igb_check_swap_media(adapter);
4221 if (adapter->flags & IGB_FLAG_MEDIA_RESET) {
4222 schedule_work(&adapter->reset_task);
4223 /* return immediately */
4224 return;
4225 }
4033 } 4226 }
4034 } 4227 }
4035 4228