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); int need_intr);
static struct pci_xhci_dev_emu *pci_xhci_dev_create(struct pci_xhci_vdev * static struct pci_xhci_dev_emu *pci_xhci_dev_create(struct pci_xhci_vdev *
xdev, void *dev_data); 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, static void pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port,
uint32_t errcode, uint32_t evtype); uint32_t errcode, uint32_t evtype);
static int pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev, 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: errout:
if (ud) if (ud)
ue->ue_deinit(ud); ue->ue_deinit(ud, true);
free(ue); free(ue);
free(de); free(de);
@ -1080,28 +1080,42 @@ errout:
} }
static void 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_devemu *ue;
struct usb_dev *ud; struct usb_dev *ud;
if (de) { if (!de)
ue = de->dev_ue; return;
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;
if (ue->ue_devtype == USB_DEV_PORT_MAPPER) /* FIXME: will merge usb_dev and usb_devemu into one data structure */
free(ue); ue = de->dev_ue;
ud = de->dev_instance;
if (ue) {
if (ue->ue_devtype == USB_DEV_PORT_MAPPER) {
free(de); assert(ue->ue_deinit);
ue->ue_deinit(ud, full);
if (full)
de->dev_instance = NULL;
}
} }
if (ue && ue->ue_devtype == USB_DEV_PORT_MAPPER && full) {
free(ue);
de->dev_ue = NULL;
}
if (full)
free(de);
} }
static inline int 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)); slot, di->path.bus, usb_dev_path(&di->path));
/* release all the resource allocated for virtual device */ /* release all the resource allocated for virtual device */
pci_xhci_dev_destroy(dev); pci_xhci_dev_destroy(dev, true);
} else } else
UPRINTF(LWRN, "invalid slot %d\r\n", slot); 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]; de = xdev->devices[i];
if (de) { if (de) {
xdev->devices[i] = NULL; xdev->devices[i] = NULL;
pci_xhci_dev_destroy(de); pci_xhci_dev_destroy(de, true);
xdev->ndevices--; xdev->ndevices--;
} }
} }

View File

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

View File

@ -116,7 +116,7 @@ struct usb_devemu {
int (*ue_reset)(void *sc); int (*ue_reset)(void *sc);
int (*ue_remove)(void *sc); int (*ue_remove)(void *sc);
int (*ue_stop)(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) #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 *hci_data, int log_level);
void usb_dev_sys_deinit(void); void usb_dev_sys_deinit(void);
void *usb_dev_init(void *pdata, char *opt); 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_info(void *pdata, int type, void *value, int size);
int usb_dev_request(void *pdata, struct usb_data_xfer *xfer); int usb_dev_request(void *pdata, struct usb_data_xfer *xfer);
int usb_dev_reset(void *pdata); int usb_dev_reset(void *pdata);