Skip to content

Commit 0f5046a

Browse files
LorenzoBianconigregkh
authored andcommitted
mt7601u: fix possible memory leak when the device is disconnected
[ Upstream commit 23377c2 ] When the device is disconnected while passing traffic it is possible to receive out of order urbs causing a memory leak since the skb linked to the current tx urb is not removed. Fix the issue deallocating the skb cleaning up the tx ring. Moreover this patch fixes the following kernel warning [ 57.480771] usb 1-1: USB disconnect, device number 2 [ 57.483451] ------------[ cut here ]------------ [ 57.483462] TX urb mismatch [ 57.483481] WARNING: CPU: 1 PID: 32 at drivers/net/wireless/mediatek/mt7601u/dma.c:245 mt7601u_complete_tx+0x165/00 [ 57.483483] Modules linked in: [ 57.483496] CPU: 1 PID: 32 Comm: kworker/1:1 Not tainted 5.2.0-rc1+ raspberrypi#72 [ 57.483498] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.12.0-2.fc30 04/01/2014 [ 57.483502] Workqueue: usb_hub_wq hub_event [ 57.483507] RIP: 0010:mt7601u_complete_tx+0x165/0x1e0 [ 57.483510] Code: 8b b5 10 04 00 00 8b 8d 14 04 00 00 eb 8b 80 3d b1 cb e1 00 00 75 9e 48 c7 c7 a4 ea 05 82 c6 05 f [ 57.483513] RSP: 0000:ffffc900000a0d28 EFLAGS: 00010092 [ 57.483516] RAX: 000000000000000f RBX: ffff88802c0a62c0 RCX: ffffc900000a0c2c [ 57.483518] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff810a8371 [ 57.483520] RBP: ffff88803ced6858 R08: 0000000000000000 R09: 0000000000000001 [ 57.483540] R10: 0000000000000002 R11: 0000000000000000 R12: 0000000000000046 [ 57.483542] R13: ffff88802c0a6c88 R14: ffff88803baab540 R15: ffff88803a0cc078 [ 57.483548] FS: 0000000000000000(0000) GS:ffff88803eb00000(0000) knlGS:0000000000000000 [ 57.483550] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 57.483552] CR2: 000055e7f6780100 CR3: 0000000028c86000 CR4: 00000000000006a0 [ 57.483554] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 57.483556] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 57.483559] Call Trace: [ 57.483561] <IRQ> [ 57.483565] __usb_hcd_giveback_urb+0x77/0xe0 [ 57.483570] xhci_giveback_urb_in_irq.isra.0+0x8b/0x140 [ 57.483574] handle_cmd_completion+0xf5b/0x12c0 [ 57.483577] xhci_irq+0x1f6/0x1810 [ 57.483581] ? lockdep_hardirqs_on+0x9e/0x180 [ 57.483584] ? _raw_spin_unlock_irq+0x24/0x30 [ 57.483588] __handle_irq_event_percpu+0x3a/0x260 [ 57.483592] handle_irq_event_percpu+0x1c/0x60 [ 57.483595] handle_irq_event+0x2f/0x4c [ 57.483599] handle_edge_irq+0x7e/0x1a0 [ 57.483603] handle_irq+0x17/0x20 [ 57.483607] do_IRQ+0x54/0x110 [ 57.483610] common_interrupt+0xf/0xf [ 57.483612] </IRQ> Acked-by: Jakub Kicinski <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Kalle Valo <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent df324ba commit 0f5046a

File tree

2 files changed

+18
-7
lines changed
  • drivers/net/wireless/mediatek/mt7601u

2 files changed

+18
-7
lines changed

drivers/net/wireless/mediatek/mt7601u/dma.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,14 +233,25 @@ static void mt7601u_complete_tx(struct urb *urb)
233233
struct sk_buff *skb;
234234
unsigned long flags;
235235

236-
spin_lock_irqsave(&dev->tx_lock, flags);
236+
switch (urb->status) {
237+
case -ECONNRESET:
238+
case -ESHUTDOWN:
239+
case -ENOENT:
240+
return;
241+
default:
242+
dev_err_ratelimited(dev->dev, "tx urb failed: %d\n",
243+
urb->status);
244+
/* fall through */
245+
case 0:
246+
break;
247+
}
237248

238-
if (mt7601u_urb_has_error(urb))
239-
dev_err(dev->dev, "Error: TX urb failed:%d\n", urb->status);
249+
spin_lock_irqsave(&dev->tx_lock, flags);
240250
if (WARN_ONCE(q->e[q->start].urb != urb, "TX urb mismatch"))
241251
goto out;
242252

243253
skb = q->e[q->start].skb;
254+
q->e[q->start].skb = NULL;
244255
trace_mt_tx_dma_done(dev, skb);
245256

246257
__skb_queue_tail(&dev->tx_skb_done, skb);
@@ -440,10 +451,10 @@ static void mt7601u_free_tx_queue(struct mt7601u_tx_queue *q)
440451
{
441452
int i;
442453

443-
WARN_ON(q->used);
444-
445454
for (i = 0; i < q->entries; i++) {
446455
usb_poison_urb(q->e[i].urb);
456+
if (q->e[i].skb)
457+
mt7601u_tx_status(q->dev, q->e[i].skb);
447458
usb_free_urb(q->e[i].urb);
448459
}
449460
}

drivers/net/wireless/mediatek/mt7601u/tx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ void mt7601u_tx_status(struct mt7601u_dev *dev, struct sk_buff *skb)
109109
info->status.rates[0].idx = -1;
110110
info->flags |= IEEE80211_TX_STAT_ACK;
111111

112-
spin_lock(&dev->mac_lock);
112+
spin_lock_bh(&dev->mac_lock);
113113
ieee80211_tx_status(dev->hw, skb);
114-
spin_unlock(&dev->mac_lock);
114+
spin_unlock_bh(&dev->mac_lock);
115115
}
116116

117117
static int mt7601u_skb_rooms(struct mt7601u_dev *dev, struct sk_buff *skb)

0 commit comments

Comments
 (0)