mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-15 18:29:02 +00:00
DM USB: xHCI: support USB hot plug out.
Implements the disconnect callback of libusb which will be called once USB device plug out. Change-Id: Ic5f072f08a92270e6e5836b49e5066da783af243 Signed-off-by: Wu, Xiaoguang <xiaoguang.wu@intel.com> Reviewed-by: Shuo Liu <shuo.a.liu@intel.com> Reviewed-by: Yu Wang <yu1.wang@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
7687a3d0d7
commit
0181d19a61
@ -325,6 +325,7 @@ static void pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port,
|
|||||||
static int pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
|
static int pci_xhci_xfer_complete(struct pci_xhci_vdev *xdev,
|
||||||
struct usb_data_xfer *xfer, uint32_t slot, uint32_t epid,
|
struct usb_data_xfer *xfer, uint32_t slot, uint32_t epid,
|
||||||
int *do_intr);
|
int *do_intr);
|
||||||
|
static inline int pci_xhci_is_valid_portnum(int n);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
||||||
@ -417,6 +418,49 @@ errout:
|
|||||||
static int
|
static int
|
||||||
pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
|
pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
|
||||||
{
|
{
|
||||||
|
struct pci_xhci_vdev *xdev;
|
||||||
|
struct pci_xhci_dev_emu *edev;
|
||||||
|
struct usb_dev *udev;
|
||||||
|
uint8_t port, native_port;
|
||||||
|
|
||||||
|
assert(hci_data);
|
||||||
|
assert(dev_data);
|
||||||
|
|
||||||
|
xdev = hci_data;
|
||||||
|
assert(xdev->devices);
|
||||||
|
|
||||||
|
native_port = *((uint8_t *)dev_data);
|
||||||
|
if (!pci_xhci_is_valid_portnum(native_port)) {
|
||||||
|
UPRINTF(LFTL, "invalid physical port %d\r\n", native_port);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (port = 1; port < XHCI_MAX_DEVS; ++port) {
|
||||||
|
edev = xdev->devices[port];
|
||||||
|
if (!edev)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
udev = edev->dev_instance;
|
||||||
|
if (udev->port == native_port)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port == XHCI_MAX_DEVS) {
|
||||||
|
UPRINTF(LFTL, "fail to find physical port %d\r\n", native_port);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UPRINTF(LDBG, "report virtual port %d status\r\n", port);
|
||||||
|
if (pci_xhci_port_chg(xdev, port, 0)) {
|
||||||
|
UPRINTF(LFTL, "fail to report event\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, the resources allocated for virtual device
|
||||||
|
* should not be released, it should be released in the
|
||||||
|
* pci_xhci_cmd_disable_slot function.
|
||||||
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,6 +1154,7 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
|
|||||||
{
|
{
|
||||||
struct pci_xhci_dev_emu *dev;
|
struct pci_xhci_dev_emu *dev;
|
||||||
uint32_t cmderr;
|
uint32_t cmderr;
|
||||||
|
int i;
|
||||||
|
|
||||||
UPRINTF(LDBG, "pci_xhci disable slot %u\r\n", slot);
|
UPRINTF(LDBG, "pci_xhci disable slot %u\r\n", slot);
|
||||||
|
|
||||||
@ -1133,6 +1178,19 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < XHCI_MAX_DEVS; ++i)
|
||||||
|
if (dev == xdev->devices[i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i < XHCI_MAX_DEVS && XHCI_PORTREG_PTR(xdev, i)) {
|
||||||
|
XHCI_PORTREG_PTR(xdev, i)->portsc &= ~(XHCI_PS_CSC |
|
||||||
|
XHCI_PS_CCS | XHCI_PS_PED | XHCI_PS_PP);
|
||||||
|
xdev->devices[i] = NULL;
|
||||||
|
xdev->slots[slot] = NULL;
|
||||||
|
pci_xhci_dev_destroy(dev);
|
||||||
|
} else
|
||||||
|
UPRINTF(LWRN, "invalid slot %d\r\n", slot);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return cmderr;
|
return cmderr;
|
||||||
}
|
}
|
||||||
|
@ -864,6 +864,8 @@ static int
|
|||||||
usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
|
usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
|
||||||
*ldev, libusb_hotplug_event event, void *pdata)
|
*ldev, libusb_hotplug_event event, void *pdata)
|
||||||
{
|
{
|
||||||
|
uint8_t port;
|
||||||
|
|
||||||
UPRINTF(LDBG, "disconnect event\r\n");
|
UPRINTF(LDBG, "disconnect event\r\n");
|
||||||
|
|
||||||
if (!ctx || !ldev) {
|
if (!ctx || !ldev) {
|
||||||
@ -871,8 +873,9 @@ usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port = libusb_get_port_number(ldev);
|
||||||
if (g_ctx.disconn_cb)
|
if (g_ctx.disconn_cb)
|
||||||
g_ctx.disconn_cb(g_ctx.hci_data, NULL);
|
g_ctx.disconn_cb(g_ctx.hci_data, &port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user