For yt8521s/yt8531s PHY, if other registers are accessing between
reads/writes of ext field registers, the value of ext filed registers
will get weird for unknown reasons. So it's protected when all of ext
field registers accessing.

Fixes: 44e97550ca68 ("net/ngbe: identify and reset PHY")
Cc: sta...@dpdk.org

Signed-off-by: Jiawen Wu <jiawe...@trustnetic.com>
---
 drivers/net/ngbe/base/ngbe_phy_yt.c | 36 +++++++++++++++++++++++++++++
 drivers/net/ngbe/base/ngbe_type.h   |  1 +
 2 files changed, 37 insertions(+)

diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c 
b/drivers/net/ngbe/base/ngbe_phy_yt.c
index c88946f7c3..726d6c8ef5 100644
--- a/drivers/net/ngbe/base/ngbe_phy_yt.c
+++ b/drivers/net/ngbe/base/ngbe_phy_yt.c
@@ -100,11 +100,15 @@ s32 ngbe_write_phy_reg_sds_ext_yt(struct ngbe_hw *hw,
 
 s32 ngbe_init_phy_yt(struct ngbe_hw *hw)
 {
+       rte_spinlock_init(&hw->phy_lock);
+
+       rte_spinlock_lock(&hw->phy_lock);
        /* close sds area register */
        ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
        /* enable interrupts */
        ngbe_write_phy_reg_mdi(hw, YT_INTR, 0,
                                YT_INTR_ENA_MASK | YT_SDS_INTR_ENA_MASK);
+       rte_spinlock_unlock(&hw->phy_lock);
 
        hw->phy.set_phy_power(hw, false);
 
@@ -123,7 +127,9 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
        hw->phy.autoneg_advertised = 0;
 
        /* check chip_mode first */
+       rte_spinlock_lock(&hw->phy_lock);
        ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
+       rte_spinlock_unlock(&hw->phy_lock);
        if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(0)) {
                /* UTP to rgmii */
                if (!hw->mac.autoneg) {
@@ -146,11 +152,14 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                        }
                        /* duplex full */
                        value |= YT_BCR_DUPLEX | YT_BCR_RESET;
+                       rte_spinlock_lock(&hw->phy_lock);
                        ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+                       rte_spinlock_unlock(&hw->phy_lock);
 
                        goto skip_an;
                }
 
+               rte_spinlock_lock(&hw->phy_lock);
                /*disable 100/10base-T Self-negotiation ability*/
                ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
                value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
@@ -189,6 +198,7 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
                value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
                ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+               rte_spinlock_unlock(&hw->phy_lock);
 skip_an:
                hw->phy.set_phy_power(hw, true);
        } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(1)) {
@@ -199,6 +209,7 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                value = YT_RGMII_CONF1_RXDELAY |
                        YT_RGMII_CONF1_TXDELAY_FE |
                        YT_RGMII_CONF1_TXDELAY;
+               rte_spinlock_lock(&hw->phy_lock);
                ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
                value = YT_CHIP_MODE_SEL(1) |
                        YT_CHIP_SW_LDO_EN |
@@ -225,17 +236,21 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                        value = YT_BCR_RESET | YT_BCR_DUPLEX |
                                YT_BCR_SPEED_SELECT1;
                hw->phy.write_reg(hw, YT_BCR, 0, value);
+               rte_spinlock_unlock(&hw->phy_lock);
 
                hw->phy.set_phy_power(hw, true);
        } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(2)) {
                hw->phy.set_phy_power(hw, true);
 
+               rte_spinlock_lock(&hw->phy_lock);
                hw->phy.read_reg(hw, YT_SPST, 0, &value);
+               rte_spinlock_unlock(&hw->phy_lock);
                if (value & YT_SPST_LINK) {
                        /* fiber up */
                        hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
                } else {
                        /* utp up */
+                       rte_spinlock_lock(&hw->phy_lock);
                        /*disable 100/10base-T Self-negotiation ability*/
                        ngbe_read_phy_reg_mdi(hw, YT_ANA, 0, &value);
                        value &= ~(YT_ANA_100BASET_FULL | YT_ANA_100BASET_HALF |
@@ -279,10 +294,12 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                        ngbe_read_phy_reg_mdi(hw, YT_BCR, 0, &value);
                        value |= YT_BCR_RESET;
                        ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+                       rte_spinlock_unlock(&hw->phy_lock);
                }
        } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(4)) {
                hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL;
 
+               rte_spinlock_lock(&hw->phy_lock);
                ngbe_read_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, &value);
                value |= YT_RGMII_CONF1_MODE;
                ngbe_write_phy_reg_ext_yt(hw, YT_RGMII_CONF1, 0, value);
@@ -297,6 +314,7 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &value);
                value &= ~YT_SMI_PHY_SW_RST;
                ngbe_write_phy_reg_ext_yt(hw, YT_CHIP, 0, value);
+               rte_spinlock_unlock(&hw->phy_lock);
 
                hw->phy.set_phy_power(hw, true);
        } else if ((value & YT_CHIP_MODE_MASK) == YT_CHIP_MODE_SEL(5)) {
@@ -320,7 +338,9 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
                        }
                        /* duplex full */
                        value |= YT_BCR_DUPLEX | YT_BCR_RESET;
+                       rte_spinlock_lock(&hw->phy_lock);
                        hw->phy.write_reg(hw, YT_BCR, 0, value);
