aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLendacky, Thomas <Thomas.Lendacky@amd.com>2014-09-03 13:14:16 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-05 18:11:20 -0400
commite3eec4e79322957d9408dc4e2cf7276c558999d7 (patch)
treeeb0e1341d18259b468ed491580e4b0d8cbb99529 /drivers/net
parente4cf0b756c78e252b989b86e281ecc12d40bd2f6 (diff)
amd-xgbe-phy: Check device for current speed mode (KR/KX)
Since device resets can change the current mode it's possible to think the device is in a different mode than it actually is. Rather than trying to determine every place that is needed to set/save the current mode, be safe and check the devices actual mode when needed rather than trying to track it. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/phy/amd-xgbe-phy.c135
1 files changed, 72 insertions, 63 deletions
diff --git a/drivers/net/phy/amd-xgbe-phy.c b/drivers/net/phy/amd-xgbe-phy.c
index f3230eef41fd..b3cef20637c0 100644
--- a/drivers/net/phy/amd-xgbe-phy.c
+++ b/drivers/net/phy/amd-xgbe-phy.c
@@ -331,7 +331,6 @@ struct amd_xgbe_phy_priv {
331 331
332 /* Maintain link status for re-starting auto-negotiation */ 332 /* Maintain link status for re-starting auto-negotiation */
333 unsigned int link; 333 unsigned int link;
334 enum amd_xgbe_phy_mode mode;
335 unsigned int speed_set; 334 unsigned int speed_set;
336 335
337 /* Auto-negotiation state machine support */ 336 /* Auto-negotiation state machine support */
@@ -468,8 +467,6 @@ static int amd_xgbe_phy_xgmii_mode(struct phy_device *phydev)
468 467
469 amd_xgbe_phy_serdes_complete_ratechange(phydev); 468 amd_xgbe_phy_serdes_complete_ratechange(phydev);
470 469
471 priv->mode = AMD_XGBE_MODE_KR;
472
473 return 0; 470 return 0;
474} 471}
475 472
@@ -518,8 +515,6 @@ static int amd_xgbe_phy_gmii_2500_mode(struct phy_device *phydev)
518 515
519 amd_xgbe_phy_serdes_complete_ratechange(phydev); 516 amd_xgbe_phy_serdes_complete_ratechange(phydev);
520 517
521 priv->mode = AMD_XGBE_MODE_KX;
522
523 return 0; 518 return 0;
524} 519}
525 520
@@ -568,18 +563,43 @@ static int amd_xgbe_phy_gmii_mode(struct phy_device *phydev)
568 563
569 amd_xgbe_phy_serdes_complete_ratechange(phydev); 564 amd_xgbe_phy_serdes_complete_ratechange(phydev);
570 565
571 priv->mode = AMD_XGBE_MODE_KX; 566 return 0;
567}
568
569static int amd_xgbe_phy_cur_mode(struct phy_device *phydev,
570 enum amd_xgbe_phy_mode *mode)
571{
572 int ret;
573
574 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
575 if (ret < 0)
576 return ret;
577
578 if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
579 *mode = AMD_XGBE_MODE_KR;
580 else
581 *mode = AMD_XGBE_MODE_KX;
572 582
573 return 0; 583 return 0;
574} 584}
575 585
586static bool amd_xgbe_phy_in_kr_mode(struct phy_device *phydev)
587{
588 enum amd_xgbe_phy_mode mode;
589
590 if (amd_xgbe_phy_cur_mode(phydev, &mode))
591 return false;
592
593 return (mode == AMD_XGBE_MODE_KR);
594}
595
576static int amd_xgbe_phy_switch_mode(struct phy_device *phydev) 596static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
577{ 597{
578 struct amd_xgbe_phy_priv *priv = phydev->priv; 598 struct amd_xgbe_phy_priv *priv = phydev->priv;
579 int ret; 599 int ret;
580 600
581 /* If we are in KR switch to KX, and vice-versa */ 601 /* If we are in KR switch to KX, and vice-versa */
582 if (priv->mode == AMD_XGBE_MODE_KR) { 602 if (amd_xgbe_phy_in_kr_mode(phydev)) {
583 if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000) 603 if (priv->speed_set == AMD_XGBE_PHY_SPEEDSET_1000_10000)
584 ret = amd_xgbe_phy_gmii_mode(phydev); 604 ret = amd_xgbe_phy_gmii_mode(phydev);
585 else 605 else
@@ -591,27 +611,31 @@ static int amd_xgbe_phy_switch_mode(struct phy_device *phydev)
591 return ret; 611 return ret;
592} 612}
593 613
594static enum amd_xgbe_phy_an amd_xgbe_an_switch_mode(struct phy_device *phydev) 614static int amd_xgbe_phy_set_mode(struct phy_device *phydev,
615 enum amd_xgbe_phy_mode mode)
595{ 616{
617 enum amd_xgbe_phy_mode cur_mode;
596 int ret; 618 int ret;
597 619
598 ret = amd_xgbe_phy_switch_mode(phydev); 620 ret = amd_xgbe_phy_cur_mode(phydev, &cur_mode);
599 if (ret < 0) 621 if (ret)
600 return AMD_XGBE_AN_ERROR; 622 return ret;
601 623
602 return AMD_XGBE_AN_START; 624 if (mode != cur_mode)
625 ret = amd_xgbe_phy_switch_mode(phydev);
626
627 return ret;
603} 628}
604 629
605static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev, 630static enum amd_xgbe_phy_an amd_xgbe_an_tx_training(struct phy_device *phydev,
606 enum amd_xgbe_phy_rx *state) 631 enum amd_xgbe_phy_rx *state)
607{ 632{
608 struct amd_xgbe_phy_priv *priv = phydev->priv;
609 int ad_reg, lp_reg, ret; 633 int ad_reg, lp_reg, ret;
610 634
611 *state = AMD_XGBE_RX_COMPLETE; 635 *state = AMD_XGBE_RX_COMPLETE;
612 636
613 /* If we're in KX mode then we're done */ 637 /* If we're not in KR mode then we're done */
614 if (priv->mode == AMD_XGBE_MODE_KX) 638 if (!amd_xgbe_phy_in_kr_mode(phydev))
615 return AMD_XGBE_AN_EVENT; 639 return AMD_XGBE_AN_EVENT;
616 640
617 /* Enable/Disable FEC */ 641 /* Enable/Disable FEC */
@@ -669,7 +693,6 @@ static enum amd_xgbe_phy_an amd_xgbe_an_tx_xnp(struct phy_device *phydev,
669static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev, 693static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev,
670 enum amd_xgbe_phy_rx *state) 694 enum amd_xgbe_phy_rx *state)
671{ 695{
672 struct amd_xgbe_phy_priv *priv = phydev->priv;
673 unsigned int link_support; 696 unsigned int link_support;
674 int ret, ad_reg, lp_reg; 697 int ret, ad_reg, lp_reg;
675 698
@@ -679,9 +702,9 @@ static enum amd_xgbe_phy_an amd_xgbe_an_rx_bpa(struct phy_device *phydev,
679 return AMD_XGBE_AN_ERROR; 702 return AMD_XGBE_AN_ERROR;
680 703
681 /* Check for a supported mode, otherwise restart in a different one */ 704 /* Check for a supported mode, otherwise restart in a different one */
682 link_support = (priv->mode == AMD_XGBE_MODE_KR) ? 0x80 : 0x20; 705 link_support = amd_xgbe_phy_in_kr_mode(phydev) ? 0x80 : 0x20;
683 if (!(ret & link_support)) 706 if (!(ret & link_support))
684 return amd_xgbe_an_switch_mode(phydev); 707 return AMD_XGBE_AN_INCOMPAT_LINK;
685 708
686 /* Check Extended Next Page support */ 709 /* Check Extended Next Page support */
687 ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); 710 ad_reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
@@ -722,7 +745,7 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
722 int ret; 745 int ret;
723 746
724 /* Be sure we aren't looping trying to negotiate */ 747 /* Be sure we aren't looping trying to negotiate */
725 if (priv->mode == AMD_XGBE_MODE_KR) { 748 if (amd_xgbe_phy_in_kr_mode(phydev)) {
726 if (priv->kr_state != AMD_XGBE_RX_READY) 749 if (priv->kr_state != AMD_XGBE_RX_READY)
727 return AMD_XGBE_AN_NO_LINK; 750 return AMD_XGBE_AN_NO_LINK;
728 priv->kr_state = AMD_XGBE_RX_BPA; 751 priv->kr_state = AMD_XGBE_RX_BPA;
@@ -825,8 +848,8 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
825 enum amd_xgbe_phy_rx *state; 848 enum amd_xgbe_phy_rx *state;
826 int ret; 849 int ret;
827 850
828 state = (priv->mode == AMD_XGBE_MODE_KR) ? &priv->kr_state 851 state = amd_xgbe_phy_in_kr_mode(phydev) ? &priv->kr_state
829 : &priv->kx_state; 852 : &priv->kx_state;
830 853
831 switch (*state) { 854 switch (*state) {
832 case AMD_XGBE_RX_BPA: 855 case AMD_XGBE_RX_BPA:
@@ -846,7 +869,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_page_received(struct phy_device *phydev)
846 869
847static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev) 870static enum amd_xgbe_phy_an amd_xgbe_an_incompat_link(struct phy_device *phydev)
848{ 871{
849 return amd_xgbe_an_switch_mode(phydev); 872 int ret;
873
874 ret = amd_xgbe_phy_switch_mode(phydev);
875 if (ret)
876 return AMD_XGBE_AN_ERROR;
877
878 return AMD_XGBE_AN_START;
850} 879}
851 880
852static void amd_xgbe_an_state_machine(struct work_struct *work) 881static void amd_xgbe_an_state_machine(struct work_struct *work)
@@ -1018,7 +1047,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev)
1018{ 1047{
1019 struct amd_xgbe_phy_priv *priv = phydev->priv; 1048 struct amd_xgbe_phy_priv *priv = phydev->priv;
1020 u32 mmd_mask = phydev->c45_ids.devices_in_package; 1049 u32 mmd_mask = phydev->c45_ids.devices_in_package;
1021 int ret;
1022 1050
1023 if (phydev->autoneg != AUTONEG_ENABLE) 1051 if (phydev->autoneg != AUTONEG_ENABLE)
1024 return amd_xgbe_phy_setup_forced(phydev); 1052 return amd_xgbe_phy_setup_forced(phydev);
@@ -1027,11 +1055,6 @@ static int amd_xgbe_phy_config_aneg(struct phy_device *phydev)
1027 if (!(mmd_mask & MDIO_DEVS_AN)) 1055 if (!(mmd_mask & MDIO_DEVS_AN))
1028 return -EINVAL; 1056 return -EINVAL;
1029 1057
1030 /* Get the current speed mode */
1031 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
1032 if (ret < 0)
1033 return ret;
1034
1035 /* Start/Restart the auto-negotiation state machine */ 1058 /* Start/Restart the auto-negotiation state machine */
1036 mutex_lock(&priv->an_mutex); 1059 mutex_lock(&priv->an_mutex);
1037 priv->an_result = AMD_XGBE_AN_READY; 1060 priv->an_result = AMD_XGBE_AN_READY;
@@ -1121,17 +1144,12 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
1121{ 1144{
1122 struct amd_xgbe_phy_priv *priv = phydev->priv; 1145 struct amd_xgbe_phy_priv *priv = phydev->priv;
1123 u32 mmd_mask = phydev->c45_ids.devices_in_package; 1146 u32 mmd_mask = phydev->c45_ids.devices_in_package;
1124 int ret, mode, ad_ret, lp_ret; 1147 int ret, ad_ret, lp_ret;
1125 1148
1126 ret = amd_xgbe_phy_update_link(phydev); 1149 ret = amd_xgbe_phy_update_link(phydev);
1127 if (ret) 1150 if (ret)
1128 return ret; 1151 return ret;
1129 1152
1130 mode = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
1131 if (mode < 0)
1132 return mode;
1133 mode &= MDIO_PCS_CTRL2_TYPE;
1134
1135 if (phydev->autoneg == AUTONEG_ENABLE) { 1153 if (phydev->autoneg == AUTONEG_ENABLE) {
1136 if (!(mmd_mask & MDIO_DEVS_AN)) 1154 if (!(mmd_mask & MDIO_DEVS_AN))
1137 return -EINVAL; 1155 return -EINVAL;
@@ -1163,40 +1181,39 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
1163 ad_ret &= lp_ret; 1181 ad_ret &= lp_ret;
1164 if (ad_ret & 0x80) { 1182 if (ad_ret & 0x80) {
1165 phydev->speed = SPEED_10000; 1183 phydev->speed = SPEED_10000;
1166 if (mode != MDIO_PCS_CTRL2_10GBR) { 1184 ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KR);
1167 ret = amd_xgbe_phy_xgmii_mode(phydev); 1185 if (ret)
1168 if (ret < 0) 1186 return ret;
1169 return ret;
1170 }
1171 } else { 1187 } else {
1172 int (*mode_fcn)(struct phy_device *); 1188 switch (priv->speed_set) {
1173 1189 case AMD_XGBE_PHY_SPEEDSET_1000_10000:
1174 if (priv->speed_set ==
1175 AMD_XGBE_PHY_SPEEDSET_1000_10000) {
1176 phydev->speed = SPEED_1000; 1190 phydev->speed = SPEED_1000;
1177 mode_fcn = amd_xgbe_phy_gmii_mode; 1191 break;
1178 } else { 1192
1193 case AMD_XGBE_PHY_SPEEDSET_2500_10000:
1179 phydev->speed = SPEED_2500; 1194 phydev->speed = SPEED_2500;
1180 mode_fcn = amd_xgbe_phy_gmii_2500_mode; 1195 break;
1181 } 1196 }
1182 1197
1183 if (mode == MDIO_PCS_CTRL2_10GBR) { 1198 ret = amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX);
1184 ret = mode_fcn(phydev); 1199 if (ret)
1185 if (ret < 0) 1200 return ret;
1186 return ret;
1187 }
1188 } 1201 }
1189 1202
1190 phydev->duplex = DUPLEX_FULL; 1203 phydev->duplex = DUPLEX_FULL;
1191 } else { 1204 } else {
1192 if (mode == MDIO_PCS_CTRL2_10GBR) { 1205 if (amd_xgbe_phy_in_kr_mode(phydev)) {
1193 phydev->speed = SPEED_10000; 1206 phydev->speed = SPEED_10000;
1194 } else { 1207 } else {
1195 if (priv->speed_set == 1208 switch (priv->speed_set) {
1196 AMD_XGBE_PHY_SPEEDSET_1000_10000) 1209 case AMD_XGBE_PHY_SPEEDSET_1000_10000:
1197 phydev->speed = SPEED_1000; 1210 phydev->speed = SPEED_1000;
1198 else 1211 break;
1212
1213 case AMD_XGBE_PHY_SPEEDSET_2500_10000:
1199 phydev->speed = SPEED_2500; 1214 phydev->speed = SPEED_2500;
1215 break;
1216 }
1200 } 1217 }
1201 phydev->duplex = DUPLEX_FULL; 1218 phydev->duplex = DUPLEX_FULL;
1202 phydev->pause = 0; 1219 phydev->pause = 0;
@@ -1329,14 +1346,6 @@ static int amd_xgbe_phy_probe(struct phy_device *phydev)
1329 1346
1330 priv->link = 1; 1347 priv->link = 1;
1331 1348
1332 ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL2);
1333 if (ret < 0)
1334 goto err_sir1;
1335 if ((ret & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
1336 priv->mode = AMD_XGBE_MODE_KR;
1337 else
1338 priv->mode = AMD_XGBE_MODE_KX;
1339
1340 mutex_init(&priv->an_mutex); 1349 mutex_init(&priv->an_mutex);
1341 INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine); 1350 INIT_WORK(&priv->an_work, amd_xgbe_an_state_machine);
1342 priv->an_workqueue = create_singlethread_workqueue(wq_name); 1351 priv->an_workqueue = create_singlethread_workqueue(wq_name);