2023-04-27 12:13:17

by Hayes Wang

[permalink] [raw]
Subject: [PATCH net v2 1/3] r8152: fix flow control issue of RTL8156A

The feature of flow control becomes abnormal, if the device sends a
pause frame and the tx/rx is disabled before sending a release frame. It
causes the lost of packets.

Set PLA_RX_FIFO_FULL and PLA_RX_FIFO_EMPTY to zeros before disabling the
tx/rx. And, toggle FC_PATCH_TASK before enabling tx/rx to reset the flow
control patch and timer. Then, the hardware could clear the state and
the flow control becomes normal after enabling tx/rx.

Besides, remove inline for fc_pause_on_auto() and fc_pause_off_auto().

Fixes: 195aae321c82 ("r8152: support new chips")
Signed-off-by: Hayes Wang <[email protected]>
---
drivers/net/usb/r8152.c | 56 ++++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 20 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0fc4b959edc1..afd50e90d1fe 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -5986,6 +5986,25 @@ static void rtl8153_disable(struct r8152 *tp)
r8153_aldps_en(tp, true);
}

+static u32 fc_pause_on_auto(struct r8152 *tp)
+{
+ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024);
+}
+
+static u32 fc_pause_off_auto(struct r8152 *tp)
+{
+ return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024);
+}
+
+static void r8156_fc_parameter(struct r8152 *tp)
+{
+ u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp);
+ u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp);
+
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16);
+}
+
static int rtl8156_enable(struct r8152 *tp)
{
u32 ocp_data;
@@ -5994,6 +6013,7 @@ static int rtl8156_enable(struct r8152 *tp)
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return -ENODEV;

+ r8156_fc_parameter(tp);
set_tx_qlen(tp);
rtl_set_eee_plus(tp);
r8153_set_rx_early_timeout(tp);
@@ -6025,9 +6045,24 @@ static int rtl8156_enable(struct r8152 *tp)
ocp_write_word(tp, MCU_TYPE_USB, USB_L1_CTRL, ocp_data);
}

+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_FW_TASK);
+ ocp_data &= ~FC_PATCH_TASK;
+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+ usleep_range(1000, 2000);
+ ocp_data |= FC_PATCH_TASK;
+ ocp_write_word(tp, MCU_TYPE_USB, USB_FW_TASK, ocp_data);
+
return rtl_enable(tp);
}

+static void rtl8156_disable(struct r8152 *tp)
+{
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, 0);
+ ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, 0);
+
+ rtl8153_disable(tp);
+}
+
static int rtl8156b_enable(struct r8152 *tp)
{
u32 ocp_data;
@@ -6429,25 +6464,6 @@ static void rtl8153c_up(struct r8152 *tp)
r8153b_u1u2en(tp, true);
}

-static inline u32 fc_pause_on_auto(struct r8152 *tp)
-{
- return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 6 * 1024);
-}
-
-static inline u32 fc_pause_off_auto(struct r8152 *tp)
-{
- return (ALIGN(mtu_to_size(tp->netdev->mtu), 1024) + 14 * 1024);
-}
-
-static void r8156_fc_parameter(struct r8152 *tp)
-{
- u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp);
- u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp);
-
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16);
- ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16);
-}
-
static void rtl8156_change_mtu(struct r8152 *tp)
{
u32 rx_max_size = mtu_to_size(tp->netdev->mtu);
@@ -9340,7 +9356,7 @@ static int rtl_ops_init(struct r8152 *tp)
case RTL_VER_10:
ops->init = r8156_init;
ops->enable = rtl8156_enable;
- ops->disable = rtl8153_disable;
+ ops->disable = rtl8156_disable;
ops->up = rtl8156_up;
ops->down = rtl8156_down;
ops->unload = rtl8153_unload;
--
2.40.0


2023-04-27 12:36:17

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net v2 1/3] r8152: fix flow control issue of RTL8156A

On Thu, Apr 27, 2023 at 08:10:55PM +0800, Hayes Wang wrote:
> The feature of flow control becomes abnormal, if the device sends a
> pause frame and the tx/rx is disabled before sending a release frame. It
> causes the lost of packets.
>
> Set PLA_RX_FIFO_FULL and PLA_RX_FIFO_EMPTY to zeros before disabling the
> tx/rx. And, toggle FC_PATCH_TASK before enabling tx/rx to reset the flow
> control patch and timer. Then, the hardware could clear the state and
> the flow control becomes normal after enabling tx/rx.
>
> Besides, remove inline for fc_pause_on_auto() and fc_pause_off_auto().
>
> Fixes: 195aae321c82 ("r8152: support new chips")
> Signed-off-by: Hayes Wang <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew