diff options
author | Howard Yen <howardyen@google.com> | 2021-08-17 00:17:29 +0800 |
---|---|---|
committer | Howard Yen <howardyen@google.com> | 2021-08-17 04:23:33 +0000 |
commit | 189997f1bc3dfcf6122221f482435d5c7761d2cc (patch) | |
tree | 52ed38a06232205d73f0b03b19597b7330882821 | |
parent | 11938884ed7a568cb40fcd65830e0ff805baa0b4 (diff) | |
download | aoc-189997f1bc3dfcf6122221f482435d5c7761d2cc.tar.gz |
aoc: usb: fix memory leakage in usb audio usecase
When the endpoint is not changed during allocating the bandwidth, xhci
driver free the old transfer ring and replace with the new one, the
leakage comes from setting the new ring to NULL when free the old ring.
Don't set the new ring to NULL in the condition to avoid memory leakage.
Bug: 196363789
Test: build and boot pass
Change-Id: I95532a84a0d285cbb55b55e9c5e0af3430698d16
Signed-off-by: Howard Yen <howardyen@google.com>
-rw-r--r-- | usb/xhci_hooks_impl_whi.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/usb/xhci_hooks_impl_whi.c b/usb/xhci_hooks_impl_whi.c index 6bb9a95..e58bdde 100644 --- a/usb/xhci_hooks_impl_whi.c +++ b/usb/xhci_hooks_impl_whi.c @@ -742,22 +742,39 @@ static struct xhci_ring *alloc_transfer_ring(struct xhci_hcd *xhci, return ep_ring; } +struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx) +{ + if (ctx->type != XHCI_CTX_TYPE_INPUT) + return NULL; + + return (struct xhci_input_control_ctx *)ctx->bytes; +} + static void free_transfer_ring(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, unsigned int ep_index) { struct xhci_vendor_data *vendor_data = xhci_to_priv(xhci)->vendor_data; struct xhci_ring *ring, *new_ring; struct xhci_ep_ctx *ep_ctx; + struct xhci_input_control_ctx *ctrl_ctx; u32 ep_type; + u32 ep_is_added, ep_is_dropped; ring = virt_dev->eps[ep_index].ring; new_ring = virt_dev->eps[ep_index].new_ring; ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->out_ctx, ep_index); ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2)); + ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); + ep_is_added = EP_IS_ADDED(ctrl_ctx, ep_index); + ep_is_dropped = EP_IS_DROPPED(ctrl_ctx, ep_index); + + xhci_dbg(xhci, "%s: ep %u is added(0x%x), is dropped(0x%x)\n", __func__, ep_index, + ep_is_added, ep_is_dropped); + if (ring) { - xhci_dbg(xhci, "%s: ep_index=%u, ep_type=%u, ring type=%u\n", __func__, ep_index, - ep_type, ring->type); + xhci_dbg(xhci, "%s: ep_index=%u, ep_type=%u, ring type=%u, new_ring=%pK\n", + __func__, ep_index, ep_type, ring->type, new_ring); if (vendor_data->op_mode == USB_OFFLOAD_SIMPLE_AUDIO_ACCESSORY && ring->type == TYPE_ISOC) { @@ -767,9 +784,9 @@ static void free_transfer_ring(struct xhci_hcd *xhci, xhci_ring_free(xhci, virt_dev->eps[ep_index].ring); virt_dev->eps[ep_index].ring = NULL; - virt_dev->eps[ep_index].new_ring = NULL; - return; + if (ep_is_added == 0 && ep_is_dropped == 0) + return; } if (new_ring) { |