mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 06:29:19 +00:00
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>
This commit is contained in:
parent
d6cc701c89
commit
d24213db2d
@ -757,6 +757,31 @@ pci_xhci_is_valid_portnum(int n)
|
||||
return n > 0 && n <= XHCI_MAX_DEVS;
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_convert_speed(int lspeed)
|
||||
{
|
||||
/* according to xhci spec, zero means undefined speed */
|
||||
int speed = 0;
|
||||
|
||||
switch (lspeed) {
|
||||
case USB_SPEED_LOW:
|
||||
speed = 0x2;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
speed = 0x1;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
speed = 0x3;
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
speed = 0x4;
|
||||
break;
|
||||
default:
|
||||
UPRINTF(LFTL, "unkown speed %08x\r\n", lspeed);
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_port_chg(struct pci_xhci_vdev *xdev, int port, int conn)
|
||||
{
|
||||
@ -779,12 +804,11 @@ pci_xhci_port_chg(struct pci_xhci_vdev *xdev, int port, int conn)
|
||||
reg->portsc |= (XHCI_PS_CSC |
|
||||
XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET));
|
||||
} else {
|
||||
speed = dev->dev_ue->ue_usbspeed;
|
||||
speed = pci_xhci_convert_speed(dev->dev_ue->ue_usbspeed);
|
||||
reg->portsc = XHCI_PS_CCS | XHCI_PS_PP | XHCI_PS_CSC;
|
||||
reg->portsc |= XHCI_PS_SPEED_SET(speed);
|
||||
}
|
||||
|
||||
|
||||
/* make an event for the guest OS */
|
||||
pci_xhci_set_evtrb(&evtrb,
|
||||
port,
|
||||
@ -3150,7 +3174,7 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
|
||||
struct pci_xhci_portregs *port;
|
||||
struct pci_xhci_dev_emu *dev;
|
||||
struct xhci_trb evtrb;
|
||||
int error;
|
||||
int speed, error;
|
||||
|
||||
assert(portn <= XHCI_MAX_DEVS);
|
||||
|
||||
@ -3159,9 +3183,9 @@ pci_xhci_reset_port(struct pci_xhci_vdev *xdev, int portn, int warm)
|
||||
port = XHCI_PORTREG_PTR(xdev, portn);
|
||||
dev = XHCI_DEVINST_PTR(xdev, portn);
|
||||
if (dev) {
|
||||
speed = pci_xhci_convert_speed(dev->dev_ue->ue_usbspeed);
|
||||
port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC);
|
||||
port->portsc |= XHCI_PS_PED |
|
||||
XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed);
|
||||
port->portsc |= XHCI_PS_PED | XHCI_PS_SPEED_SET(speed);
|
||||
|
||||
if (warm && dev->dev_ue->ue_usbver == 3)
|
||||
port->portsc |= XHCI_PS_WRC;
|
||||
|
@ -21,6 +21,31 @@ static struct usb_dev_sys_ctx_info g_ctx;
|
||||
static inline uint8_t usb_dev_get_ep_type(struct usb_dev *udev, int pid,
|
||||
int epnum);
|
||||
|
||||
static int
|
||||
libusb_speed_to_usb_speed(int libusb_speed)
|
||||
{
|
||||
int speed = LIBUSB_SPEED_UNKNOWN;
|
||||
|
||||
switch (libusb_speed) {
|
||||
case LIBUSB_SPEED_LOW:
|
||||
speed = USB_SPEED_LOW;
|
||||
break;
|
||||
case LIBUSB_SPEED_FULL:
|
||||
speed = USB_SPEED_FULL;
|
||||
break;
|
||||
case LIBUSB_SPEED_HIGH:
|
||||
speed = USB_SPEED_HIGH;
|
||||
break;
|
||||
case LIBUSB_SPEED_SUPER:
|
||||
speed = USB_SPEED_SUPER;
|
||||
break;
|
||||
default:
|
||||
UPRINTF(LWRN, "%s unexpect speed %d\r\n", __func__,
|
||||
libusb_speed);
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
static void
|
||||
usb_dev_comp_req(struct libusb_transfer *libusb_xfer)
|
||||
{
|
||||
@ -852,6 +877,7 @@ usb_dev_info(void *pdata, int type, void *value, int size)
|
||||
break;
|
||||
case USB_INFO_SPEED:
|
||||
sz = sizeof(udev->speed);
|
||||
udev->speed = libusb_speed_to_usb_speed(udev->speed);
|
||||
pv = &udev->speed;
|
||||
break;
|
||||
case USB_INFO_BUS:
|
||||
|
Loading…
Reference in New Issue
Block a user