Skip to content

Commit f533a07

Browse files
YangLiang3NanlinXie
authored andcommitted
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>
1 parent 6886d3c commit f533a07

File tree

5 files changed

+222
-22
lines changed

5 files changed

+222
-22
lines changed

devicemodel/hw/pci/xhci.c

Lines changed: 134 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,112 @@ pci_xhci_get_native_port_index_by_vport(struct pci_xhci_vdev *xdev,
571571
return -1;
572572
}
573573

574+
static void
575+
pci_xhci_clr_native_port_assigned(struct pci_xhci_vdev *xdev,
576+
struct usb_native_devinfo *info)
577+
{
578+
int i;
579+
580+
assert(xdev);
581+
assert(info);
582+
assert(xdev->native_ports);
583+
584+
i = pci_xhci_get_native_port_index_by_path(xdev, &info->path);
585+
if (i >= 0) {
586+
xdev->native_ports[i].state = VPORT_FREE;
587+
xdev->native_ports[i].vport = 0;
588+
}
589+
}
590+
591+
static int
592+
pci_xhci_assign_hub_ports(struct pci_xhci_vdev *xdev,
593+
struct usb_native_devinfo *info)
594+
{
595+
int index;
596+
uint8_t i;
597+
struct usb_native_devinfo di;
598+
struct usb_devpath *path;
599+
600+
if (!xdev || !info || info->type != USB_TYPE_EXTHUB)
601+
return -1;
602+
603+
index = pci_xhci_get_native_port_index_by_path(xdev, &info->path);
604+
if (index < 0) {
605+
UPRINTF(LDBG, "cannot find hub %d-%s\r\n", info->path.bus,
606+
usb_dev_path(&info->path));
607+
return -1;
608+
}
609+
610+
xdev->native_ports[index].info = *info;
611+
UPRINTF(LDBG, "Found an USB hub %d-%s with %d port(s).\r\n",
612+
info->path.bus, usb_dev_path(&info->path),
613+
info->maxchild);
614+
615+
path = &di.path;
616+
for (i = 1; i <= info->maxchild; i++) {
617+
618+
/* make a device path for hub ports */
619+
memcpy(path->path, info->path.path, info->path.depth);
620+
memcpy(path->path + info->path.depth, &i, sizeof(i));
621+
memset(path->path + info->path.depth + 1, 0,
622+
USB_MAX_TIERS - info->path.depth - 1);
623+
path->depth = info->path.depth + 1;
624+
path->bus = info->path.bus;
625+
626+
/* set the device path as assigned */
627+
index = pci_xhci_set_native_port_assigned(xdev, &di);
628+
if (index < 0) {
629+
UPRINTF(LFTL, "too many USB devices\r\n");
630+
return -1;
631+
}
632+
UPRINTF(LDBG, "Add %d-%s as assigned port\r\n",
633+
path->bus, usb_dev_path(path));
634+
}
635+
return 0;
636+
}
637+
638+
static int
639+
pci_xhci_unassign_hub_ports(struct pci_xhci_vdev *xdev,
640+
struct usb_native_devinfo *info)
641+
{
642+
uint8_t i, index;
643+
struct usb_native_devinfo di, *oldinfo;
644+
struct usb_devpath *path;
645+
646+
if (!xdev || !info || info->type != USB_TYPE_EXTHUB)
647+
return -1;
648+
649+
index = pci_xhci_get_native_port_index_by_path(xdev, &info->path);
650+
if (index < 0) {
651+
UPRINTF(LFTL, "cannot find USB hub %d-%s\r\n",
652+
info->path.bus, usb_dev_path(&info->path));
653+
return -1;
654+
}
655+
656+
oldinfo = &xdev->native_ports[index].info;
657+
UPRINTF(LDBG, "Disconnect an USB hub %d-%s with %d port(s)\r\n",
658+
oldinfo->path.bus, usb_dev_path(&oldinfo->path),
659+
oldinfo->maxchild);
660+
661+
path = &di.path;
662+
for (i = 1; i <= oldinfo->maxchild; i++) {
663+
664+
/* make a device path for hub ports */
665+
memcpy(path->path, oldinfo->path.path, oldinfo->path.depth);
666+
memcpy(path->path + oldinfo->path.depth, &i, sizeof(i));
667+
memset(path->path + oldinfo->path.depth + 1, 0,
668+
USB_MAX_TIERS - oldinfo->path.depth - 1);
669+
path->depth = oldinfo->path.depth + 1;
670+
path->bus = oldinfo->path.bus;
671+
672+
/* clear the device path as not assigned */
673+
pci_xhci_clr_native_port_assigned(xdev, &di);
674+
UPRINTF(LDBG, "Del %d-%s as assigned port\r\n",
675+
path->bus, usb_dev_path(path));
676+
}
677+
return 0;
678+
}
679+
574680
static int
575681
pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
576682
{
@@ -579,6 +685,7 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
579685
int vport;
580686
int need_intr = 1;
581687
int index;
688+
int rc;
582689

583690
xdev = hci_data;
584691

@@ -600,6 +707,15 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
600707
di->path.bus, usb_dev_path(&di->path));
601708
return 0;
602709
}
710+
711+
if (di->type == USB_TYPE_EXTHUB) {
712+
rc = pci_xhci_assign_hub_ports(xdev, di);
713+
if (rc < 0)
714+
UPRINTF(LFTL, "fail to assign ports of hub %d-%s\r\n",
715+
di->path.bus, usb_dev_path(&di->path));
716+
return 0;
717+
}
718+
603719
UPRINTF(LDBG, "%04x:%04x %d-%s belong to this vm.\r\n", di->vid,
604720
di->pid, di->path.bus, usb_dev_path(&di->path));
605721

