1 From b3da86d432b7cd65b025a11f68613e333d2483db Mon Sep 17 00:00:00 2001
2 From: Piotr Wejman <piotrwejman90@gmail.com>
3 Date: Mon, 1 Apr 2024 21:22:39 +0200
4 Subject: net: stmmac: fix rx queue priority assignment
6 From: Piotr Wejman <piotrwejman90@gmail.com>
8 commit b3da86d432b7cd65b025a11f68613e333d2483db upstream.
10 The driver should ensure that same priority is not mapped to multiple
11 rx queues. From DesignWare Cores Ethernet Quality-of-Service
12 Databook, section 17.1.29 MAC_RxQ_Ctrl2:
13 "[...]The software must ensure that the content of this field is
14 mutually exclusive to the PSRQ fields for other queues, that is,
15 the same priority is not mapped to multiple Rx queues[...]"
17 Previously rx_queue_priority() function was:
18 - clearing all priorities from a queue
19 - adding new priorities to that queue
20 After this patch it will:
21 - first assign new priorities to a queue
22 - then remove those priorities from all other queues
23 - keep other priorities previously assigned to that queue
25 Fixes: a8f5102af2a7 ("net: stmmac: TX and RX queue priority configuration")
26 Fixes: 2142754f8b9c ("net: stmmac: Add MAC related callbacks for XGMAC2")
27 Signed-off-by: Piotr Wejman <piotrwejman90@gmail.com>
28 Link: https://lore.kernel.org/r/20240401192239.33942-1-piotrwejman90@gmail.com
29 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
30 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 40 +++++++++++++++-----
33 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 38 +++++++++++++++----
34 2 files changed, 62 insertions(+), 16 deletions(-)
36 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
37 +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
38 @@ -87,19 +87,41 @@ static void dwmac4_rx_queue_priority(str
41 void __iomem *ioaddr = hw->pcsr;
48 - base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;
51 + ctrl2 = readl(ioaddr + GMAC_RXQ_CTRL2);
52 + ctrl3 = readl(ioaddr + GMAC_RXQ_CTRL3);
54 + /* The software must ensure that the same priority
55 + * is not mapped to multiple Rx queues
57 + for (i = 0; i < 4; i++)
58 + clear_mask |= ((prio << GMAC_RXQCTRL_PSRQX_SHIFT(i)) &
59 + GMAC_RXQCTRL_PSRQX_MASK(i));
61 - value = readl(ioaddr + base_register);
62 + ctrl2 &= ~clear_mask;
63 + ctrl3 &= ~clear_mask;
65 - value &= ~GMAC_RXQCTRL_PSRQX_MASK(queue);
66 - value |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
67 + /* First assign new priorities to a queue, then
68 + * clear them from others queues
71 + ctrl2 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
72 GMAC_RXQCTRL_PSRQX_MASK(queue);
73 - writel(value, ioaddr + base_register);
75 + writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2);
76 + writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3);
80 + ctrl3 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
81 + GMAC_RXQCTRL_PSRQX_MASK(queue);
83 + writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3);
84 + writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2);
88 static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
89 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
90 +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
91 @@ -97,17 +97,41 @@ static void dwxgmac2_rx_queue_prio(struc
94 void __iomem *ioaddr = hw->pcsr;
100 - reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
102 + ctrl2 = readl(ioaddr + XGMAC_RXQ_CTRL2);
103 + ctrl3 = readl(ioaddr + XGMAC_RXQ_CTRL3);
105 + /* The software must ensure that the same priority
106 + * is not mapped to multiple Rx queues
108 + for (i = 0; i < 4; i++)
109 + clear_mask |= ((prio << XGMAC_PSRQ_SHIFT(i)) &
112 + ctrl2 &= ~clear_mask;
113 + ctrl3 &= ~clear_mask;
115 + /* First assign new priorities to a queue, then
116 + * clear them from others queues
119 + ctrl2 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
122 + writel(ctrl2, ioaddr + XGMAC_RXQ_CTRL2);
123 + writel(ctrl3, ioaddr + XGMAC_RXQ_CTRL3);
127 - value = readl(ioaddr + reg);
128 - value &= ~XGMAC_PSRQ(queue);
129 - value |= (prio << XGMAC_PSRQ_SHIFT(queue)) & XGMAC_PSRQ(queue);
130 + ctrl3 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
133 - writel(value, ioaddr + reg);
134 + writel(ctrl3, ioaddr + XGMAC_RXQ_CTRL3);
135 + writel(ctrl2, ioaddr + XGMAC_RXQ_CTRL2);
139 static void dwxgmac2_tx_queue_prio(struct mac_device_info *hw, u32 prio,