Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78ece0b9 authored by Larry Finger's avatar Larry Finger Committed by Greg Kroah-Hartman
Browse files

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: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 74a3b060
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
	if (!precvbuf->purb)
		res = _FAIL;
	precvbuf->pskb = NULL;
	precvbuf->reuse = false;
	precvbuf->pallocated_buf = NULL;
	precvbuf->pbuf = NULL;
	precvbuf->pdata = NULL;
+0 −1
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ struct recv_buf {
	struct _adapter  *adapter;
	struct urb *purb;
	_pkt *pskb;
	u8 reuse;
	u8  irp_pending;
	u32  transfer_len;
	uint  len;
+8 −16
Original line number Diff line number Diff line
@@ -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 */