aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/igb/igb_ethtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/igb/igb_ethtool.c')
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c198
1 files changed, 125 insertions, 73 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 70591117051b..2ea012849825 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -148,9 +148,9 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
148 SUPPORTED_100baseT_Full | 148 SUPPORTED_100baseT_Full |
149 SUPPORTED_1000baseT_Full| 149 SUPPORTED_1000baseT_Full|
150 SUPPORTED_Autoneg | 150 SUPPORTED_Autoneg |
151 SUPPORTED_TP); 151 SUPPORTED_TP |
152 ecmd->advertising = (ADVERTISED_TP | 152 SUPPORTED_Pause);
153 ADVERTISED_Pause); 153 ecmd->advertising = ADVERTISED_TP;
154 154
155 if (hw->mac.autoneg == 1) { 155 if (hw->mac.autoneg == 1) {
156 ecmd->advertising |= ADVERTISED_Autoneg; 156 ecmd->advertising |= ADVERTISED_Autoneg;
@@ -158,6 +158,21 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
158 ecmd->advertising |= hw->phy.autoneg_advertised; 158 ecmd->advertising |= hw->phy.autoneg_advertised;
159 } 159 }
160 160
161 if (hw->mac.autoneg != 1)
162 ecmd->advertising &= ~(ADVERTISED_Pause |
163 ADVERTISED_Asym_Pause);
164
165 if (hw->fc.requested_mode == e1000_fc_full)
166 ecmd->advertising |= ADVERTISED_Pause;
167 else if (hw->fc.requested_mode == e1000_fc_rx_pause)
168 ecmd->advertising |= (ADVERTISED_Pause |
169 ADVERTISED_Asym_Pause);
170 else if (hw->fc.requested_mode == e1000_fc_tx_pause)
171 ecmd->advertising |= ADVERTISED_Asym_Pause;
172 else
173 ecmd->advertising &= ~(ADVERTISED_Pause |
174 ADVERTISED_Asym_Pause);
175
161 ecmd->port = PORT_TP; 176 ecmd->port = PORT_TP;
162 ecmd->phy_address = hw->phy.addr; 177 ecmd->phy_address = hw->phy.addr;
163 } else { 178 } else {
@@ -198,6 +213,19 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
198 } 213 }
199 214
200 ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; 215 ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
216
217 /* MDI-X => 2; MDI =>1; Invalid =>0 */
218 if (hw->phy.media_type == e1000_media_type_copper)
219 ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
220 ETH_TP_MDI;
221 else
222 ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
223
224 if (hw->phy.mdix == AUTO_ALL_MODES)
225 ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
226 else
227 ecmd->eth_tp_mdix_ctrl = hw->phy.mdix;
228
201 return 0; 229 return 0;
202} 230}
203 231
@@ -214,6 +242,22 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
214 return -EINVAL; 242 return -EINVAL;
215 } 243 }
216 244
245 /*
246 * MDI setting is only allowed when autoneg enabled because
247 * some hardware doesn't allow MDI setting when speed or
248 * duplex is forced.
249 */
250 if (ecmd->eth_tp_mdix_ctrl) {
251 if (hw->phy.media_type != e1000_media_type_copper)
252 return -EOPNOTSUPP;
253
254 if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) &&
255 (ecmd->autoneg != AUTONEG_ENABLE)) {
256 dev_err(&adapter->pdev->dev, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n");
257 return -EINVAL;
258 }
259 }
260
217 while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) 261 while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
218 msleep(1); 262 msleep(1);
219 263
@@ -227,12 +271,25 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
227 hw->fc.requested_mode = e1000_fc_default; 271 hw->fc.requested_mode = e1000_fc_default;
228 } else { 272 } else {
229 u32 speed = ethtool_cmd_speed(ecmd); 273 u32 speed = ethtool_cmd_speed(ecmd);
274 /* calling this overrides forced MDI setting */
230 if (igb_set_spd_dplx(adapter, speed, ecmd->duplex)) { 275 if (igb_set_spd_dplx(adapter, speed, ecmd->duplex)) {
231 clear_bit(__IGB_RESETTING, &adapter->state); 276 clear_bit(__IGB_RESETTING, &adapter->state);
232 return -EINVAL; 277 return -EINVAL;
233 } 278 }
234 } 279 }
235 280
281 /* MDI-X => 2; MDI => 1; Auto => 3 */
282 if (ecmd->eth_tp_mdix_ctrl) {
283 /*
284 * fix up the value for auto (3 => 0) as zero is mapped
285 * internally to auto
286 */
287 if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
288 hw->phy.mdix = AUTO_ALL_MODES;
289 else
290 hw->phy.mdix = ecmd->eth_tp_mdix_ctrl;
291 }
292
236 /* reset the link */ 293 /* reset the link */
237 if (netif_running(adapter->netdev)) { 294 if (netif_running(adapter->netdev)) {
238 igb_down(adapter); 295 igb_down(adapter);
@@ -1469,33 +1526,22 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
1469{ 1526{
1470 struct e1000_hw *hw = &adapter->hw; 1527 struct e1000_hw *hw = &adapter->hw;
1471 u32 ctrl_reg = 0; 1528 u32 ctrl_reg = 0;
1472 u16 phy_reg = 0;
1473 1529
1474 hw->mac.autoneg = false; 1530 hw->mac.autoneg = false;
1475 1531
1476 switch (hw->phy.type) { 1532 if (hw->phy.type == e1000_phy_m88) {
1477 case e1000_phy_m88: 1533 if (hw->phy.id != I210_I_PHY_ID) {
1478 /* Auto-MDI/MDIX Off */ 1534 /* Auto-MDI/MDIX Off */
1479 igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); 1535 igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
1480 /* reset to update Auto-MDI/MDIX */ 1536 /* reset to update Auto-MDI/MDIX */
1481 igb_write_phy_reg(hw, PHY_CONTROL, 0x9140); 1537 igb_write_phy_reg(hw, PHY_CONTROL, 0x9140);
1482 /* autoneg off */ 1538 /* autoneg off */
1483 igb_write_phy_reg(hw, PHY_CONTROL, 0x8140); 1539 igb_write_phy_reg(hw, PHY_CONTROL, 0x8140);
1484 break; 1540 } else {
1485 case e1000_phy_82580: 1541 /* force 1000, set loopback */
1486 /* enable MII loopback */ 1542 igb_write_phy_reg(hw, I347AT4_PAGE_SELECT, 0);
1487 igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041); 1543 igb_write_phy_reg(hw, PHY_CONTROL, 0x4140);
1488 break; 1544 }
1489 case e1000_phy_i210:
1490 /* set loopback speed in PHY */
1491 igb_read_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2),
1492 &phy_reg);
1493 phy_reg |= GS40G_MAC_SPEED_1G;
1494 igb_write_phy_reg(hw, (GS40G_PAGE_SELECT & GS40G_PAGE_2),
1495 phy_reg);
1496 ctrl_reg = rd32(E1000_CTRL_EXT);
1497 default:
1498 break;
1499 } 1545 }
1500 1546
1501 /* add small delay to avoid loopback test failure */ 1547 /* add small delay to avoid loopback test failure */
@@ -1513,7 +1559,7 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
1513 E1000_CTRL_FD | /* Force Duplex to FULL */ 1559 E1000_CTRL_FD | /* Force Duplex to FULL */
1514 E1000_CTRL_SLU); /* Set link up enable bit */ 1560 E1000_CTRL_SLU); /* Set link up enable bit */
1515 1561
1516 if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210)) 1562 if (hw->phy.type == e1000_phy_m88)
1517 ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ 1563 ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
1518 1564
1519 wr32(E1000_CTRL, ctrl_reg); 1565 wr32(E1000_CTRL, ctrl_reg);
@@ -1521,11 +1567,10 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
1521 /* Disable the receiver on the PHY so when a cable is plugged in, the 1567 /* Disable the receiver on the PHY so when a cable is plugged in, the
1522 * PHY does not begin to autoneg when a cable is reconnected to the NIC. 1568 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
1523 */ 1569 */
1524 if ((hw->phy.type == e1000_phy_m88) || (hw->phy.type == e1000_phy_i210)) 1570 if (hw->phy.type == e1000_phy_m88)
1525 igb_phy_disable_receiver(adapter); 1571 igb_phy_disable_receiver(adapter);
1526 1572
1527 udelay(500); 1573 mdelay(500);
1528
1529 return 0; 1574 return 0;
1530} 1575}
1531 1576
@@ -1785,13 +1830,6 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data)
1785 *data = 0; 1830 *data = 0;
1786 goto out; 1831 goto out;
1787 } 1832 }
1788 if ((adapter->hw.mac.type == e1000_i210)
1789 || (adapter->hw.mac.type == e1000_i211)) {
1790 dev_err(&adapter->pdev->dev,
1791 "Loopback test not supported on this part at this time.\n");
1792 *data = 0;
1793 goto out;
1794 }
1795 *data = igb_setup_desc_rings(adapter); 1833 *data = igb_setup_desc_rings(adapter);
1796 if (*data) 1834 if (*data)
1797 goto out; 1835 goto out;
@@ -2257,6 +2295,54 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
2257 } 2295 }
2258} 2296}
2259 2297
2298static int igb_get_ts_info(struct net_device *dev,
2299 struct ethtool_ts_info *info)
2300{
2301 struct igb_adapter *adapter = netdev_priv(dev);
2302
2303 switch (adapter->hw.mac.type) {
2304#ifdef CONFIG_IGB_PTP
2305 case e1000_82576:
2306 case e1000_82580:
2307 case e1000_i350:
2308 case e1000_i210:
2309 case e1000_i211:
2310 info->so_timestamping =
2311 SOF_TIMESTAMPING_TX_HARDWARE |
2312 SOF_TIMESTAMPING_RX_HARDWARE |
2313 SOF_TIMESTAMPING_RAW_HARDWARE;
2314
2315 if (adapter->ptp_clock)
2316 info->phc_index = ptp_clock_index(adapter->ptp_clock);
2317 else
2318 info->phc_index = -1;
2319
2320 info->tx_types =
2321 (1 << HWTSTAMP_TX_OFF) |
2322 (1 << HWTSTAMP_TX_ON);
2323
2324 info->rx_filters = 1 << HWTSTAMP_FILTER_NONE;
2325
2326 /* 82576 does not support timestamping all packets. */
2327 if (adapter->hw.mac.type >= e1000_82580)
2328 info->rx_filters |= 1 << HWTSTAMP_FILTER_ALL;
2329 else
2330 info->rx_filters |=
2331 (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
2332 (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
2333 (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
2334 (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
2335 (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
2336 (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
2337 (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
2338
2339 return 0;
2340#endif /* CONFIG_IGB_PTP */
2341 default:
2342 return -EOPNOTSUPP;
2343 }
2344}
2345
2260static int igb_ethtool_begin(struct net_device *netdev) 2346static int igb_ethtool_begin(struct net_device *netdev)
2261{ 2347{
2262 struct igb_adapter *adapter = netdev_priv(netdev); 2348 struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2270,38 +2356,6 @@ static void igb_ethtool_complete(struct net_device *netdev)
2270 pm_runtime_put(&adapter->pdev->dev); 2356 pm_runtime_put(&adapter->pdev->dev);
2271} 2357}
2272 2358
2273#ifdef CONFIG_IGB_PTP
2274static int igb_ethtool_get_ts_info(struct net_device *dev,
2275 struct ethtool_ts_info *info)
2276{
2277 struct igb_adapter *adapter = netdev_priv(dev);
2278
2279 info->so_timestamping =
2280 SOF_TIMESTAMPING_TX_HARDWARE |
2281 SOF_TIMESTAMPING_RX_HARDWARE |
2282 SOF_TIMESTAMPING_RAW_HARDWARE;
2283
2284 if (adapter->ptp_clock)
2285 info->phc_index = ptp_clock_index(adapter->ptp_clock);
2286 else
2287 info->phc_index = -1;
2288
2289 info->tx_types =
2290 (1 << HWTSTAMP_TX_OFF) |
2291 (1 << HWTSTAMP_TX_ON);
2292
2293 info->rx_filters =
2294 (1 << HWTSTAMP_FILTER_NONE) |
2295 (1 << HWTSTAMP_FILTER_ALL) |
2296 (1 << HWTSTAMP_FILTER_SOME) |
2297 (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
2298 (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
2299 (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
2300
2301 return 0;
2302}
2303
2304#endif
2305static const struct ethtool_ops igb_ethtool_ops = { 2359static const struct ethtool_ops igb_ethtool_ops = {
2306 .get_settings = igb_get_settings, 2360 .get_settings = igb_get_settings,
2307 .set_settings = igb_set_settings, 2361 .set_settings = igb_set_settings,
@@ -2328,11 +2382,9 @@ static const struct ethtool_ops igb_ethtool_ops = {
2328 .get_ethtool_stats = igb_get_ethtool_stats, 2382 .get_ethtool_stats = igb_get_ethtool_stats,
2329 .get_coalesce = igb_get_coalesce, 2383 .get_coalesce = igb_get_coalesce,
2330 .set_coalesce = igb_set_coalesce, 2384 .set_coalesce = igb_set_coalesce,
2385 .get_ts_info = igb_get_ts_info,
2331 .begin = igb_ethtool_begin, 2386 .begin = igb_ethtool_begin,
2332 .complete = igb_ethtool_complete, 2387 .complete = igb_ethtool_complete,
2333#ifdef CONFIG_IGB_PTP
2334 .get_ts_info = igb_ethtool_get_ts_info,
2335#endif
2336}; 2388};
2337 2389
2338void igb_set_ethtool_ops(struct net_device *netdev) 2390void igb_set_ethtool_ops(struct net_device *netdev)