lkml.org 
[lkml]   [2021]   [Oct]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.14 008/169] r8152: avoid to resubmit rx immediately
    Date
    From: Hayes Wang <hayeswang@realtek.com>

    [ Upstream commit baf33d7a75642b4b38a87fdf1cd96b506df4849f ]

    For the situation that the disconnect event comes very late when the
    device is unplugged, the driver would resubmit the RX bulk transfer
    after getting the callback with -EPROTO immediately and continually.
    Finally, soft lockup occurs.

    This patch avoids to resubmit RX immediately. It uses a workqueue to
    schedule the RX NAPI. And the NAPI would resubmit the RX. It let the
    disconnect event have opportunity to stop the submission before soft
    lockup.

    Reported-by: Jason-ch Chen <jason-ch.chen@mediatek.com>
    Tested-by: Jason-ch Chen <jason-ch.chen@mediatek.com>
    Signed-off-by: Hayes Wang <hayeswang@realtek.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/usb/r8152.c | 16 +++++++++++++++-
    1 file changed, 15 insertions(+), 1 deletion(-)

    diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
    index 79832374f78d..92fca5e9ed03 100644
    --- a/drivers/net/usb/r8152.c
    +++ b/drivers/net/usb/r8152.c
    @@ -767,6 +767,7 @@ enum rtl8152_flags {
    PHY_RESET,
    SCHEDULE_TASKLET,
    GREEN_ETHERNET,
    + RX_EPROTO,
    };

    #define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2 0x3082
    @@ -1770,6 +1771,14 @@ static void read_bulk_callback(struct urb *urb)
    rtl_set_unplug(tp);
    netif_device_detach(tp->netdev);
    return;
    + case -EPROTO:
    + urb->actual_length = 0;
    + spin_lock_irqsave(&tp->rx_lock, flags);
    + list_add_tail(&agg->list, &tp->rx_done);
    + spin_unlock_irqrestore(&tp->rx_lock, flags);
    + set_bit(RX_EPROTO, &tp->flags);
    + schedule_delayed_work(&tp->schedule, 1);
    + return;
    case -ENOENT:
    return; /* the urb is in unlink state */
    case -ETIME:
    @@ -2425,6 +2434,7 @@ static int rx_bottom(struct r8152 *tp, int budget)
    if (list_empty(&tp->rx_done))
    goto out1;

    + clear_bit(RX_EPROTO, &tp->flags);
    INIT_LIST_HEAD(&rx_queue);
    spin_lock_irqsave(&tp->rx_lock, flags);
    list_splice_init(&tp->rx_done, &rx_queue);
    @@ -2441,7 +2451,7 @@ static int rx_bottom(struct r8152 *tp, int budget)

    agg = list_entry(cursor, struct rx_agg, list);
    urb = agg->urb;
    - if (urb->actual_length < ETH_ZLEN)
    + if (urb->status != 0 || urb->actual_length < ETH_ZLEN)
    goto submit;

    agg_free = rtl_get_free_rx(tp, GFP_ATOMIC);
    @@ -6643,6 +6653,10 @@ static void rtl_work_func_t(struct work_struct *work)
    netif_carrier_ok(tp->netdev))
    tasklet_schedule(&tp->tx_tl);

    + if (test_and_clear_bit(RX_EPROTO, &tp->flags) &&
    + !list_empty(&tp->rx_done))
    + napi_schedule(&tp->napi);
    +
    mutex_unlock(&tp->control);

    out1:
    --
    2.33.0


    \
     
     \ /
      Last update: 2021-10-25 21:48    [W:4.188 / U:0.528 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site