Skip to content

Commit 37e4b8d

Browse files
Jianheng Zhangkuba-moo
authored andcommitted
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. Fixes: 5a55861 ("net: stmmac: support FPE link partner hand-shaking procedure") Reviewed-by: Serge Semin <fancer.lancer@gmail.com> Signed-off-by: Jianheng Zhang <Jianheng.Zhang@synopsys.com> Link: https://lore.kernel.org/r/CY5PR12MB637225A7CF529D5BE0FBE59CBF81A@CY5PR12MB6372.namprd12.prod.outlook.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent adbf100 commit 37e4b8d

7 files changed

Lines changed: 36 additions & 30 deletions

File tree

drivers/net/ethernet/stmicro/stmmac/dwmac5.c

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -710,28 +710,22 @@ void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
710710
}
711711
}
712712

713-
void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
713+
void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
714+
u32 num_txq, u32 num_rxq,
714715
bool enable)
715716
{
716717
u32 value;
717718

718-
if (!enable) {
719-
value = readl(ioaddr + MAC_FPE_CTRL_STS);
720-
721-
value &= ~EFPE;
722-
723-
writel(value, ioaddr + MAC_FPE_CTRL_STS);
724-
return;
719+
if (enable) {
720+
cfg->fpe_csr = EFPE;
721+
value = readl(ioaddr + GMAC_RXQ_CTRL1);
722+
value &= ~GMAC_RXQCTRL_FPRQ;
723+
value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
724+
writel(value, ioaddr + GMAC_RXQ_CTRL1);
725+
} else {
726+
cfg->fpe_csr = 0;
725727
}
726-
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);
728+
writel(cfg->fpe_csr, ioaddr + MAC_FPE_CTRL_STS);
735729
}
736730

737731
int 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)
741735

742736
status = FPE_EVENT_UNKNOWN;
743737

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+
*/
744741
value = readl(ioaddr + MAC_FPE_CTRL_STS);
745742

746743
if (value & TRSP) {
@@ -766,19 +763,15 @@ int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)
766763
return status;
767764
}
768765

769-
void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, enum stmmac_mpacket_type type)
766+
void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
767+
enum stmmac_mpacket_type type)
770768
{
771-
u32 value;
769+
u32 value = cfg->fpe_csr;
772770

773-
value = readl(ioaddr + MAC_FPE_CTRL_STS);
774-
775-
if (type == MPACKET_VERIFY) {
776-
value &= ~SRSP;
771+
if (type == MPACKET_VERIFY)
777772
value |= SVER;
778-
} else {
779-
value &= ~SVER;
773+
else if (type == MPACKET_RESPONSE)
780774
value |= SRSP;
781-
}
782775

783776
writel(value, ioaddr + MAC_FPE_CTRL_STS);
784777
}

drivers/net/ethernet/stmicro/stmmac/dwmac5.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,11 @@ int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
153153
unsigned int ptp_rate);
154154
void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
155155
struct stmmac_extra_stats *x, u32 txqcnt);
156-
void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
156+
void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
157+
u32 num_txq, u32 num_rxq,
157158
bool enable);
158159
void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
160+
struct stmmac_fpe_cfg *cfg,
159161
enum stmmac_mpacket_type type);
160162
int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);
161163

drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,8 @@ static int dwxgmac3_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
14841484
return 0;
14851485
}
14861486

1487-
static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq,
1487+
static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
1488+
u32 num_txq,
14881489
u32 num_rxq, bool enable)
14891490
{
14901491
u32 value;

drivers/net/ethernet/stmicro/stmmac/hwif.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,9 +412,11 @@ struct stmmac_ops {
412412
unsigned int ptp_rate);
413413
void (*est_irq_status)(void __iomem *ioaddr, struct net_device *dev,
414414
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,
416417
bool enable);
417418
void (*fpe_send_mpacket)(void __iomem *ioaddr,
419+
struct stmmac_fpe_cfg *cfg,
418420
enum stmmac_mpacket_type type);
419421
int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev);
420422
};

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,8 @@ static void stmmac_fpe_link_state_handle(struct stmmac_priv *priv, bool is_up)
964964
bool *hs_enable = &fpe_cfg->hs_enable;
965965

966966
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);
968969
} else {
969970
*lo_state = FPE_STATE_OFF;
970971
*lp_state = FPE_STATE_OFF;
@@ -5839,6 +5840,7 @@ static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
58395840
/* If user has requested FPE enable, quickly response */
58405841
if (*hs_enable)
58415842
stmmac_fpe_send_mpacket(priv, priv->ioaddr,
5843+
fpe_cfg,
58425844
MPACKET_RESPONSE);
58435845
}
58445846

@@ -7263,6 +7265,7 @@ static void stmmac_fpe_lp_task(struct work_struct *work)
72637265
if (*lo_state == FPE_STATE_ENTERING_ON &&
72647266
*lp_state == FPE_STATE_ENTERING_ON) {
72657267
stmmac_fpe_configure(priv, priv->ioaddr,
7268+
fpe_cfg,
72667269
priv->plat->tx_queues_to_use,
72677270
priv->plat->rx_queues_to_use,
72687271
*enable);
@@ -7281,6 +7284,7 @@ static void stmmac_fpe_lp_task(struct work_struct *work)
72817284
netdev_info(priv->dev, SEND_VERIFY_MPAKCET_FMT,
72827285
*lo_state, *lp_state);
72837286
stmmac_fpe_send_mpacket(priv, priv->ioaddr,
7287+
fpe_cfg,
72847288
MPACKET_VERIFY);
72857289
}
72867290
/* Sleep then retry */
@@ -7295,6 +7299,7 @@ void stmmac_fpe_handshake(struct stmmac_priv *priv, bool enable)
72957299
if (priv->plat->fpe_cfg->hs_enable != enable) {
72967300
if (enable) {
72977301
stmmac_fpe_send_mpacket(priv, priv->ioaddr,
7302+
priv->plat->fpe_cfg,
72987303
MPACKET_VERIFY);
72997304
} else {
73007305
priv->plat->fpe_cfg->lo_fpe_state = FPE_STATE_OFF;
@@ -7755,6 +7760,7 @@ int stmmac_suspend(struct device *dev)
77557760
if (priv->dma_cap.fpesel) {
77567761
/* Disable FPE */
77577762
stmmac_fpe_configure(priv, priv->ioaddr,
7763+
priv->plat->fpe_cfg,
77587764
priv->plat->tx_queues_to_use,
77597765
priv->plat->rx_queues_to_use, false);
77607766

drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
10791079

10801080
priv->plat->fpe_cfg->enable = false;
10811081
stmmac_fpe_configure(priv, priv->ioaddr,
1082+
priv->plat->fpe_cfg,
10821083
priv->plat->tx_queues_to_use,
10831084
priv->plat->rx_queues_to_use,
10841085
false);

include/linux/stmmac.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ struct stmmac_fpe_cfg {
175175
bool hs_enable; /* FPE handshake enable */
176176
enum stmmac_fpe_state lp_fpe_state; /* Link Partner FPE state */
177177
enum stmmac_fpe_state lo_fpe_state; /* Local station FPE state */
178+
u32 fpe_csr; /* MAC_FPE_CTRL_STS reg cache */
178179
};
179180

180181
struct stmmac_safety_feature_cfg {

0 commit comments

Comments
 (0)