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

Commit afe3bc4b authored by Dov Levenglick's avatar Dov Levenglick
Browse files

usb: gadget: Free UL buffers in gbam_disconnect() for RMNET



On certain devices, the (device) OUT ep are connected sys2bam
vs. the IPA. Towards supporting this, buffers are allocated in
memory to pass from the USB to the IPA. When gbam_disconnect()
is called for the RMNET function, we need to free all the
RX buffers used for the UL path in order to avoid a memory leak.

Change-Id: Ia9ec11241ca90c62f9e38f4ba29830197a7f69af
Signed-off-by: default avatarDanny Segal <dsegal@codeaurora.org>
Signed-off-by: default avatarDov Levenglick <dovl@codeaurora.org>
parent 500bff85
Loading
Loading
Loading
Loading
+32 −10
Original line number Diff line number Diff line
@@ -871,36 +871,56 @@ static void gbam_notify(void *p, int event, unsigned long data)
	}
}

static void gbam_free_buffers(struct gbam_port *port)
static void gbam_free_rx_buffers(struct gbam_port *port)
{
	struct sk_buff		*skb;
	unsigned long		flags;
	struct bam_ch_info	*d;

	spin_lock_irqsave(&port->port_lock_ul, flags);
	spin_lock(&port->port_lock_dl);

	if (!port || !port->port_usb)
		goto free_buf_out;
		goto free_rx_buf_out;

	d = &port->data_ch;

	gbam_free_requests(port->port_usb->in, &d->tx_idle);
	gbam_free_requests(port->port_usb->out, &d->rx_idle);

	while ((skb = __skb_dequeue(&d->tx_skb_q)))
		dev_kfree_skb_any(skb);

	while ((skb = __skb_dequeue(&d->rx_skb_q)))
		dev_kfree_skb_any(skb);

	gbam_free_rx_skb_idle_list(port);

free_buf_out:
	spin_unlock(&port->port_lock_dl);
free_rx_buf_out:
	spin_unlock_irqrestore(&port->port_lock_ul, flags);
}

static void gbam_free_tx_buffers(struct gbam_port *port)
{
	struct sk_buff		*skb;
	unsigned long		flags;
	struct bam_ch_info	*d;

	spin_lock_irqsave(&port->port_lock_dl, flags);

	if (!port || !port->port_usb)
		goto free_tx_buf_out;

	d = &port->data_ch;
	gbam_free_requests(port->port_usb->in, &d->tx_idle);

	while ((skb = __skb_dequeue(&d->tx_skb_q)))
		dev_kfree_skb_any(skb);

free_tx_buf_out:
	spin_unlock_irqrestore(&port->port_lock_dl, flags);
}

static void gbam_free_buffers(struct gbam_port *port)
{
	gbam_free_rx_buffers(port);
	gbam_free_tx_buffers(port);
}

static void gbam_disconnect_work(struct work_struct *w)
{
	struct gbam_port *port =
@@ -1636,6 +1656,8 @@ void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans)

	if (trans == USB_GADGET_XPORT_BAM)
		gbam_free_buffers(port);
	else if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
		gbam_free_rx_buffers(port);

	spin_lock_irqsave(&port->port_lock_ul, flags);
	spin_lock(&port->port_lock_dl);