Skip to content

Commit

Permalink
r8152: avoid to resubmit rx immediately
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
hayesorz authored and davem330 committed Oct 5, 2021
1 parent 3f6cffb commit baf33d7
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion drivers/net/usb/r8152.c
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,7 @@ enum rtl8152_flags {
PHY_RESET,
SCHEDULE_TASKLET,
GREEN_ETHERNET,
RX_EPROTO,
};

#define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2 0x3082
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit baf33d7

Please sign in to comment.