mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 06:29:19 +00:00
DM USB: xHCI: WA for the 'lost adb' issue.
This patch is one xDCI passthrough workaround. To support DRD in Guest, the xDCI does VT-d pass through, and DRD be emulated in xHCI mediator. With Guest S3 stress test, ramdonly the xDCI can't be emuerated by USB host even the DRD is already switch to device mode. When this issue reproduce, does DRD switch to host then switch back can resuce this issue. Besides, the virtual drd regiters need to be set to reset value during Guest warm reset flow. Tracked-On: #2326 Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>y
This commit is contained in:
parent
a4014db275
commit
79b145f89f
@ -508,6 +508,35 @@ static struct pci_xhci_option_elem xhci_option_table[] = {
|
||||
{"cap", pci_xhci_parse_extcap}
|
||||
};
|
||||
|
||||
|
||||
static void pci_xhci_reset_role(void)
|
||||
{
|
||||
int fd, rc;
|
||||
|
||||
fd = open(XHCI_NATIVE_DRD_SWITCH_PATH, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
UPRINTF(LFTL, "drd native interface open failed\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
UPRINTF(LWRN, "write device in the CRS trap\r\n");
|
||||
rc = write(fd, "host", 4);
|
||||
if (rc != 4)
|
||||
UPRINTF(LFTL, "drd 1 native interface write failure %d\r\n", rc);
|
||||
|
||||
rc = fsync(fd);
|
||||
if (rc)
|
||||
UPRINTF(LFTL, "drd 2 native interface write failure %d\r\n", rc);
|
||||
|
||||
usleep(100000);
|
||||
|
||||
rc = write(fd, "device", 6);
|
||||
if (rc != 6)
|
||||
UPRINTF(LFTL, "drd 3 native interface write failure %d\r\n", rc);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static int
|
||||
pci_xhci_get_free_vport(struct pci_xhci_vdev *xdev,
|
||||
struct usb_native_devinfo *di)
|
||||
@ -1245,6 +1274,18 @@ pci_xhci_usbcmd_write(struct pci_xhci_vdev *xdev, uint32_t cmd)
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd & XHCI_CMD_CRS)
|
||||
if (xdev->pid == XHCI_PCI_DEVICE_ID_INTEL_APL &&
|
||||
xdev->vid == XHCI_PCI_VENDOR_ID_INTEL)
|
||||
/* This is a workaround for xDCI passthru. The DRD
|
||||
* role switching is the precondition for the xDCI
|
||||
* to work properly. And theoritically, this reset
|
||||
* operation is not neccessary. But currently, due
|
||||
* to some unknown reason, this operation could help
|
||||
* xDCI works better.
|
||||
*/
|
||||
pci_xhci_reset_role();
|
||||
|
||||
cmd &= ~(XHCI_CMD_CSS | XHCI_CMD_CRS);
|
||||
return cmd;
|
||||
}
|
||||
@ -1402,7 +1443,7 @@ pci_xhci_apl_drdregs_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||
excap++;
|
||||
|
||||
if (!excap || !excap->data || excap->start != XHCI_APL_DRDCAP_BASE) {
|
||||
UPRINTF(LWRN, "drd extended capability can't be found\r\n");
|
||||
UPRINTF(LFTL, "drd extended capability can't be found\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1410,15 +1451,14 @@ pci_xhci_apl_drdregs_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||
|
||||
offset -= XHCI_APL_DRDREGS_BASE;
|
||||
if (offset != XHCI_DRD_MUX_CFG0) {
|
||||
UPRINTF(LWRN, "drd configuration register access failed.\r\n");
|
||||
UPRINTF(LFTL, "drd configuration register access failed.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (excap_drd->drdcfg0 == value) {
|
||||
UPRINTF(LDBG, "No mode switch action. Current drd: %s mode\r\n",
|
||||
UPRINTF(LFTL, "No mode switch action. Current drd: %s mode\r\n",
|
||||
excap_drd->drdcfg1 & XHCI_DRD_CFG1_HOST_MODE ?
|
||||
"host" : "device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
excap_drd->drdcfg0 = value;
|
||||
@ -1438,16 +1478,17 @@ pci_xhci_apl_drdregs_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||
|
||||
fd = open(XHCI_NATIVE_DRD_SWITCH_PATH, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
UPRINTF(LWRN, "drd native interface open failed\r\n");
|
||||
UPRINTF(LFTL, "drd native interface open failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = write(fd, mstr, msz);
|
||||
close(fd);
|
||||
UPRINTF(LWRN, "drd write native interface: rc %d\r\n", rc);
|
||||
if (rc == msz)
|
||||
excap_drd->drdcfg1 = drdcfg1;
|
||||
else {
|
||||
UPRINTF(LWRN, "drd native interface write "
|
||||
UPRINTF(LFTL, "drd native interface write "
|
||||
"%s mode failed, drdcfg0: 0x%x, "
|
||||
"drdcfg1: 0x%x.\r\n",
|
||||
value & XHCI_DRD_CFG0_IDPIN ? "device" : "host",
|
||||
@ -1468,10 +1509,10 @@ pci_xhci_excap_write(struct pci_xhci_vdev *xdev, uint64_t offset,
|
||||
if (xdev->excap_ptr && xdev->excap_write)
|
||||
rc = xdev->excap_write(xdev, offset, value);
|
||||
else
|
||||
UPRINTF(LWRN, "write invalid offset 0x%lx\r\n", offset);
|
||||
UPRINTF(LWRN, "drd write invalid offset 0x%lx\r\n", offset);
|
||||
|
||||
if (rc)
|
||||
UPRINTF(LWRN, "something wrong for xhci excap offset "
|
||||
UPRINTF(LWRN, "drd something wrong for xhci excap offset "
|
||||
"0x%lx write \r\n", offset);
|
||||
}
|
||||
|
||||
@ -3540,6 +3581,7 @@ pci_xhci_excap_read(struct pci_xhci_vdev *xdev, uint64_t offset)
|
||||
excap++;
|
||||
}
|
||||
|
||||
UPRINTF(LWRN, "drd read offset 0x%lx\r\n", offset);
|
||||
if (!excap || excap->start == EXCAP_GROUP_END) {
|
||||
UPRINTF(LWRN, "extended capability 0x%lx can't be found\r\n",
|
||||
offset);
|
||||
@ -3552,6 +3594,7 @@ pci_xhci_excap_read(struct pci_xhci_vdev *xdev, uint64_t offset)
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
|
||||
UPRINTF(LWRN, "drd read offset 0x%lx, value: %u\r\n", offset, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -4205,6 +4248,9 @@ pci_xhci_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
|
||||
usb_dev_sys_deinit();
|
||||
|
||||
excap_drd_apl.drdcfg0 = 0;
|
||||
excap_drd_apl.drdcfg1 = 0;
|
||||
|
||||
xdev->vbdp_polling = false;
|
||||
sem_post(&xdev->vbdp_sem);
|
||||
pthread_join(xdev->vbdp_thread, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user