diff options
author | David S. Miller <davem@davemloft.net> | 2018-04-23 21:24:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-23 21:24:23 -0400 |
commit | 6cd968f4481437e6a8194b5e028000310ffe5ce2 (patch) | |
tree | dd2873463ce6a30e76bfac45dd2bc6c9ef74b253 | |
parent | a49e2f5d5fb141884452ddb428f551b123d436b5 (diff) | |
parent | 117df655f8ed51adb6e6b163812a06ebeae9f453 (diff) |
Merge branch 'amd-xgbe-fixes'
aTom Lendacky says:
====================
amd-xgbe: AMD XGBE driver fixes 2018-04-23
This patch series addresses some issues in the AMD XGBE driver.
The following fixes are included in this driver update series:
- Improve KR auto-negotiation and training (2 patches)
- Add pre and post auto-negotiation hooks
- Use the pre and post auto-negotiation hooks to disable CDR tracking
during auto-negotiation page exchange in KR mode
- Check for SFP tranceiver signal support and only use the signal if the
SFP indicates that it is supported
This patch series is based on net.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-common.h | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-main.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 24 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 196 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe.h | 9 |
7 files changed, 233 insertions, 23 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 7ea72ef11a55..d272dc6984ac 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h | |||
@@ -1321,6 +1321,10 @@ | |||
1321 | #define MDIO_VEND2_AN_STAT 0x8002 | 1321 | #define MDIO_VEND2_AN_STAT 0x8002 |
1322 | #endif | 1322 | #endif |
1323 | 1323 | ||
1324 | #ifndef MDIO_VEND2_PMA_CDR_CONTROL | ||
1325 | #define MDIO_VEND2_PMA_CDR_CONTROL 0x8056 | ||
1326 | #endif | ||
1327 | |||
1324 | #ifndef MDIO_CTRL1_SPEED1G | 1328 | #ifndef MDIO_CTRL1_SPEED1G |
1325 | #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) | 1329 | #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) |
1326 | #endif | 1330 | #endif |
@@ -1369,6 +1373,10 @@ | |||
1369 | #define XGBE_AN_CL37_TX_CONFIG_MASK 0x08 | 1373 | #define XGBE_AN_CL37_TX_CONFIG_MASK 0x08 |
1370 | #define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100 | 1374 | #define XGBE_AN_CL37_MII_CTRL_8BIT 0x0100 |
1371 | 1375 | ||
1376 | #define XGBE_PMA_CDR_TRACK_EN_MASK 0x01 | ||
1377 | #define XGBE_PMA_CDR_TRACK_EN_OFF 0x00 | ||
1378 | #define XGBE_PMA_CDR_TRACK_EN_ON 0x01 | ||
1379 | |||
1372 | /* Bit setting and getting macros | 1380 | /* Bit setting and getting macros |
1373 | * The get macro will extract the current bit field value from within | 1381 | * The get macro will extract the current bit field value from within |
1374 | * the variable | 1382 | * the variable |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c index 7d128be61310..b91143947ed2 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | |||
@@ -519,6 +519,22 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata) | |||
519 | "debugfs_create_file failed\n"); | 519 | "debugfs_create_file failed\n"); |
520 | } | 520 | } |
521 | 521 | ||
522 | if (pdata->vdata->an_cdr_workaround) { | ||
523 | pfile = debugfs_create_bool("an_cdr_workaround", 0600, | ||
524 | pdata->xgbe_debugfs, | ||
525 | &pdata->debugfs_an_cdr_workaround); | ||
526 | if (!pfile) | ||
527 | netdev_err(pdata->netdev, | ||
528 | "debugfs_create_bool failed\n"); | ||
529 | |||
530 | pfile = debugfs_create_bool("an_cdr_track_early", 0600, | ||
531 | pdata->xgbe_debugfs, | ||
532 | &pdata->debugfs_an_cdr_track_early); | ||
533 | if (!pfile) | ||
534 | netdev_err(pdata->netdev, | ||
535 | "debugfs_create_bool failed\n"); | ||
536 | } | ||
537 | |||
522 | kfree(buf); | 538 | kfree(buf); |
523 | } | 539 | } |
524 | 540 | ||
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 795e556d4a3f..441d0973957b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c | |||
@@ -349,6 +349,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) | |||
349 | XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); | 349 | XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1); |
350 | 350 | ||
351 | /* Call MDIO/PHY initialization routine */ | 351 | /* Call MDIO/PHY initialization routine */ |
352 | pdata->debugfs_an_cdr_workaround = pdata->vdata->an_cdr_workaround; | ||
352 | ret = pdata->phy_if.phy_init(pdata); | 353 | ret = pdata->phy_if.phy_init(pdata); |
353 | if (ret) | 354 | if (ret) |
354 | return ret; | 355 | return ret; |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 072b9f664597..1b45cd73a258 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | |||
@@ -432,11 +432,16 @@ static void xgbe_an73_disable(struct xgbe_prv_data *pdata) | |||
432 | xgbe_an73_set(pdata, false, false); | 432 | xgbe_an73_set(pdata, false, false); |
433 | xgbe_an73_disable_interrupts(pdata); | 433 | xgbe_an73_disable_interrupts(pdata); |
434 | 434 | ||
435 | pdata->an_start = 0; | ||
436 | |||
435 | netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n"); | 437 | netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n"); |
436 | } | 438 | } |
437 | 439 | ||
438 | static void xgbe_an_restart(struct xgbe_prv_data *pdata) | 440 | static void xgbe_an_restart(struct xgbe_prv_data *pdata) |
439 | { | 441 | { |
442 | if (pdata->phy_if.phy_impl.an_pre) | ||
443 | pdata->phy_if.phy_impl.an_pre(pdata); | ||
444 | |||
440 | switch (pdata->an_mode) { | 445 | switch (pdata->an_mode) { |
441 | case XGBE_AN_MODE_CL73: | 446 | case XGBE_AN_MODE_CL73: |
442 | case XGBE_AN_MODE_CL73_REDRV: | 447 | case XGBE_AN_MODE_CL73_REDRV: |
@@ -453,6 +458,9 @@ static void xgbe_an_restart(struct xgbe_prv_data *pdata) | |||
453 | 458 | ||
454 | static void xgbe_an_disable(struct xgbe_prv_data *pdata) | 459 | static void xgbe_an_disable(struct xgbe_prv_data *pdata) |
455 | { | 460 | { |
461 | if (pdata->phy_if.phy_impl.an_post) | ||
462 | pdata->phy_if.phy_impl.an_post(pdata); | ||
463 | |||
456 | switch (pdata->an_mode) { | 464 | switch (pdata->an_mode) { |
457 | case XGBE_AN_MODE_CL73: | 465 | case XGBE_AN_MODE_CL73: |
458 | case XGBE_AN_MODE_CL73_REDRV: | 466 | case XGBE_AN_MODE_CL73_REDRV: |
@@ -505,11 +513,11 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata, | |||
505 | XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, | 513 | XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, |
506 | reg); | 514 | reg); |
507 | 515 | ||
508 | if (pdata->phy_if.phy_impl.kr_training_post) | ||
509 | pdata->phy_if.phy_impl.kr_training_post(pdata); | ||
510 | |||
511 | netif_dbg(pdata, link, pdata->netdev, | 516 | netif_dbg(pdata, link, pdata->netdev, |
512 | "KR training initiated\n"); | 517 | "KR training initiated\n"); |
518 | |||
519 | if (pdata->phy_if.phy_impl.kr_training_post) | ||
520 | pdata->phy_if.phy_impl.kr_training_post(pdata); | ||
513 | } | 521 | } |
514 | 522 | ||
515 | return XGBE_AN_PAGE_RECEIVED; | 523 | return XGBE_AN_PAGE_RECEIVED; |
@@ -637,11 +645,11 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata) | |||
637 | return XGBE_AN_NO_LINK; | 645 | return XGBE_AN_NO_LINK; |
638 | } | 646 | } |
639 | 647 | ||
640 | xgbe_an73_disable(pdata); | 648 | xgbe_an_disable(pdata); |
641 | 649 | ||
642 | xgbe_switch_mode(pdata); | 650 | xgbe_switch_mode(pdata); |
643 | 651 | ||
644 | xgbe_an73_restart(pdata); | 652 | xgbe_an_restart(pdata); |
645 | 653 | ||
646 | return XGBE_AN_INCOMPAT_LINK; | 654 | return XGBE_AN_INCOMPAT_LINK; |
647 | } | 655 | } |
@@ -820,6 +828,9 @@ static void xgbe_an37_state_machine(struct xgbe_prv_data *pdata) | |||
820 | pdata->an_result = pdata->an_state; | 828 | pdata->an_result = pdata->an_state; |
821 | pdata->an_state = XGBE_AN_READY; | 829 | pdata->an_state = XGBE_AN_READY; |
822 | 830 | ||
831 | if (pdata->phy_if.phy_impl.an_post) | ||
832 | pdata->phy_if.phy_impl.an_post(pdata); | ||
833 | |||
823 | netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n", | 834 | netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n", |
824 | xgbe_state_as_string(pdata->an_result)); | 835 | xgbe_state_as_string(pdata->an_result)); |
825 | } | 836 | } |
@@ -903,6 +914,9 @@ again: | |||
903 | pdata->kx_state = XGBE_RX_BPA; | 914 | pdata->kx_state = XGBE_RX_BPA; |
904 | pdata->an_start = 0; | 915 | pdata->an_start = 0; |
905 | 916 | ||
917 | if (pdata->phy_if.phy_impl.an_post) | ||
918 | pdata->phy_if.phy_impl.an_post(pdata); | ||
919 | |||
906 | netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n", | 920 | netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n", |
907 | xgbe_state_as_string(pdata->an_result)); | 921 | xgbe_state_as_string(pdata->an_result)); |
908 | } | 922 | } |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c index eb23f9ba1a9a..82d1f416ee2a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c | |||
@@ -456,6 +456,7 @@ static const struct xgbe_version_data xgbe_v2a = { | |||
456 | .irq_reissue_support = 1, | 456 | .irq_reissue_support = 1, |
457 | .tx_desc_prefetch = 5, | 457 | .tx_desc_prefetch = 5, |
458 | .rx_desc_prefetch = 5, | 458 | .rx_desc_prefetch = 5, |
459 | .an_cdr_workaround = 1, | ||
459 | }; | 460 | }; |
460 | 461 | ||
461 | static const struct xgbe_version_data xgbe_v2b = { | 462 | static const struct xgbe_version_data xgbe_v2b = { |
@@ -470,6 +471,7 @@ static const struct xgbe_version_data xgbe_v2b = { | |||
470 | .irq_reissue_support = 1, | 471 | .irq_reissue_support = 1, |
471 | .tx_desc_prefetch = 5, | 472 | .tx_desc_prefetch = 5, |
472 | .rx_desc_prefetch = 5, | 473 | .rx_desc_prefetch = 5, |
474 | .an_cdr_workaround = 1, | ||
473 | }; | 475 | }; |
474 | 476 | ||
475 | static const struct pci_device_id xgbe_pci_table[] = { | 477 | static const struct pci_device_id xgbe_pci_table[] = { |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 3304a291aa96..aac884314000 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | |||
@@ -147,6 +147,14 @@ | |||
147 | /* Rate-change complete wait/retry count */ | 147 | /* Rate-change complete wait/retry count */ |
148 | #define XGBE_RATECHANGE_COUNT 500 | 148 | #define XGBE_RATECHANGE_COUNT 500 |
149 | 149 | ||
150 | /* CDR delay values for KR support (in usec) */ | ||
151 | #define XGBE_CDR_DELAY_INIT 10000 | ||
152 | #define XGBE_CDR_DELAY_INC 10000 | ||
153 | #define XGBE_CDR_DELAY_MAX 100000 | ||
154 | |||
155 | /* RRC frequency during link status check */ | ||
156 | #define XGBE_RRC_FREQUENCY 10 | ||
157 | |||
150 | enum xgbe_port_mode { | 158 | enum xgbe_port_mode { |
151 | XGBE_PORT_MODE_RSVD = 0, | 159 | XGBE_PORT_MODE_RSVD = 0, |
152 | XGBE_PORT_MODE_BACKPLANE, | 160 | XGBE_PORT_MODE_BACKPLANE, |
@@ -245,6 +253,10 @@ enum xgbe_sfp_speed { | |||
245 | #define XGBE_SFP_BASE_VENDOR_SN 4 | 253 | #define XGBE_SFP_BASE_VENDOR_SN 4 |
246 | #define XGBE_SFP_BASE_VENDOR_SN_LEN 16 | 254 | #define XGBE_SFP_BASE_VENDOR_SN_LEN 16 |
247 | 255 | ||
256 | #define XGBE_SFP_EXTD_OPT1 1 | ||
257 | #define XGBE_SFP_EXTD_OPT1_RX_LOS BIT(1) | ||
258 | #define XGBE_SFP_EXTD_OPT1_TX_FAULT BIT(3) | ||
259 | |||
248 | #define XGBE_SFP_EXTD_DIAG 28 | 260 | #define XGBE_SFP_EXTD_DIAG 28 |
249 | #define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2) | 261 | #define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2) |
250 | 262 | ||
@@ -324,6 +336,7 @@ struct xgbe_phy_data { | |||
324 | 336 | ||
325 | unsigned int sfp_gpio_address; | 337 | unsigned int sfp_gpio_address; |
326 | unsigned int sfp_gpio_mask; | 338 | unsigned int sfp_gpio_mask; |
339 | unsigned int sfp_gpio_inputs; | ||
327 | unsigned int sfp_gpio_rx_los; | 340 | unsigned int sfp_gpio_rx_los; |
328 | unsigned int sfp_gpio_tx_fault; | 341 | unsigned int sfp_gpio_tx_fault; |
329 | unsigned int sfp_gpio_mod_absent; | 342 | unsigned int sfp_gpio_mod_absent; |
@@ -355,6 +368,10 @@ struct xgbe_phy_data { | |||
355 | unsigned int redrv_addr; | 368 | unsigned int redrv_addr; |
356 | unsigned int redrv_lane; | 369 | unsigned int redrv_lane; |
357 | unsigned int redrv_model; | 370 | unsigned int redrv_model; |
371 | |||
372 | /* KR AN support */ | ||
373 | unsigned int phy_cdr_notrack; | ||
374 | unsigned int phy_cdr_delay; | ||
358 | }; | 375 | }; |
359 | 376 | ||
360 | /* I2C, MDIO and GPIO lines are muxed, so only one device at a time */ | 377 | /* I2C, MDIO and GPIO lines are muxed, so only one device at a time */ |
@@ -974,6 +991,49 @@ static void xgbe_phy_sfp_external_phy(struct xgbe_prv_data *pdata) | |||
974 | phy_data->sfp_phy_avail = 1; | 991 | phy_data->sfp_phy_avail = 1; |
975 | } | 992 | } |
976 | 993 | ||
994 | static bool xgbe_phy_check_sfp_rx_los(struct xgbe_phy_data *phy_data) | ||
995 | { | ||
996 | u8 *sfp_extd = phy_data->sfp_eeprom.extd; | ||
997 | |||
998 | if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_RX_LOS)) | ||
999 | return false; | ||
1000 | |||
1001 | if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) | ||
1002 | return false; | ||
1003 | |||
1004 | if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_rx_los)) | ||
1005 | return true; | ||
1006 | |||
1007 | return false; | ||
1008 | } | ||
1009 | |||
1010 | static bool xgbe_phy_check_sfp_tx_fault(struct xgbe_phy_data *phy_data) | ||
1011 | { | ||
1012 | u8 *sfp_extd = phy_data->sfp_eeprom.extd; | ||
1013 | |||
1014 | if (!(sfp_extd[XGBE_SFP_EXTD_OPT1] & XGBE_SFP_EXTD_OPT1_TX_FAULT)) | ||
1015 | return false; | ||
1016 | |||
1017 | if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) | ||
1018 | return false; | ||
1019 | |||
1020 | if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_tx_fault)) | ||
1021 | return true; | ||
1022 | |||
1023 | return false; | ||
1024 | } | ||
1025 | |||
1026 | static bool xgbe_phy_check_sfp_mod_absent(struct xgbe_phy_data *phy_data) | ||
1027 | { | ||
1028 | if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) | ||
1029 | return false; | ||
1030 | |||
1031 | if (phy_data->sfp_gpio_inputs & (1 << phy_data->sfp_gpio_mod_absent)) | ||
1032 | return true; | ||
1033 | |||
1034 | return false; | ||
1035 | } | ||
1036 | |||
977 | static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata) | 1037 | static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata) |
978 | { | 1038 | { |
979 | struct xgbe_phy_data *phy_data = pdata->phy_data; | 1039 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
@@ -1019,6 +1079,10 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) | |||
1019 | if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP) | 1079 | if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP) |
1020 | return; | 1080 | return; |
1021 | 1081 | ||
1082 | /* Update transceiver signals (eeprom extd/options) */ | ||
1083 | phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data); | ||
1084 | phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data); | ||
1085 | |||
1022 | if (xgbe_phy_sfp_parse_quirks(pdata)) | 1086 | if (xgbe_phy_sfp_parse_quirks(pdata)) |
1023 | return; | 1087 | return; |
1024 | 1088 | ||
@@ -1184,7 +1248,6 @@ put: | |||
1184 | static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) | 1248 | static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) |
1185 | { | 1249 | { |
1186 | struct xgbe_phy_data *phy_data = pdata->phy_data; | 1250 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
1187 | unsigned int gpio_input; | ||
1188 | u8 gpio_reg, gpio_ports[2]; | 1251 | u8 gpio_reg, gpio_ports[2]; |
1189 | int ret; | 1252 | int ret; |
1190 | 1253 | ||
@@ -1199,23 +1262,9 @@ static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata) | |||
1199 | return; | 1262 | return; |
1200 | } | 1263 | } |
1201 | 1264 | ||
1202 | gpio_input = (gpio_ports[1] << 8) | gpio_ports[0]; | 1265 | phy_data->sfp_gpio_inputs = (gpio_ports[1] << 8) | gpio_ports[0]; |
1203 | |||
1204 | if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) { | ||
1205 | /* No GPIO, just assume the module is present for now */ | ||
1206 | phy_data->sfp_mod_absent = 0; | ||
1207 | } else { | ||
1208 | if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent))) | ||
1209 | phy_data->sfp_mod_absent = 0; | ||
1210 | } | ||
1211 | |||
1212 | if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) && | ||
1213 | (gpio_input & (1 << phy_data->sfp_gpio_rx_los))) | ||
1214 | phy_data->sfp_rx_los = 1; | ||
1215 | 1266 | ||
1216 | if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) && | 1267 | phy_data->sfp_mod_absent = xgbe_phy_check_sfp_mod_absent(phy_data); |
1217 | (gpio_input & (1 << phy_data->sfp_gpio_tx_fault))) | ||
1218 | phy_data->sfp_tx_fault = 1; | ||
1219 | } | 1268 | } |
1220 | 1269 | ||
1221 | static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata) | 1270 | static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata) |
@@ -2361,7 +2410,7 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) | |||
2361 | return 1; | 2410 | return 1; |
2362 | 2411 | ||
2363 | /* No link, attempt a receiver reset cycle */ | 2412 | /* No link, attempt a receiver reset cycle */ |
2364 | if (phy_data->rrc_count++) { | 2413 | if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { |
2365 | phy_data->rrc_count = 0; | 2414 | phy_data->rrc_count = 0; |
2366 | xgbe_phy_rrc(pdata); | 2415 | xgbe_phy_rrc(pdata); |
2367 | } | 2416 | } |
@@ -2669,6 +2718,103 @@ static bool xgbe_phy_port_enabled(struct xgbe_prv_data *pdata) | |||
2669 | return true; | 2718 | return true; |
2670 | } | 2719 | } |
2671 | 2720 | ||
2721 | static void xgbe_phy_cdr_track(struct xgbe_prv_data *pdata) | ||
2722 | { | ||
2723 | struct xgbe_phy_data *phy_data = pdata->phy_data; | ||
2724 | |||
2725 | if (!pdata->debugfs_an_cdr_workaround) | ||
2726 | return; | ||
2727 | |||
2728 | if (!phy_data->phy_cdr_notrack) | ||
2729 | return; | ||
2730 | |||
2731 | usleep_range(phy_data->phy_cdr_delay, | ||
2732 | phy_data->phy_cdr_delay + 500); | ||
2733 | |||
2734 | XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, | ||
2735 | XGBE_PMA_CDR_TRACK_EN_MASK, | ||
2736 | XGBE_PMA_CDR_TRACK_EN_ON); | ||
2737 | |||
2738 | phy_data->phy_cdr_notrack = 0; | ||
2739 | } | ||
2740 | |||
2741 | static void xgbe_phy_cdr_notrack(struct xgbe_prv_data *pdata) | ||
2742 | { | ||
2743 | struct xgbe_phy_data *phy_data = pdata->phy_data; | ||
2744 | |||
2745 | if (!pdata->debugfs_an_cdr_workaround) | ||
2746 | return; | ||
2747 | |||
2748 | if (phy_data->phy_cdr_notrack) | ||
2749 | return; | ||
2750 | |||
2751 | XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_CDR_CONTROL, | ||
2752 | XGBE_PMA_CDR_TRACK_EN_MASK, | ||
2753 | XGBE_PMA_CDR_TRACK_EN_OFF); | ||
2754 | |||
2755 | xgbe_phy_rrc(pdata); | ||
2756 | |||
2757 | phy_data->phy_cdr_notrack = 1; | ||
2758 | } | ||
2759 | |||
2760 | static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata) | ||
2761 | { | ||
2762 | if (!pdata->debugfs_an_cdr_track_early) | ||
2763 | xgbe_phy_cdr_track(pdata); | ||
2764 | } | ||
2765 | |||
2766 | static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata) | ||
2767 | { | ||
2768 | if (pdata->debugfs_an_cdr_track_early) | ||
2769 | xgbe_phy_cdr_track(pdata); | ||
2770 | } | ||
2771 | |||
2772 | static void xgbe_phy_an_post(struct xgbe_prv_data *pdata) | ||
2773 | { | ||
2774 | struct xgbe_phy_data *phy_data = pdata->phy_data; | ||
2775 | |||
2776 | switch (pdata->an_mode) { | ||
2777 | case XGBE_AN_MODE_CL73: | ||
2778 | case XGBE_AN_MODE_CL73_REDRV: | ||
2779 | if (phy_data->cur_mode != XGBE_MODE_KR) | ||
2780 | break; | ||
2781 | |||
2782 | xgbe_phy_cdr_track(pdata); | ||
2783 | |||
2784 | switch (pdata->an_result) { | ||
2785 | case XGBE_AN_READY: | ||
2786 | case XGBE_AN_COMPLETE: | ||
2787 | break; | ||
2788 | default: | ||
2789 | if (phy_data->phy_cdr_delay < XGBE_CDR_DELAY_MAX) | ||
2790 | phy_data->phy_cdr_delay += XGBE_CDR_DELAY_INC; | ||
2791 | else | ||
2792 | phy_data->phy_cdr_delay = XGBE_CDR_DELAY_INIT; | ||
2793 | break; | ||
2794 | } | ||
2795 | break; | ||
2796 | default: | ||
2797 | break; | ||
2798 | } | ||
2799 | } | ||
2800 | |||
2801 | static void xgbe_phy_an_pre(struct xgbe_prv_data *pdata) | ||
2802 | { | ||
2803 | struct xgbe_phy_data *phy_data = pdata->phy_data; | ||
2804 | |||
2805 | switch (pdata->an_mode) { | ||
2806 | case XGBE_AN_MODE_CL73: | ||
2807 | case XGBE_AN_MODE_CL73_REDRV: | ||
2808 | if (phy_data->cur_mode != XGBE_MODE_KR) | ||
2809 | break; | ||
2810 | |||
2811 | xgbe_phy_cdr_notrack(pdata); | ||
2812 | break; | ||
2813 | default: | ||
2814 | break; | ||
2815 | } | ||
2816 | } | ||
2817 | |||
2672 | static void xgbe_phy_stop(struct xgbe_prv_data *pdata) | 2818 | static void xgbe_phy_stop(struct xgbe_prv_data *pdata) |
2673 | { | 2819 | { |
2674 | struct xgbe_phy_data *phy_data = pdata->phy_data; | 2820 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
@@ -2680,6 +2826,9 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) | |||
2680 | xgbe_phy_sfp_reset(phy_data); | 2826 | xgbe_phy_sfp_reset(phy_data); |
2681 | xgbe_phy_sfp_mod_absent(pdata); | 2827 | xgbe_phy_sfp_mod_absent(pdata); |
2682 | 2828 | ||
2829 | /* Reset CDR support */ | ||
2830 | xgbe_phy_cdr_track(pdata); | ||
2831 | |||
2683 | /* Power off the PHY */ | 2832 | /* Power off the PHY */ |
2684 | xgbe_phy_power_off(pdata); | 2833 | xgbe_phy_power_off(pdata); |
2685 | 2834 | ||
@@ -2712,6 +2861,9 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata) | |||
2712 | /* Start in highest supported mode */ | 2861 | /* Start in highest supported mode */ |
2713 | xgbe_phy_set_mode(pdata, phy_data->start_mode); | 2862 | xgbe_phy_set_mode(pdata, phy_data->start_mode); |
2714 | 2863 | ||
2864 | /* Reset CDR support */ | ||
2865 | xgbe_phy_cdr_track(pdata); | ||
2866 | |||
2715 | /* After starting the I2C controller, we can check for an SFP */ | 2867 | /* After starting the I2C controller, we can check for an SFP */ |
2716 | switch (phy_data->port_mode) { | 2868 | switch (phy_data->port_mode) { |
2717 | case XGBE_PORT_MODE_SFP: | 2869 | case XGBE_PORT_MODE_SFP: |
@@ -3019,6 +3171,8 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) | |||
3019 | } | 3171 | } |
3020 | } | 3172 | } |
3021 | 3173 | ||
3174 | phy_data->phy_cdr_delay = XGBE_CDR_DELAY_INIT; | ||
3175 | |||
3022 | /* Register for driving external PHYs */ | 3176 | /* Register for driving external PHYs */ |
3023 | mii = devm_mdiobus_alloc(pdata->dev); | 3177 | mii = devm_mdiobus_alloc(pdata->dev); |
3024 | if (!mii) { | 3178 | if (!mii) { |
@@ -3071,4 +3225,10 @@ void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *phy_if) | |||
3071 | phy_impl->an_advertising = xgbe_phy_an_advertising; | 3225 | phy_impl->an_advertising = xgbe_phy_an_advertising; |
3072 | 3226 | ||
3073 | phy_impl->an_outcome = xgbe_phy_an_outcome; | 3227 | phy_impl->an_outcome = xgbe_phy_an_outcome; |
3228 | |||
3229 | phy_impl->an_pre = xgbe_phy_an_pre; | ||
3230 | phy_impl->an_post = xgbe_phy_an_post; | ||
3231 | |||
3232 | phy_impl->kr_training_pre = xgbe_phy_kr_training_pre; | ||
3233 | phy_impl->kr_training_post = xgbe_phy_kr_training_post; | ||
3074 | } | 3234 | } |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index ad102c8bac7b..95d4b56448c6 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h | |||
@@ -833,6 +833,7 @@ struct xgbe_hw_if { | |||
833 | /* This structure represents implementation specific routines for an | 833 | /* This structure represents implementation specific routines for an |
834 | * implementation of a PHY. All routines are required unless noted below. | 834 | * implementation of a PHY. All routines are required unless noted below. |
835 | * Optional routines: | 835 | * Optional routines: |
836 | * an_pre, an_post | ||
836 | * kr_training_pre, kr_training_post | 837 | * kr_training_pre, kr_training_post |
837 | */ | 838 | */ |
838 | struct xgbe_phy_impl_if { | 839 | struct xgbe_phy_impl_if { |
@@ -875,6 +876,10 @@ struct xgbe_phy_impl_if { | |||
875 | /* Process results of auto-negotiation */ | 876 | /* Process results of auto-negotiation */ |
876 | enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *); | 877 | enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *); |
877 | 878 | ||
879 | /* Pre/Post auto-negotiation support */ | ||
880 | void (*an_pre)(struct xgbe_prv_data *); | ||
881 | void (*an_post)(struct xgbe_prv_data *); | ||
882 | |||
878 | /* Pre/Post KR training enablement support */ | 883 | /* Pre/Post KR training enablement support */ |
879 | void (*kr_training_pre)(struct xgbe_prv_data *); | 884 | void (*kr_training_pre)(struct xgbe_prv_data *); |
880 | void (*kr_training_post)(struct xgbe_prv_data *); | 885 | void (*kr_training_post)(struct xgbe_prv_data *); |
@@ -989,6 +994,7 @@ struct xgbe_version_data { | |||
989 | unsigned int irq_reissue_support; | 994 | unsigned int irq_reissue_support; |
990 | unsigned int tx_desc_prefetch; | 995 | unsigned int tx_desc_prefetch; |
991 | unsigned int rx_desc_prefetch; | 996 | unsigned int rx_desc_prefetch; |
997 | unsigned int an_cdr_workaround; | ||
992 | }; | 998 | }; |
993 | 999 | ||
994 | struct xgbe_vxlan_data { | 1000 | struct xgbe_vxlan_data { |
@@ -1257,6 +1263,9 @@ struct xgbe_prv_data { | |||
1257 | unsigned int debugfs_xprop_reg; | 1263 | unsigned int debugfs_xprop_reg; |
1258 | 1264 | ||
1259 | unsigned int debugfs_xi2c_reg; | 1265 | unsigned int debugfs_xi2c_reg; |
1266 | |||
1267 | bool debugfs_an_cdr_workaround; | ||
1268 | bool debugfs_an_cdr_track_early; | ||
1260 | }; | 1269 | }; |
1261 | 1270 | ||
1262 | /* Function prototypes*/ | 1271 | /* Function prototypes*/ |