@@ -637,32 +753,42 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
637753
{
638754
struct pci_xhci_vdev *xdev;
639755
struct pci_xhci_dev_emu *edev;
640-
struct usb_native_devinfo di;
756+
struct usb_native_devinfo *di;
641757
uint8_t vport, slot;
642758
uint16_t state;
643759
int need_intr = 1;
644760
int index;
761+
int rc;
645762

646763
assert(hci_data);
647764
assert(dev_data);
648765

649766
xdev = hci_data;
650767
assert(xdev->devices);
651768

652-
di = *((struct usb_native_devinfo *)dev_data);
653-
if (!pci_xhci_is_valid_portnum(ROOTHUB_PORT(di.path))) {
769+
di = dev_data;
770+
if (!pci_xhci_is_valid_portnum(ROOTHUB_PORT(di->path))) {
654771
UPRINTF(LFTL, "invalid physical port %d\r\n",
655-
ROOTHUB_PORT(di.path));
772+
ROOTHUB_PORT(di->path));
656773
return -1;
657774
}
658775

659-
index = pci_xhci_get_native_port_index_by_path(xdev, &di.path);
776+
index = pci_xhci_get_native_port_index_by_path(xdev, &di->path);
660777
if (index < 0) {
661778
UPRINTF(LFTL, "fail to find physical port %d\r\n",
662-
ROOTHUB_PORT(di.path));
779+
ROOTHUB_PORT(di->path));
663780
return -1;
664781
}
665782

783+
if (di->type == USB_TYPE_EXTHUB) {
784+
rc = pci_xhci_unassign_hub_ports(xdev, di);
785+
if (rc < 0)
786+
UPRINTF(LFTL, "fail to unassign the ports of hub"
787+
" %d-%s\r\n", di->path.bus,
788+
usb_dev_path(&di->path));
789+
return 0;
790+
}
791+
666792
state = xdev->native_ports[index].state;
667793
vport = xdev->native_ports[index].vport;
668794

@@ -674,8 +800,8 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
674800
* cleared for future connecting.
675801
*/
676802
UPRINTF(LFTL, "disconnect VPORT_CONNECTED device: "
677-
"%d-%s vport %d\r\n", di.path.bus,
678-
usb_dev_path(&di.path), vport);
803+
"%d-%s vport %d\r\n", di->path.bus,
804+
usb_dev_path(&di->path), vport);
679805
pci_xhci_disconnect_port(xdev, vport, 0);
680806
xdev->native_ports[index].state = VPORT_ASSIGNED;
681807
return 0;

