DM USB: xHCI: support multiple hubs in single layer
This patch is used to enable multiple hubs in single layer under Flat Mode. Tracked-On: #1434 Signed-off-by: Liang Yang <liang3.yang@intel.com> Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
6886d3cdf8
commit
f533a07af1
|
@ -571,6 +571,112 @@ pci_xhci_get_native_port_index_by_vport(struct pci_xhci_vdev *xdev,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_xhci_clr_native_port_assigned(struct pci_xhci_vdev *xdev,
|
||||
struct usb_native_devinfo *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(xdev);
|
||||
assert(info);
|
||||
assert(xdev->native_ports);
|
||||
|
||||
i = pci_xhci_get_native_port_index_by_path(xdev, &info->path);
|
||||
if (i >= 0) {
|
||||
xdev->native_ports[i].state = VPORT_FREE;
|
||||
xdev->native_ports[i].vport = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_assign_hub_ports(struct pci_xhci_vdev *xdev,
|
||||
struct usb_native_devinfo *info)
|
||||
{
|
||||
int index;
|
||||
uint8_t i;
|
||||
struct usb_native_devinfo di;
|
||||
struct usb_devpath *path;
|
||||
|
||||
if (!xdev || !info || info->type != USB_TYPE_EXTHUB)
|
||||
return -1;
|
||||
|
||||
index = pci_xhci_get_native_port_index_by_path(xdev, &info->path);
|
||||
if (index < 0) {
|
||||
UPRINTF(LDBG, "cannot find hub %d-%s\r\n", info->path.bus,
|
||||
usb_dev_path(&info->path));
|
||||
return -1;
|
||||
}
|
||||
|
||||
xdev->native_ports[index].info = *info;
|
||||
UPRINTF(LDBG, "Found an USB hub %d-%s with %d port(s).\r\n",
|
||||
info->path.bus, usb_dev_path(&info->path),
|
||||
info->maxchild);
|
||||
|
||||
path = &di.path;
|
||||
for (i = 1; i <= info->maxchild; i++) {
|
||||
|
||||
/* make a device path for hub ports */
|
||||
memcpy(path->path, info->path.path, info->path.depth);
|
||||
memcpy(path->path + info->path.depth, &i, sizeof(i));
|
||||
memset(path->path + info->path.depth + 1, 0,
|
||||
USB_MAX_TIERS - info->path.depth - 1);
|
||||
path->depth = info->path.depth + 1;
|
||||
path->bus = info->path.bus;
|
||||
|
||||
/* set the device path as assigned */
|
||||
index = pci_xhci_set_native_port_assigned(xdev, &di);
|
||||
if (index < 0) {
|
||||
UPRINTF(LFTL, "too many USB devices\r\n");
|
||||
return -1;
|
||||
}
|
||||
UPRINTF(LDBG, "Add %d-%s as assigned port\r\n",
|
||||
path->bus, usb_dev_path(path));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_unassign_hub_ports(struct pci_xhci_vdev *xdev,
|
||||
struct usb_native_devinfo *info)
|
||||
{
|
||||
uint8_t i, index;
|
||||
struct usb_native_devinfo di, *oldinfo;
|
||||
struct usb_devpath *path;
|
||||
|
||||
if (!xdev || !info || info->type != USB_TYPE_EXTHUB)
|
||||
return -1;
|
||||
|
||||
index = pci_xhci_get_native_port_index_by_path(xdev, &info->path);
|
||||
if (index < 0) {
|
||||
UPRINTF(LFTL, "cannot find USB hub %d-%s\r\n",
|
||||
info->path.bus, usb_dev_path(&info->path));
|
||||
return -1;
|
||||
}
|
||||
|
||||
oldinfo = &xdev->native_ports[index].info;
|
||||
UPRINTF(LDBG, "Disconnect an USB hub %d-%s with %d port(s)\r\n",
|
||||
oldinfo->path.bus, usb_dev_path(&oldinfo->path),
|
||||
oldinfo->maxchild);
|
||||
|
||||
path = &di.path;
|
||||
for (i = 1; i <= oldinfo->maxchild; i++) {
|
||||
|
||||
/* make a device path for hub ports */
|
||||
memcpy(path->path, oldinfo->path.path, oldinfo->path.depth);
|
||||
memcpy(path->path + oldinfo->path.depth, &i, sizeof(i));
|
||||
memset(path->path + oldinfo->path.depth + 1, 0,
|
||||
USB_MAX_TIERS - oldinfo->path.depth - 1);
|
||||
path->depth = oldinfo->path.depth + 1;
|
||||
path->bus = oldinfo->path.bus;
|
||||
|
||||
/* clear the device path as not assigned */
|
||||
pci_xhci_clr_native_port_assigned(xdev, &di);
|
||||
UPRINTF(LDBG, "Del %d-%s as assigned port\r\n",
|
||||
path->bus, usb_dev_path(path));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
||||
{
|
||||
|
@ -579,6 +685,7 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
|||
int vport;
|
||||
int need_intr = 1;
|
||||
int index;
|
||||
int rc;
|
||||
|
||||
xdev = hci_data;
|
||||
|
||||
|
@ -600,6 +707,15 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
|
|||
di->path.bus, usb_dev_path(&di->path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (di->type == USB_TYPE_EXTHUB) {
|
||||
rc = pci_xhci_assign_hub_ports(xdev, di);
|
||||
if (rc < 0)
|
||||
UPRINTF(LFTL, "fail to assign ports of hub %d-%s\r\n",
|
||||
di->path.bus, usb_dev_path(&di->path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
UPRINTF(LDBG, "%04x:%04x %d-%s belong to this vm.\r\n", di->vid,
|
||||
di->pid, di->path.bus, usb_dev_path(&di->path));
|
||||
|
||||
|
@ -637,11 +753,12 @@ 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_native_devinfo di;
|
||||
struct usb_native_devinfo *di;
|
||||
uint8_t vport, slot;
|
||||
uint16_t state;
|
||||
int need_intr = 1;
|
||||
int index;
|
||||
int rc;
|
||||
|
||||
assert(hci_data);
|
||||
assert(dev_data);
|
||||
|
@ -649,20 +766,29 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
|
|||
xdev = hci_data;
|
||||
assert(xdev->devices);
|
||||
|
||||
di = *((struct usb_native_devinfo *)dev_data);
|
||||
if (!pci_xhci_is_valid_portnum(ROOTHUB_PORT(di.path))) {
|
||||
di = dev_data;
|
||||
if (!pci_xhci_is_valid_portnum(ROOTHUB_PORT(di->path))) {
|
||||
UPRINTF(LFTL, "invalid physical port %d\r\n",
|
||||
ROOTHUB_PORT(di.path));
|
||||
ROOTHUB_PORT(di->path));
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = pci_xhci_get_native_port_index_by_path(xdev, &di.path);
|
||||
index = pci_xhci_get_native_port_index_by_path(xdev, &di->path);
|
||||
if (index < 0) {
|
||||
UPRINTF(LFTL, "fail to find physical port %d\r\n",
|
||||
ROOTHUB_PORT(di.path));
|
||||
ROOTHUB_PORT(di->path));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (di->type == USB_TYPE_EXTHUB) {
|
||||
rc = pci_xhci_unassign_hub_ports(xdev, di);
|
||||
if (rc < 0)
|
||||
UPRINTF(LFTL, "fail to unassign the ports of hub"
|
||||
" %d-%s\r\n", di->path.bus,
|
||||
usb_dev_path(&di->path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
state = xdev->native_ports[index].state;
|
||||
vport = xdev->native_ports[index].vport;
|
||||
|
||||
|
@ -674,8 +800,8 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
|
|||
* cleared for future connecting.
|
||||
*/
|
||||
UPRINTF(LFTL, "disconnect VPORT_CONNECTED device: "
|
||||
"%d-%s vport %d\r\n", di.path.bus,
|
||||
usb_dev_path(&di.path), vport);
|
||||
"%d-%s vport %d\r\n", di->path.bus,
|
||||
usb_dev_path(&di->path), vport);
|
||||
pci_xhci_disconnect_port(xdev, vport, 0);
|
||||
xdev->native_ports[index].state = VPORT_ASSIGNED;
|
||||
return 0;
|
||||
|
|
|
@ -46,6 +46,24 @@ usb_get_native_devinfo(struct libusb_device *ldev,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* set device type */
|
||||
if (ROOTHUB_PORT(info->path) == 0)
|
||||
info->type = USB_TYPE_ROOTHUB;
|
||||
else if (d.bDeviceClass == LIBUSB_CLASS_HUB)
|
||||
info->type = USB_TYPE_EXTHUB;
|
||||
else if (info->path.path[1] == 0)
|
||||
info->type = USB_TYPE_ROOTHUB_SUBDEV;
|
||||
else
|
||||
info->type = USB_TYPE_EXTHUB_SUBDEV;
|
||||
|
||||
if (info->type == USB_TYPE_EXTHUB) {
|
||||
info->maxchild = usb_get_hub_port_num(&info->path);
|
||||
if (info->maxchild < 0)
|
||||
UPRINTF(LFTL, "fail to get count of numbers of hub"
|
||||
" %d-%s\r\n", info->path.bus,
|
||||
usb_dev_path(&info->path));
|
||||
}
|
||||
|
||||
info->pid = d.idProduct;
|
||||
info->vid = d.idVendor;
|
||||
info->bcd = d.bcdUSB;
|
||||
|
@ -73,15 +91,36 @@ usb_dev_scan_dev()
|
|||
if (num_devs < 0)
|
||||
return -1;
|
||||
|
||||
/* first pass, process external hubs */
|
||||
for (i = 0; i < num_devs; ++i) {
|
||||
ldev = devlist[i];
|
||||
|
||||
ret = usb_get_native_devinfo(ldev, &di, &d);
|
||||
if (ret == false)
|
||||
continue;
|
||||
|
||||
if (ROOTHUB_PORT(di.path) == 0)
|
||||
continue;
|
||||
if (d.bDeviceClass == LIBUSB_CLASS_HUB)
|
||||
|
||||
if (di.type != USB_TYPE_EXTHUB)
|
||||
continue;
|
||||
|
||||
if (g_ctx.conn_cb)
|
||||
g_ctx.conn_cb(g_ctx.hci_data, &di);
|
||||
}
|
||||
|
||||
/* second pass, process devices */
|
||||
for (i = 0; i < num_devs; ++i) {
|
||||
ldev = devlist[i];
|
||||
|
||||
ret = usb_get_native_devinfo(ldev, &di, &d);
|
||||
if (ret == false)
|
||||
continue;
|
||||
|
||||
if (ROOTHUB_PORT(di.path) == 0)
|
||||
continue;
|
||||
|
||||
if (di.type == USB_TYPE_EXTHUB)
|
||||
continue;
|
||||
|
||||
if (g_ctx.conn_cb)
|
||||
|
@ -941,8 +980,8 @@ usb_dev_init(void *pdata, char *opt)
|
|||
int ver;
|
||||
|
||||
assert(pdata);
|
||||
|
||||
di = pdata;
|
||||
|
||||
libusb_get_device_descriptor(di->priv_data, &desc);
|
||||
UPRINTF(LINF, "Found USB device: %d-%s\r\nPID(0x%X), VID(0x%X) CLASS"
|
||||
"(0x%X) SUBCLASS(0x%X) BCD(0x%X) SPEED(%d)\r\n",
|
||||
|
@ -1088,7 +1127,6 @@ usb_dev_native_sys_conn_cb(struct libusb_context *ctx, struct libusb_device
|
|||
*ldev, libusb_hotplug_event event, void *pdata)
|
||||
{
|
||||
struct usb_native_devinfo di;
|
||||
struct libusb_device_descriptor d;
|
||||
bool ret;
|
||||
|
||||
UPRINTF(LDBG, "connect event\r\n");
|
||||
|
@ -1098,13 +1136,10 @@ usb_dev_native_sys_conn_cb(struct libusb_context *ctx, struct libusb_device
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = usb_get_native_devinfo(ldev, &di, &d);
|
||||
ret = usb_get_native_devinfo(ldev, &di, NULL);
|
||||
if (ret == false)
|
||||
return 0;
|
||||
|
||||
if (d.bDeviceClass == LIBUSB_CLASS_HUB)
|
||||
return 0;
|
||||
|
||||
if (g_ctx.conn_cb)
|
||||
g_ctx.conn_cb(g_ctx.hci_data, &di);
|
||||
|
||||
|
@ -1116,7 +1151,6 @@ usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
|
|||
*ldev, libusb_hotplug_event event, void *pdata)
|
||||
{
|
||||
struct usb_native_devinfo di;
|
||||
struct libusb_device_descriptor d;
|
||||
bool ret;
|
||||
|
||||
UPRINTF(LDBG, "disconnect event\r\n");
|
||||
|
@ -1126,13 +1160,10 @@ usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = usb_get_native_devinfo(ldev, &di, &d);
|
||||
ret = usb_get_native_devinfo(ldev, &di, NULL);
|
||||
if (ret == false)
|
||||
return 0;
|
||||
|
||||
if (d.bDeviceClass == LIBUSB_CLASS_HUB)
|
||||
return 0;
|
||||
|
||||
if (g_ctx.disconn_cb)
|
||||
g_ctx.disconn_cb(g_ctx.hci_data, &di);
|
||||
|
||||
|
|
|
@ -264,3 +264,37 @@ usb_dev_path(struct usb_devpath *path)
|
|||
|
||||
return output;
|
||||
}
|
||||
|
||||
int
|
||||
usb_get_hub_port_num(struct usb_devpath *path)
|
||||
{
|
||||
int rc, fd;
|
||||
char buf[128];
|
||||
char cnt[8];
|
||||
|
||||
if (!usb_native_is_bus_existed(path->bus))
|
||||
return -1;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s/%d-%s/maxchild", NATIVE_USBSYS_DEVDIR,
|
||||
path->bus, usb_dev_path(path));
|
||||
if (access(buf, R_OK)) {
|
||||
UPRINTF(LWRN, "can't find maxchild file\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(buf, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
UPRINTF(LWRN, "fail to open maxchild file\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = read(fd, &cnt, sizeof(cnt));
|
||||
if (rc < 0) {
|
||||
UPRINTF(LWRN, "fail to read maxchild file\r\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return atoi(cnt);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,14 @@ enum usb_xfer_blk_stat {
|
|||
USB_XFER_BLK_HANDLED
|
||||
};
|
||||
|
||||
enum usb_native_devtype {
|
||||
USB_TYPE_ROOTHUB,
|
||||
USB_TYPE_EXTHUB,
|
||||
USB_TYPE_ROOTHUB_SUBDEV,
|
||||
USB_TYPE_EXTHUB_SUBDEV,
|
||||
USB_TYPE_NONE
|
||||
};
|
||||
|
||||
#define USB_MAX_TIERS 7
|
||||
|
||||
struct usb_hci;
|
||||
|
@ -174,9 +182,11 @@ struct usb_devpath {
|
|||
|
||||
struct usb_native_devinfo {
|
||||
int speed;
|
||||
int maxchild;
|
||||
uint16_t bcd;
|
||||
uint16_t pid;
|
||||
uint16_t vid;
|
||||
enum usb_native_devtype type;
|
||||
struct usb_devpath path;
|
||||
void *priv_data;
|
||||
};
|
||||
|
@ -247,5 +257,6 @@ struct usb_data_xfer_block *usb_data_xfer_append(struct usb_data_xfer *xfer,
|
|||
int blen,
|
||||
void *hci_data,
|
||||
int ccs);
|
||||
int usb_get_hub_port_num(struct usb_devpath *path);
|
||||
char *usb_dev_path(struct usb_devpath *path);
|
||||
#endif /* _USB_CORE_H_ */
|
||||
|
|
|
@ -119,6 +119,4 @@ 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);
|
||||
int usb_dev_data(void *pdata, struct usb_data_xfer *xfer, int dir, int epctx);
|
||||
enum usb_native_dev_type usb_get_parent_dev_type(void *pdata, uint16_t *bus,
|
||||
uint16_t *port);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue