r8152: avoid to resubmit rx immediately
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>
This commit is contained in:
parent
3f6cffb860
commit
baf33d7a75
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user