History

net: stmmac: fix FPE events losing

The status bits of register MAC_FPE_CTRL_STS are clear on read. Using 32-bit read for MAC_FPE_CTRL_STS in dwmac5_fpe_configure() and dwmac5_fpe_send_mpacket() clear the status bits. Then the stmmac interrupt handler missing FPE event status and leads to FPE handshaking failure and retries. To avoid clear status bits of MAC_FPE_CTRL_STS in dwmac5_fpe_configure() and dwmac5_fpe_send_mpacket(), add fpe_csr to stmmac_fpe_cfg structure to cache the control bits of MAC_FPE_CTRL_STS and to avoid reading MAC_FPE_CTRL_STS in those methods.

Jianheng Zhang committed 2 years ago

Commit 37e4b8d1 parent adbf1007 files · +36 −30Browse files

Unified · Split

7 files
  1. drivers/net/ethernet/stmicro/stmmac/dwmac5.c +19 −26
  2. drivers/net/ethernet/stmicro/stmmac/dwmac5.h +3 −1
  3. drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +2 −1
  4. drivers/net/ethernet/stmicro/stmmac/hwif.h +3 −1
  5. drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +7 −1
  6. drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +1 −0
  7. include/linux/stmmac.h +1 −0
drivers/net/ethernet/stmicro/stmmac/dwmac5.c+19−26
@@ -710,28 +710,22 @@ void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev, · 709 unmodified lines
710 }710 }
711}711}
712 712
713void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,713void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
714 u32 num_txq, u32 num_rxq,
714 bool enable)715 bool enable)
715{716{
716 u32 value;717 u32 value;
717 718
718 if (!enable) {719 if (enable) {
719 value = readl(ioaddr + MAC_FPE_CTRL_STS);720 cfg->fpe_csr = EFPE;
720 721 value = readl(ioaddr + GMAC_RXQ_CTRL1);
721 value &= ~EFPE;722 value &= ~GMAC_RXQCTRL_FPRQ;
722 723 value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
723 writel(value, ioaddr + MAC_FPE_CTRL_STS);724 writel(value, ioaddr + GMAC_RXQ_CTRL1);
724 return;725 } else {
726 cfg->fpe_csr = 0;
725 }727 }
726 728 writel(cfg->fpe_csr, ioaddr + MAC_FPE_CTRL_STS);
727 value = readl(ioaddr + GMAC_RXQ_CTRL1);
728 value &= ~GMAC_RXQCTRL_FPRQ;
729 value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
730 writel(value, ioaddr + GMAC_RXQ_CTRL1);
731
732 value = readl(ioaddr + MAC_FPE_CTRL_STS);
733 value |= EFPE;
734 writel(value, ioaddr + MAC_FPE_CTRL_STS);
735}729}
736 730
737int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)731int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)
@@ -741,6 +735,9 @@ int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev) · 3 unmodified lines
741 735
742 status = FPE_EVENT_UNKNOWN;736 status = FPE_EVENT_UNKNOWN;
743 737
738 /* Reads from the MAC_FPE_CTRL_STS register should only be performed
739 * here, since the status flags of MAC_FPE_CTRL_STS are "clear on read"
740 */
744 value = readl(ioaddr + MAC_FPE_CTRL_STS);741 value = readl(ioaddr + MAC_FPE_CTRL_STS);
745 742
746 if (value & TRSP) {743 if (value & TRSP) {
@@ -766,19 +763,15 @@ int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev) · 19 unmodified lines
766 return status;763 return status;
767}764}
768 765
769void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, enum stmmac_mpacket_type type)766void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
767 enum stmmac_mpacket_type type)
770{768{
771 u32 value;769 u32 value = cfg->fpe_csr;
772 770
773 value = readl(ioaddr + MAC_FPE_CTRL_STS);771 if (type == MPACKET_VERIFY)
774
775 if (type == MPACKET_VERIFY) {
776 value &= ~SRSP;
777 value |= SVER;772 value |= SVER;
778 } else {773 else if (type == MPACKET_RESPONSE)
779 value &= ~SVER;
780 value |= SRSP;774 value |= SRSP;
781 }
782 775
783 writel(value, ioaddr + MAC_FPE_CTRL_STS);776 writel(value, ioaddr + MAC_FPE_CTRL_STS);
784}777}
drivers/net/ethernet/stmicro/stmmac/dwmac5.h+3−1
@@ -153,9 +153,11 @@ int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg, · 152 unmodified lines
153 unsigned int ptp_rate);153 unsigned int ptp_rate);
154void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,154void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
155 struct stmmac_extra_stats *x, u32 txqcnt);155 struct stmmac_extra_stats *x, u32 txqcnt);
156void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,156void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
157 u32 num_txq, u32 num_rxq,
157 bool enable);158 bool enable);
158void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,159void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
160 struct stmmac_fpe_cfg *cfg,
159 enum stmmac_mpacket_type type);161 enum stmmac_mpacket_type type);
160int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);162int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);
161 163
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c+2−1
@@ -1484,7 +1484,8 @@ static int dwxgmac3_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg, · 1483 unmodified lines
1484 return 0;1484 return 0;
1485}1485}
1486 1486
1487static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq,1487static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
1488 u32 num_txq,
1488 u32 num_rxq, bool enable)1489 u32 num_rxq, bool enable)
1489{1490{
1490 u32 value;1491 u32 value;
drivers/net/ethernet/stmicro/stmmac/hwif.h+3−1
@@ -412,9 +412,11 @@ struct stmmac_ops { · 411 unmodified lines
412 unsigned int ptp_rate);412 unsigned int ptp_rate);
413 void (*est_irq_status)(void __iomem *ioaddr, struct net_device *dev,413 void (*est_irq_status)(void __iomem *ioaddr, struct net_device *dev,
414 struct stmmac_extra_stats *x, u32 txqcnt);414 struct stmmac_extra_stats *x, u32 txqcnt);
415 void (*fpe_configure)(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,415 void (*fpe_configure)(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
416 u32 num_txq, u32 num_rxq,
416 bool enable);417 bool enable);
417 void (*fpe_send_mpacket)(void __iomem *ioaddr,418 void (*fpe_send_mpacket)(void __iomem *ioaddr,
419 struct stmmac_fpe_cfg *cfg,
418 enum stmmac_mpacket_type type);420 enum stmmac_mpacket_type type);
419 int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev);421 int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev);
420};422};
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c+7−1
@@ -964,7 +964,8 @@ static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up) · 963 unmodified lines
964 bool *hs_enable = &fpe_cfg->hs_enable;964 bool *hs_enable = &fpe_cfg->hs_enable;
965 965
966 if (is_up && *hs_enable) {966 if (is_up && *hs_enable) {
967 stmmac_fpe_send_mpacket(priv, priv->ioaddr, MPACKET_VERIFY);967 stmmac_fpe_send_mpacket(priv, priv->ioaddr, fpe_cfg,
968 MPACKET_VERIFY);
968 } else {969 } else {
969 *lo_state = FPE_STATE_OFF;970 *lo_state = FPE_STATE_OFF;
970 *lp_state = FPE_STATE_OFF;971 *lp_state = FPE_STATE_OFF;
@@ -5839,6 +5840,7 @@ static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status) · 4868 unmodified lines
5839 /* If user has requested FPE enable, quickly response */5840 /* If user has requested FPE enable, quickly response */
5840 if (*hs_enable)5841 if (*hs_enable)
5841 stmmac_fpe_send_mpacket(priv, priv->ioaddr,5842 stmmac_fpe_send_mpacket(priv, priv->ioaddr,
5843 fpe_cfg,
5842 MPACKET_RESPONSE);5844 MPACKET_RESPONSE);
5843 }5845 }
5844 5846
@@ -7263,6 +7265,7 @@ static void stmmac_fpe_lp_task(struct work_struct *work) · 1418 unmodified lines
7263 if (*lo_state == FPE_STATE_ENTERING_ON &&7265 if (*lo_state == FPE_STATE_ENTERING_ON &&
7264 *lp_state == FPE_STATE_ENTERING_ON) {7266 *lp_state == FPE_STATE_ENTERING_ON) {
7265 stmmac_fpe_configure(priv, priv->ioaddr,7267 stmmac_fpe_configure(priv, priv->ioaddr,
7268 fpe_cfg,
7266 priv->plat->tx_queues_to_use,7269 priv->plat->tx_queues_to_use,
7267 priv->plat->rx_queues_to_use,7270 priv->plat->rx_queues_to_use,
7268 *enable);7271 *enable);
@@ -7281,6 +7284,7 @@ static void stmmac_fpe_lp_task(struct work_struct *work) · 12 unmodified lines
7281 netdev_info(priv->dev, SEND_VERIFY_MPAKCET_FMT,7284 netdev_info(priv->dev, SEND_VERIFY_MPAKCET_FMT,
7282 *lo_state, *lp_state);7285 *lo_state, *lp_state);
7283 stmmac_fpe_send_mpacket(priv, priv->ioaddr,7286 stmmac_fpe_send_mpacket(priv, priv->ioaddr,
7287 fpe_cfg,
7284 MPACKET_VERIFY);7288 MPACKET_VERIFY);
7285 }7289 }
7286 /* Sleep then retry */7290 /* Sleep then retry */
@@ -7295,6 +7299,7 @@ void stmmac_fpe_handshake(struct stmmac_priv *priv, bool enable) · 8 unmodified lines
7295 if (priv->plat->fpe_cfg->hs_enable != enable) {7299 if (priv->plat->fpe_cfg->hs_enable != enable) {
7296 if (enable) {7300 if (enable) {
7297 stmmac_fpe_send_mpacket(priv, priv->ioaddr,7301 stmmac_fpe_send_mpacket(priv, priv->ioaddr,
7302 priv->plat->fpe_cfg,
7298 MPACKET_VERIFY);7303 MPACKET_VERIFY);
7299 } else {7304 } else {
7300 priv->plat->fpe_cfg->lo_fpe_state = FPE_STATE_OFF;7305 priv->plat->fpe_cfg->lo_fpe_state = FPE_STATE_OFF;
@@ -7755,6 +7760,7 @@ int stmmac_suspend(struct device *dev) · 454 unmodified lines
7755 if (priv->dma_cap.fpesel) {7760 if (priv->dma_cap.fpesel) {
7756 /* Disable FPE */7761 /* Disable FPE */
7757 stmmac_fpe_configure(priv, priv->ioaddr,7762 stmmac_fpe_configure(priv, priv->ioaddr,
7763 priv->plat->fpe_cfg,
7758 priv->plat->tx_queues_to_use,7764 priv->plat->tx_queues_to_use,
7759 priv->plat->rx_queues_to_use, false);7765 priv->plat->rx_queues_to_use, false);
7760 7766
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c+1−0
@@ -1079,6 +1079,7 @@ disable: · 1078 unmodified lines
1079 1079
1080 priv->plat->fpe_cfg->enable = false;1080 priv->plat->fpe_cfg->enable = false;
1081 stmmac_fpe_configure(priv, priv->ioaddr,1081 stmmac_fpe_configure(priv, priv->ioaddr,
1082 priv->plat->fpe_cfg,
1082 priv->plat->tx_queues_to_use,1083 priv->plat->tx_queues_to_use,
1083 priv->plat->rx_queues_to_use,1084 priv->plat->rx_queues_to_use,
1084 false);1085 false);
include/linux/stmmac.h+1−0
@@ -175,6 +175,7 @@ struct stmmac_fpe_cfg { · 174 unmodified lines
175 bool hs_enable; /* FPE handshake enable */175 bool hs_enable; /* FPE handshake enable */
176 enum stmmac_fpe_state lp_fpe_state; /* Link Partner FPE state */176 enum stmmac_fpe_state lp_fpe_state; /* Link Partner FPE state */
177 enum stmmac_fpe_state lo_fpe_state; /* Local station FPE state */177 enum stmmac_fpe_state lo_fpe_state; /* Local station FPE state */
178 u32 fpe_csr; /* MAC_FPE_CTRL_STS reg cache */
178};179};
179 180
180struct stmmac_safety_feature_cfg {181struct stmmac_safety_feature_cfg {