devicemodel/hw/platform/usb_pmapper.c

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ usb_get_native_devinfo(struct libusb_device *ldev,
4646
return false;
4747
}
4848

49+
/* set device type */
50+
if (ROOTHUB_PORT(info->path) == 0)
51+
info->type = USB_TYPE_ROOTHUB;
52+
else if (d.bDeviceClass == LIBUSB_CLASS_HUB)
53+
info->type = USB_TYPE_EXTHUB;
54+
else if (info->path.path[1] == 0)
55+
info->type = USB_TYPE_ROOTHUB_SUBDEV;
56+
else
57+
info->type = USB_TYPE_EXTHUB_SUBDEV;
58+
59+
if (info->type == USB_TYPE_EXTHUB) {
60+
info->maxchild = usb_get_hub_port_num(&info->path);
61+
if (info->maxchild < 0)
62+
UPRINTF(LFTL, "fail to get count of numbers of hub"
63+
" %d-%s\r\n", info->path.bus,
64+
usb_dev_path(&info->path));
65+
}
66+
4967
info->pid = d.idProduct;
5068
info->vid = d.idVendor;
5169
info->bcd = d.bcdUSB;
@@ -73,15 +91,36 @@ usb_dev_scan_dev()
7391
if (num_devs < 0)
7492
return -1;
7593

94+
/* first pass, process external hubs */
7695
for (i = 0; i < num_devs; ++i) {
7796
ldev = devlist[i];
7897

7998
ret = usb_get_native_devinfo(ldev, &di, &d);
8099
if (ret == false)
81100
continue;
101+
82102
if (ROOTHUB_PORT(di.path) == 0)
83103
continue;
84-
if (d.bDeviceClass == LIBUSB_CLASS_HUB)
104+
105+
if (di.type != USB_TYPE_EXTHUB)
106+
continue;
107+
108+
if (g_ctx.conn_cb)
109+
g_ctx.conn_cb(g_ctx.hci_data, &di);
110+
}
111+
112+
/* second pass, process devices */
113+
for (i = 0; i < num_devs; ++i) {
114+
ldev = devlist[i];
115+
116+
ret = usb_get_native_devinfo(ldev, &di, &d);
117+
if (ret == false)
118+
continue;
119+
120+
if (ROOTHUB_PORT(di.path) == 0)
121+
continue;
122+
123+
if (di.type == USB_TYPE_EXTHUB)
85124
continue;
86125

87126
if (g_ctx.conn_cb)
@@ -941,8 +980,8 @@ usb_dev_init(void *pdata, char *opt)
941980
int ver;
942981

943982
assert(pdata);
944-
945983
di = pdata;
984+
946985
libusb_get_device_descriptor(di->priv_data, &desc);
947986
UPRINTF(LINF, "Found USB device: %d-%s\r\nPID(0x%X), VID(0x%X) CLASS"
948987
"(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
10881127
*ldev, libusb_hotplug_event event, void *pdata)
10891128
{
10901129
struct usb_native_devinfo di;
1091-
struct libusb_device_descriptor d;
10921130
bool ret;
10931131

10941132
UPRINTF(LDBG, "connect event\r\n");
@@ -1098,13 +1136,10 @@ usb_dev_native_sys_conn_cb(struct libusb_context *ctx, struct libusb_device
10981136
return -1;
10991137
}
11001138

1101-
ret = usb_get_native_devinfo(ldev, &di, &d);
1139+
ret = usb_get_native_devinfo(ldev, &di, NULL);
11021140
if (ret == false)
11031141
return 0;
11041142

1105-
if (d.bDeviceClass == LIBUSB_CLASS_HUB)
1106-
return 0;
1107-
11081143
if (g_ctx.conn_cb)
11091144
g_ctx.conn_cb(g_ctx.hci_data, &di);
11101145

@@ -1116,7 +1151,6 @@ usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
11161151
*ldev, libusb_hotplug_event event, void *pdata)
11171152
{
11181153
struct usb_native_devinfo di;
1119-
struct libusb_device_descriptor d;
11201154
bool ret;
11211155

11221156
UPRINTF(LDBG, "disconnect event\r\n");
@@ -1126,13 +1160,10 @@ usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
11261160
return -1;
11271161
}
11281162

1129-
ret = usb_get_native_devinfo(ldev, &di, &d);
1163+
ret = usb_get_native_devinfo(ldev, &di, NULL);
11301164
if (ret == false)
11311165
return 0;
11321166

1133-
if (d.bDeviceClass == LIBUSB_CLASS_HUB)
1134-
return 0;
1135-
11361167
if (g_ctx.disconn_cb)
11371168
g_ctx.disconn_cb(g_ctx.hci_data, &di);
11381169

devicemodel/hw/usb_core.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,37 @@ usb_dev_path(struct usb_devpath *path)
264264

265265
return output;
266266
}
267+
268+
int
269+
usb_get_hub_port_num(struct usb_devpath *path)
270+
{
271+
int rc, fd;
272+
char buf[128];
273+
char cnt[8];
274+
275+
if (!usb_native_is_bus_existed(path->bus))
276+
return -1;
277+
278+
snprintf(buf, sizeof(buf), "%s/%d-%s/maxchild", NATIVE_USBSYS_DEVDIR,
279+
path->bus, usb_dev_path(path));
280+
if (access(buf, R_OK)) {
281+
UPRINTF(LWRN, "can't find maxchild file\r\n");
282+
return -1;
283+
}
284+
285+
fd = open(buf, O_RDONLY);
286+
if (fd < 0) {
287+
UPRINTF(LWRN, "fail to open maxchild file\r\n");
288+
return -1;
289+
}
290+
291+
rc = read(fd, &cnt, sizeof(cnt));
292+
if (rc < 0) {
293+
UPRINTF(LWRN, "fail to read maxchild file\r\n");
294+
close(fd);
295+
return -1;
296+
}
297+
298+
close(fd);
299+
return atoi(cnt);
300+
}

