summaryrefslogtreecommitdiff
path: root/drivers/staging/rtl8712/usb_ops_linux.c
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2016-06-03 20:17:36 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-21 18:28:49 +0200
commit78ece0b94518816f08f4e60fae62d078aa4cb63d (patch)
tree13f3ec387b5ca9b260c250a22f0956a8601d1b1b /drivers/staging/rtl8712/usb_ops_linux.c
parent74a3b060bc29851d7caf42b9c8c3c1129fd50553 (diff)
staging: r8712u: Fix leak of skb
There are two types of messages queued for RX. The major type, which does I/O on the device, was being handled properly. The skbs that communicated with the firmware were being leaked. While rewriting the code that sets up the skb, it was possible to remove the private variable indicating that the old skb could be reused. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/rtl8712/usb_ops_linux.c')
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c24
1 files changed, 8 insertions, 16 deletions
diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
index 0f39ea8df689..fc6bb0be2a28 100644
--- a/drivers/staging/rtl8712/usb_ops_linux.c
+++ b/drivers/staging/rtl8712/usb_ops_linux.c
@@ -202,26 +202,23 @@ static void r8712_usb_read_port_complete(struct urb *purb)
if (purb->status == 0) { /* SUCCESS */
if ((purb->actual_length > (MAX_RECVBUF_SZ)) ||
(purb->actual_length < RXDESC_SIZE)) {
- precvbuf->reuse = true;
r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
(unsigned char *)precvbuf);
} else {
+ _pkt *pskb = precvbuf->pskb;
+
precvbuf->transfer_len = purb->actual_length;
pbuf = (uint *)precvbuf->pbuf;
isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff;
if ((isevt & 0x1ff) == 0x1ff) {
r8712_rxcmd_event_hdl(padapter, pbuf);
- precvbuf->reuse = true;
+ skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
r8712_read_port(padapter, precvpriv->ff_hwaddr,
0, (unsigned char *)precvbuf);
} else {
- _pkt *pskb = precvbuf->pskb;
-
skb_put(pskb, purb->actual_length);
skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
tasklet_hi_schedule(&precvpriv->recv_tasklet);
- precvbuf->pskb = NULL;
- precvbuf->reuse = false;
r8712_read_port(padapter, precvpriv->ff_hwaddr,
0, (unsigned char *)precvbuf);
}
@@ -241,7 +238,6 @@ static void r8712_usb_read_port_complete(struct urb *purb)
}
/* Fall through. */
case -EPROTO:
- precvbuf->reuse = true;
r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
(unsigned char *)precvbuf);
break;
@@ -272,14 +268,11 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf)
return _FAIL;
- if (precvbuf->reuse || !precvbuf->pskb) {
- precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
- if (precvbuf->pskb != NULL)
- precvbuf->reuse = true;
- }
r8712_init_recvbuf(adapter, precvbuf);
- /* re-assign for linux based on skb */
- if (!precvbuf->reuse || !precvbuf->pskb) {
+ /* Try to use skb from the free queue */
+ precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
+
+ if (!precvbuf->pskb) {
precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev,
MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
if (!precvbuf->pskb)
@@ -293,13 +286,12 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
precvbuf->pend = skb_end_pointer(precvbuf->pskb);
precvbuf->pbuf = precvbuf->pskb->data;
- } else { /* reuse skb */
+ } else { /* skb is reused */
precvbuf->phead = precvbuf->pskb->head;
precvbuf->pdata = precvbuf->pskb->data;
precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
precvbuf->pend = skb_end_pointer(precvbuf->pskb);
precvbuf->pbuf = precvbuf->pskb->data;
- precvbuf->reuse = false;
}
purb = precvbuf->purb;
/* translate DMA FIFO addr to pipehandle */