ACRN:DM Release resource when destroy the device

When destroy the usb device release the resource allocate for transfer
in case cause the memory leak issue. Add the release and cancel
transfer request call back for the emulation device, use the emulation
device call back in xHCI controller emulation.

Tracked-On: #6533
Signed-off-by: Liu Long <long.liu@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Liu Long 2021-09-01 16:45:07 +08:00 committed by wenlingz
parent f45344b6bc
commit a0b3f1cfc8
4 changed files with 53 additions and 20 deletions

View File

@ -481,7 +481,7 @@ static int pci_xhci_parse_tablet(struct pci_xhci_vdev *xdev, char *opts);
static int pci_xhci_parse_log_level(struct pci_xhci_vdev *xdev, char *opts);
static int pci_xhci_parse_extcap(struct pci_xhci_vdev *xdev, char *opts);
static int pci_xhci_convert_speed(int lspeed);
static void pci_xhci_free_usb_xfer(struct usb_xfer *xfer);
static void pci_xhci_free_usb_xfer(struct pci_xhci_dev_emu *dev, struct usb_xfer *xfer);
static void pci_xhci_isoc_handler(void *arg, uint64_t param);
#define XHCI_OPT_MAX_LEN 32
@ -1006,15 +1006,17 @@ pci_xhci_dev_create(struct pci_xhci_vdev *xdev, void *dev_data)
* function interface should be changed and refined
* in future.
*/
ue->ue_init = usb_dev_init;
ue->ue_request = usb_dev_request;
ue->ue_data = usb_dev_data;
ue->ue_info = usb_dev_info;
ue->ue_reset = usb_dev_reset;
ue->ue_remove = NULL;
ue->ue_stop = NULL;
ue->ue_deinit = usb_dev_deinit;
ue->ue_devtype = USB_DEV_PORT_MAPPER;
ue->ue_init = usb_dev_init;
ue->ue_request = usb_dev_request;
ue->ue_data = usb_dev_data;
ue->ue_info = usb_dev_info;
ue->ue_reset = usb_dev_reset;
ue->ue_remove = NULL;
ue->ue_stop = NULL;
ue->ue_cancel_req = usb_dev_cancel_request;
ue->ue_free_req = usb_dev_free_request;
ue->ue_deinit = usb_dev_deinit;
ue->ue_devtype = USB_DEV_PORT_MAPPER;
ud = ue->ue_init(dev_data, NULL);
if (!ud)
@ -1072,16 +1074,16 @@ pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de)
} else
return;
if (ue->ue_devtype == USB_DEV_PORT_MAPPER)
free(ue);
for (i = 1; i < XHCI_MAX_ENDPOINTS; i++) {
vdep = &de->eps[i];
if (vdep->ep_xfer) {
pci_xhci_free_usb_xfer(vdep->ep_xfer);
pci_xhci_free_usb_xfer(de, vdep->ep_xfer);
vdep->ep_xfer = NULL;
}
}
if (ue->ue_devtype == USB_DEV_PORT_MAPPER)
free(ue);
free(de);
}
@ -1654,15 +1656,23 @@ fail:
}
static void
pci_xhci_free_usb_xfer(struct usb_xfer *xfer)
pci_xhci_free_usb_xfer(struct pci_xhci_dev_emu *dev, struct usb_xfer *xfer)
{
int i;
if (!xfer)
return;
for (i = 0; i < xfer->max_blk_cnt; i++)
free(xfer->data[i].hcb);
for (i = 0; i < xfer->max_blk_cnt; i++) {
if(xfer->reqs[i]) {
if (dev && dev->dev_ue->ue_free_req)
dev->dev_ue->ue_free_req(xfer->reqs[i]->trn);
free(xfer->reqs[i]->buffer);
free(xfer->reqs[i]);
}
if (xfer->data)
free(xfer->data[i].hcb);
}
free(xfer->data);
free(xfer->reqs);
@ -1748,7 +1758,7 @@ pci_xhci_init_ep(struct pci_xhci_dev_emu *dev, int epid, uint32_t slot)
return 0;
errout:
pci_xhci_free_usb_xfer(devep->ep_xfer);
pci_xhci_free_usb_xfer(dev, devep->ep_xfer);
devep->ep_xfer = NULL;
devep->timer_data.dev = NULL;
devep->timer_data.slot = 0;
@ -1777,7 +1787,7 @@ pci_xhci_disable_ep(struct pci_xhci_dev_emu *dev, int epid)
free(devep->ep_sctx_trbs);
if (devep->ep_xfer != NULL) {
pci_xhci_free_usb_xfer(devep->ep_xfer);
pci_xhci_free_usb_xfer(dev, devep->ep_xfer);
devep->ep_xfer = NULL;
}
@ -2380,7 +2390,8 @@ pci_xhci_cmd_reset_ep(struct pci_xhci_vdev *xdev,
r = xfer->reqs[i];
if (r && r->trn)
/* let usb_dev_comp_req to free the memory */
libusb_cancel_transfer(r->trn);
if (dev->dev_ue->ue_cancel_req != NULL)
dev->dev_ue->ue_cancel_req(r->trn);
}
xfer->ndata = 0;
@ -3021,7 +3032,7 @@ pci_xhci_try_usb_xfer(struct pci_xhci_vdev *xdev,
if (err == XHCI_TRB_ERROR_SUCCESS && do_intr)
pci_xhci_assert_interrupt(xdev);
pci_xhci_free_usb_xfer(devep->ep_xfer);
pci_xhci_free_usb_xfer(dev, devep->ep_xfer);
devep->ep_xfer = NULL;
}
}

View File

@ -1118,6 +1118,24 @@ errout:
return NULL;
}
void
usb_dev_free_request(void *pdata)
{
struct libusb_transfer *trn;
trn = pdata;
libusb_free_transfer(trn);
}
void
usb_dev_cancel_request(void *pdata)
{
struct libusb_transfer *trn;
trn = pdata;
libusb_cancel_transfer(trn);
}
void
usb_dev_deinit(void *pdata)
{

View File

@ -115,6 +115,8 @@ struct usb_devemu {
int (*ue_reset)(void *sc);
int (*ue_remove)(void *sc);
int (*ue_stop)(void *sc);
void (*ue_cancel_req)(void *pdata);
void (*ue_free_req)(void *pdata);
void (*ue_deinit)(void *pdata);
};
#define USB_EMUL_SET(x) DATA_SET(usb_emu_set, x)

View File

@ -129,4 +129,6 @@ int usb_dev_info(void *pdata, int type, void *value, int size);
int usb_dev_request(void *pdata, struct usb_xfer *xfer);
int usb_dev_reset(void *pdata);
int usb_dev_data(void *pdata, struct usb_xfer *xfer, int dir, int epctx);
void usb_dev_cancel_request(void *pdata);
void usb_dev_free_request(void *pdata);
#endif