devicemodel/include/usb_core.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ enum usb_xfer_blk_stat {
8484
USB_XFER_BLK_HANDLED
8585
};
8686

87+
enum usb_native_devtype {
88+
USB_TYPE_ROOTHUB,
89+
USB_TYPE_EXTHUB,
90+
USB_TYPE_ROOTHUB_SUBDEV,
91+
USB_TYPE_EXTHUB_SUBDEV,
92+
USB_TYPE_NONE
93+
};
94+
8795
#define USB_MAX_TIERS 7
8896

8997
struct usb_hci;
@@ -174,9 +182,11 @@ struct usb_devpath {
174182

175183
struct usb_native_devinfo {
176184
int speed;
185+
int maxchild;
177186
uint16_t bcd;
178187
uint16_t pid;
179188
uint16_t vid;
189+
enum usb_native_devtype type;
180190
struct usb_devpath path;
181191
void *priv_data;
182192
};
@@ -247,5 +257,6 @@ struct usb_data_xfer_block *usb_data_xfer_append(struct usb_data_xfer *xfer,
247257
int blen,
248258
void *hci_data,
249259
int ccs);
260+
int usb_get_hub_port_num(struct usb_devpath *path);
250261
char *usb_dev_path(struct usb_devpath *path);
251262
#endif /* _USB_CORE_H_ */

devicemodel/include/usb_pmapper.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,4 @@ int usb_dev_info(void *pdata, int type, void *value, int size);
119119
int usb_dev_request(void *pdata, struct usb_data_xfer *xfer);
120120
int usb_dev_reset(void *pdata);
121121
int usb_dev_data(void *pdata, struct usb_data_xfer *xfer, int dir, int epctx);
122-
enum usb_native_dev_type usb_get_parent_dev_type(void *pdata, uint16_t *bus,
123-
uint16_t *port);
124122
#endif

0 commit comments

Comments
 (0)