DM USB: xHCI: refine the de-init logic of xHCI vdevice

Add 'full' and 'non-full' de-initialize support for xHCI virtual
device. The non-full de-initialization mainly release usb_dev
structure and unbind the usbfs with native device. And the full
de-initialize will release all the resources allocated for xHCI
virtual device including the unbinding operation mentioned above

Tracked-On: #2576
Signed-off-by: Conghui Chen <conghui.chen@intel.com>
Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Xiaoguang Wu 2019-02-18 13:30:53 +08:00 committed by wenlingz
parent 76a5131b37
commit b77755cd58
4 changed files with 50 additions and 31 deletions

View File

@ -489,7 +489,7 @@ static int pci_xhci_disconnect_port(struct pci_xhci_vdev *xdev, int port,
int need_intr);
static struct pci_xhci_dev_emu *pci_xhci_dev_create(struct pci_xhci_vdev *
xdev, void *dev_data);
static void pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de);
static void pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de, bool full);
static void pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port,
uint32_t errcode, uint32_t evtype);
static int pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
@ -1072,7 +1072,7 @@ pci_xhci_dev_create(struct pci_xhci_vdev *xdev, void *dev_data)
errout:
if (ud)
ue->ue_deinit(ud);
ue->ue_deinit(ud, true);
free(ue);
free(de);
@ -1080,28 +1080,42 @@ errout:
}
static void
pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de)
pci_xhci_dev_destroy(struct pci_xhci_dev_emu *de, bool full)
{
/*
* When full == false, it means the destroy operation is partial and
* the pci_xhci_dev_emu is not released. Except that, the partial
* destroy also unbind the usbfs with the native USB device.
* When full == true, this function will release all the resources
* and do the unbind operation mentioned above.
*/
struct usb_devemu *ue;
struct usb_dev *ud;
if (de) {
if (!de)
return;
/* FIXME: will merge usb_dev and usb_devemu into one data structure */
ue = de->dev_ue;
ud = de->dev_instance;
if (ue) {
if (ue->ue_devtype == USB_DEV_PORT_MAPPER) {
assert(ue->ue_deinit);
if (ue->ue_deinit)
ue->ue_deinit(ud);
}
} else
return;
ue->ue_deinit(ud, full);
if (ue->ue_devtype == USB_DEV_PORT_MAPPER)
if (full)
de->dev_instance = NULL;
}
}
if (ue && ue->ue_devtype == USB_DEV_PORT_MAPPER && full) {
free(ue);
free(de);
de->dev_ue = NULL;
}
if (full)
free(de);
}
static inline int
@ -1857,7 +1871,7 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
slot, di->path.bus, usb_dev_path(&di->path));
/* release all the resource allocated for virtual device */
pci_xhci_dev_destroy(dev);
pci_xhci_dev_destroy(dev, true);
} else
UPRINTF(LWRN, "invalid slot %d\r\n", slot);
@ -4233,7 +4247,7 @@ pci_xhci_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
de = xdev->devices[i];
if (de) {
xdev->devices[i] = NULL;
pci_xhci_dev_destroy(de);
pci_xhci_dev_destroy(de, true);
xdev->ndevices--;
}
}

View File

@ -1054,22 +1054,27 @@ errout:
}
void
usb_dev_deinit(void *pdata)
usb_dev_deinit(void *pdata, bool full)
{
int rc = 0;
struct usb_dev *udev;
udev = pdata;
if (udev) {
if (udev->handle) {
if (!udev)
return;
if (!udev->handle)
goto out;
rc = usb_dev_native_toggle_if_drivers(udev, 1);
if (rc)
UPRINTF(LWRN, "fail to attach if drv rc:%d\r\n",
rc);
UPRINTF(LWRN, "fail to attach if drv rc:%d\r\n", rc);
libusb_close(udev->handle);
}
udev->handle = NULL;
out:
if (full)
free(udev);
}
}
int

View File

@ -116,7 +116,7 @@ struct usb_devemu {
int (*ue_reset)(void *sc);
int (*ue_remove)(void *sc);
int (*ue_stop)(void *sc);
void (*ue_deinit)(void *pdata);
void (*ue_deinit)(void *pdata, bool full);
};
#define USB_EMUL_SET(x) DATA_SET(usb_emu_set, x)

View File

@ -114,7 +114,7 @@ int usb_dev_sys_init(usb_dev_sys_cb conn_cb, usb_dev_sys_cb disconn_cb,
void *hci_data, int log_level);
void usb_dev_sys_deinit(void);
void *usb_dev_init(void *pdata, char *opt);
void usb_dev_deinit(void *pdata);
void usb_dev_deinit(void *pdata, bool full);
int usb_dev_info(void *pdata, int type, void *value, int size);
int usb_dev_request(void *pdata, struct usb_data_xfer *xfer);
int usb_dev_reset(void *pdata);