+                       rte_spinlock_unlock(&hw->phy_lock);
 
                        goto skip_an_sr;
                }
@@ -339,19 +359,23 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed,
 
                /* duplex full */
                value |= YT_BCR_DUPLEX | YT_BCR_RESET;
+               rte_spinlock_lock(&hw->phy_lock);
                hw->phy.write_reg(hw, YT_BCR, 0, value);
 
                /* software reset to make the above configuration take effect */
                hw->phy.read_reg(hw, YT_BCR, 0, &value);
                value |= YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN;
                hw->phy.write_reg(hw, 0x0, 0, value);
+               rte_spinlock_unlock(&hw->phy_lock);
 
 skip_an_sr:
                hw->phy.set_phy_power(hw, true);
        }
 
+       rte_spinlock_lock(&hw->phy_lock);
        ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
        ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &value);
+       rte_spinlock_unlock(&hw->phy_lock);
 
        return 0;
 }
@@ -366,6 +390,7 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
                hw->phy.type != ngbe_phy_yt8521s_sfi)
                return NGBE_ERR_PHY_TYPE;
 
+       rte_spinlock_lock(&hw->phy_lock);
        /* check chip_mode first */
        ngbe_read_phy_reg_ext_yt(hw, YT_CHIP, 0, &ctrl);
        if (ctrl & YT_CHIP_MODE_MASK) {
@@ -395,6 +420,7 @@ s32 ngbe_reset_phy_yt(struct ngbe_hw *hw)
                        msleep(1);
                }
        }
+       rte_spinlock_unlock(&hw->phy_lock);
 
        if (i == YT_PHY_RST_WAIT_PERIOD) {
                DEBUGOUT("PHY reset polling failed to complete.");
@@ -409,7 +435,9 @@ s32 ngbe_get_phy_advertised_pause_yt(struct ngbe_hw *hw, u8 
*pause_bit)
        u16 value;
        s32 status = 0;
 
+       rte_spinlock_lock(&hw->phy_lock);
        status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
+       rte_spinlock_unlock(&hw->phy_lock);
        value &= YT_FANA_PAUSE_MASK;
        *pause_bit = (u8)(value >> 7);
 
@@ -421,7 +449,9 @@ s32 ngbe_get_phy_lp_advertised_pause_yt(struct ngbe_hw *hw, 
u8 *pause_bit)
        u16 value;
        s32 status = 0;
 
+       rte_spinlock_lock(&hw->phy_lock);
        status = hw->phy.read_reg(hw, YT_LPAR, 0, &value);
+       rte_spinlock_unlock(&hw->phy_lock);
        value &= YT_FLPAR_PAUSE_MASK;
        *pause_bit = (u8)(value >> 7);
 
@@ -433,10 +463,12 @@ s32 ngbe_set_phy_pause_adv_yt(struct ngbe_hw *hw, u16 
pause_bit)
        u16 value;
        s32 status = 0;
 
+       rte_spinlock_lock(&hw->phy_lock);
        status = hw->phy.read_reg(hw, YT_ANA, 0, &value);
        value &= ~YT_FANA_PAUSE_MASK;
        value |= pause_bit;
        status = hw->phy.write_reg(hw, YT_ANA, 0, value);
+       rte_spinlock_unlock(&hw->phy_lock);
 
        return status;
 }
@@ -453,6 +485,7 @@ s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
        /* Initialize speed and link to default case */
        *link_up = false;
        *speed = NGBE_LINK_SPEED_UNKNOWN;
+       rte_spinlock_lock(&hw->phy_lock);
 
        ngbe_write_phy_reg_ext_yt(hw, YT_SMI_PHY, 0, 0);
        ngbe_read_phy_reg_mdi(hw, YT_INTR_STATUS, 0, &insr);
@@ -472,6 +505,7 @@ s32 ngbe_check_phy_link_yt(struct ngbe_hw *hw,
                        *link_up = true;
        }
 
+       rte_spinlock_unlock(&hw->phy_lock);
        if (*link_up) {
                if (phy_speed == YT_SPST_SPEED_1000M)
                        *speed = NGBE_LINK_SPEED_1GB_FULL;
@@ -488,6 +522,7 @@ s32 ngbe_set_phy_power_yt(struct ngbe_hw *hw, bool on)
 {
        u16 value = 0;
 
+       rte_spinlock_lock(&hw->phy_lock);
        /* power down/up in fiber mode */
        hw->phy.read_reg(hw, YT_BCR, 0, &value);
        if (on)
@@ -504,6 +539,7 @@ s32 ngbe_set_phy_power_yt(struct ngbe_hw *hw, bool on)
        else
                value |= YT_BCR_PWDN;
        ngbe_write_phy_reg_mdi(hw, YT_BCR, 0, value);
+       rte_spinlock_unlock(&hw->phy_lock);
 
        return 0;
 }
diff --git a/drivers/net/ngbe/base/ngbe_type.h 
b/drivers/net/ngbe/base/ngbe_type.h
index aa5c41146c..05804eeab7 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -433,6 +433,7 @@ struct ngbe_hw {
        bool gpio_ctl;
        u32 led_conf;
        bool init_phy;
+       rte_spinlock_t phy_lock;
        struct {
                u64 rx_qp_packets;
                u64 tx_qp_packets;
-- 
2.27.0

Reply via email to