Skip to content

Commit d24213d

Browse files
xiaoguangwulijinxia
authored andcommitted
DM USB: xHCI: fix xhci speed emulation logic
The xHCI speed emulation is not right, which will cause failure during enumeration of certain USB device. This patch is used to fix it. Change-Id: I2d996298983882ed6921a75a10dec9e8684a393e Tracked-On: Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Reviewed-by: Liang Yang <liang3.yang@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent d6cc701 commit d24213d

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

devicemodel/hw/pci/xhci.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,31 @@ pci_xhci_is_valid_portnum(int n)
757757
return n > 0 && n <= XHCI_MAX_DEVS;
758758
}
759759

760+
static int
761+
pci_xhci_convert_speed(int lspeed)
762+
{
763+
/* according to xhci spec, zero means undefined speed */
764+
int speed = 0;
765+
766+
switch (lspeed) {
767+
case USB_SPEED_LOW:
768+
speed = 0x2;
769+
break;
770+
case USB_SPEED_FULL:
771+
speed = 0x1;
772+
break;
773+
case USB_SPEED_HIGH:
774+
speed = 0x3;
775+
break;
776+
case USB_SPEED_SUPER:
777+
speed = 0x4;
778+
break;
779+
default:
780+
UPRINTF(LFTL, "unkown speed %08x\r\n", lspeed);
781+
}
782+
return speed;
783+
}
784+
760785
static int
761786
pci_xhci_port_chg(struct pci_xhci_vdev *xdev, int port, int conn)
762787
{
@@ -779,12 +804,11 @@ pci_xhci_port_chg(struct pci_xhci_vdev *xdev, int port, int conn)
779804
reg->portsc |= (XHCI_PS_CSC |
780805
XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET));
781806
} else {
782-
speed = dev->dev_ue->ue_usbspeed;
807+
speed = pci_xhci_convert_speed(dev->dev_ue->ue_usbspeed);
783808
reg->portsc = XHCI_PS_CCS | XHCI_PS_PP | XHCI_PS_CSC;
784809
reg->portsc |= XHCI_PS_SPEED_SET(speed);
785810
}
786811

787-
788812
/* make an event for the guest OS */
789813
pci_xhci_set_evtrb(&evtrb,
790814
port,
@@ -3150,7 +3174,7 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
31503174
struct pci_xhci_portregs *port;
31513175
struct pci_xhci_dev_emu *dev;
31523176
struct xhci_trb evtrb;
3153-
int error;
3177+
int speed, error;
31543178

31553179
assert(portn <= XHCI_MAX_DEVS);
31563180

@@ -3159,9 +3183,9 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
31593183
port = XHCI_PORTREG_PTR(xdev, portn);
31603184
dev = XHCI_DEVINST_PTR(xdev, portn);
31613185
if (dev) {
3186+
speed = pci_xhci_convert_speed(dev->dev_ue->ue_usbspeed);
31623187
port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC);
3163-
port->portsc |= XHCI_PS_PED |
3164-
XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed);
3188+
port->portsc |= XHCI_PS_PED | XHCI_PS_SPEED_SET(speed);
31653189

31663190
if (warm && dev->dev_ue->ue_usbver == 3)
31673191
port->portsc |= XHCI_PS_WRC;

devicemodel/hw/platform/usb_pmapper.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,31 @@ static struct usb_dev_sys_ctx_info g_ctx;
2121
static inline uint8_t usb_dev_get_ep_type(struct usb_dev *udev, int pid,
2222
int epnum);
2323

24+
static int
25+
libusb_speed_to_usb_speed(int libusb_speed)
26+
{
27+
int speed = LIBUSB_SPEED_UNKNOWN;
28+
29+
switch (libusb_speed) {
30+
case LIBUSB_SPEED_LOW:
31+
speed = USB_SPEED_LOW;
32+
break;
33+
case LIBUSB_SPEED_FULL:
34+
speed = USB_SPEED_FULL;
35+
break;
36+
case LIBUSB_SPEED_HIGH:
37+
speed = USB_SPEED_HIGH;
38+
break;
39+
case LIBUSB_SPEED_SUPER:
40+
speed = USB_SPEED_SUPER;
41+
break;
42+
default:
43+
UPRINTF(LWRN, "%s unexpect speed %d\r\n", __func__,
44+
libusb_speed);
45+
}
46+
return speed;
47+
}
48+
2449
static void
2550
usb_dev_comp_req(struct libusb_transfer *libusb_xfer)
2651
{
@@ -852,6 +877,7 @@ usb_dev_info(void *pdata, int type, void *value, int size)
852877
break;
853878
case USB_INFO_SPEED:
854879
sz = sizeof(udev->speed);
880+
udev->speed = libusb_speed_to_usb_speed(udev->speed);
855881
pv = &udev->speed;
856882
break;
857883
case USB_INFO_BUS:

0 commit comments

Comments
 (0)