usb: fixes for dwc2 + ehci.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCgAGBQJfjYeMAAoJEEy22O7T6HE4OJ4P/jfLNSd+IEYjZ/bExbFkRo8C fkP6S6Q73T0h+kx2YkazotcERduxCx8hwBCrV5yRoVLyfVreYCso154KXW8fADdq N8ejZeTQDgtinfwM7sF0XpbaG2JSp/mi9h0GBYAyBl7VtGoVr2vU2WlKuJXRaU/G zZ48Cn0AXCJwLUELOyil05vIBWzdv6cFOg9PGvl7GAn2AxVqicE2Q895A2SsN3+j 1zcZfgF37xeB2+CzaozggLxsmdjEHBmK4/v1+T62COjpFZp4FKM4YDb409dKDXFm Ld6ZgQnchL+7Hfs6Imh/7Y8xnoVew5nrNw/iwe5qUoc3vOXW9v7WCdgFJxYWuDWT VO8HKWSPGW5xcKNeBzswOw00POwvMsOc90ExkrLHX4s5613ITpv8JWUaoOIUygqU MeO5lcy7XnCzRdyhT9Bp7Asfn3chYEIaxG74YY1JOMiLhQLR+z79c1Tm6xiLZ6nH zueAG3+wHduMvE43+5y2e+1IRbyrhPlWWuuJBnMHkVEVe3FACfO14Ai1vkLy3D9J nF06F0O3QuxahmJuGaGemj6C1aI165Lj9hh27qRw/PEtq7qyXgtRvzWXgKMc+PSp xaVTTjuHl8jyOpBAPbyjM81xGqietimSHcHrXMABCzUNXiXuFEr3P1r0WkV4jifs 77S1ndygtpitLpgZFwtx =etZw -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/usb-20201019-pull-request' into staging usb: fixes for dwc2 + ehci. # gpg: Signature made Mon 19 Oct 2020 13:33:16 BST # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/usb-20201019-pull-request: hw/usb/hcd-dwc2: fix divide-by-zero in dwc2_handle_packet() usb/hcd-ehci: Fix error handling on missing device for iTD usb: hcd-dwc2: change assert()s to qemu_log_mask(LOG_GUEST_ERROR...) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
000f5b8f46
@ -238,13 +238,24 @@ static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev,
|
||||
pid = get_field(hctsiz, TSIZ_SC_MC_PID);
|
||||
pcnt = get_field(hctsiz, TSIZ_PKTCNT);
|
||||
len = get_field(hctsiz, TSIZ_XFERSIZE);
|
||||
assert(len <= DWC2_MAX_XFER_SIZE);
|
||||
if (len > DWC2_MAX_XFER_SIZE) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: HCTSIZ transfer size too large\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
chan = index >> 3;
|
||||
p = &s->packet[chan];
|
||||
|
||||
trace_usb_dwc2_handle_packet(chan, dev, &p->packet, epnum, types[eptype],
|
||||
dirs[epdir], mps, len, pcnt);
|
||||
|
||||
if (mps == 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Bad HCCHAR_MPS set to zero\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
|
||||
pid = USB_TOKEN_SETUP;
|
||||
} else {
|
||||
@ -663,7 +674,12 @@ static uint64_t dwc2_glbreg_read(void *ptr, hwaddr addr, int index,
|
||||
DWC2State *s = ptr;
|
||||
uint32_t val;
|
||||
|
||||
assert(addr <= GINTSTS2);
|
||||
if (addr > GINTSTS2) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = s->glbreg[index];
|
||||
|
||||
switch (addr) {
|
||||
@ -690,7 +706,12 @@ static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
|
||||
uint32_t old;
|
||||
int iflg = 0;
|
||||
|
||||
assert(addr <= GINTSTS2);
|
||||
if (addr > GINTSTS2) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
mmio = &s->glbreg[index];
|
||||
old = *mmio;
|
||||
|
||||
@ -715,27 +736,34 @@ static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
|
||||
val &= ~GRSTCTL_DMAREQ;
|
||||
if (!(old & GRSTCTL_TXFFLSH) && (val & GRSTCTL_TXFFLSH)) {
|
||||
/* TODO - TX fifo flush */
|
||||
qemu_log_mask(LOG_UNIMP, "Tx FIFO flush not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Tx FIFO flush not implemented\n",
|
||||
__func__);
|
||||
}
|
||||
if (!(old & GRSTCTL_RXFFLSH) && (val & GRSTCTL_RXFFLSH)) {
|
||||
/* TODO - RX fifo flush */
|
||||
qemu_log_mask(LOG_UNIMP, "Rx FIFO flush not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Rx FIFO flush not implemented\n",
|
||||
__func__);
|
||||
}
|
||||
if (!(old & GRSTCTL_IN_TKNQ_FLSH) && (val & GRSTCTL_IN_TKNQ_FLSH)) {
|
||||
/* TODO - device IN token queue flush */
|
||||
qemu_log_mask(LOG_UNIMP, "Token queue flush not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Token queue flush not implemented\n",
|
||||
__func__);
|
||||
}
|
||||
if (!(old & GRSTCTL_FRMCNTRRST) && (val & GRSTCTL_FRMCNTRRST)) {
|
||||
/* TODO - host frame counter reset */
|
||||
qemu_log_mask(LOG_UNIMP, "Frame counter reset not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"%s: Frame counter reset not implemented\n",
|
||||
__func__);
|
||||
}
|
||||
if (!(old & GRSTCTL_HSFTRST) && (val & GRSTCTL_HSFTRST)) {
|
||||
/* TODO - host soft reset */
|
||||
qemu_log_mask(LOG_UNIMP, "Host soft reset not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Host soft reset not implemented\n",
|
||||
__func__);
|
||||
}
|
||||
if (!(old & GRSTCTL_CSFTRST) && (val & GRSTCTL_CSFTRST)) {
|
||||
/* TODO - core soft reset */
|
||||
qemu_log_mask(LOG_UNIMP, "Core soft reset not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Core soft reset not implemented\n",
|
||||
__func__);
|
||||
}
|
||||
/* don't allow clearing of self-clearing bits */
|
||||
val |= old & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH |
|
||||
@ -774,7 +802,12 @@ static uint64_t dwc2_fszreg_read(void *ptr, hwaddr addr, int index,
|
||||
DWC2State *s = ptr;
|
||||
uint32_t val;
|
||||
|
||||
assert(addr == HPTXFSIZ);
|
||||
if (addr != HPTXFSIZ) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = s->fszreg[index];
|
||||
|
||||
trace_usb_dwc2_fszreg_read(addr, val);
|
||||
@ -789,7 +822,12 @@ static void dwc2_fszreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
|
||||
uint32_t *mmio;
|
||||
uint32_t old;
|
||||
|
||||
assert(addr == HPTXFSIZ);
|
||||
if (addr != HPTXFSIZ) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
mmio = &s->fszreg[index];
|
||||
old = *mmio;
|
||||
|
||||
@ -810,7 +848,12 @@ static uint64_t dwc2_hreg0_read(void *ptr, hwaddr addr, int index,
|
||||
DWC2State *s = ptr;
|
||||
uint32_t val;
|
||||
|
||||
assert(addr >= HCFG && addr <= HPRT0);
|
||||
if (addr < HCFG || addr > HPRT0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = s->hreg0[index];
|
||||
|
||||
switch (addr) {
|
||||
@ -837,7 +880,12 @@ static void dwc2_hreg0_write(void *ptr, hwaddr addr, int index, uint64_t val,
|
||||
int prst = 0;
|
||||
int iflg = 0;
|
||||
|
||||
assert(addr >= HCFG && addr <= HPRT0);
|
||||
if (addr < HCFG || addr > HPRT0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
mmio = &s->hreg0[index];
|
||||
old = *mmio;
|
||||
|
||||
@ -923,7 +971,12 @@ static uint64_t dwc2_hreg1_read(void *ptr, hwaddr addr, int index,
|
||||
DWC2State *s = ptr;
|
||||
uint32_t val;
|
||||
|
||||
assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
|
||||
if (addr < HCCHAR(0) || addr > HCDMAB(DWC2_NB_CHAN - 1)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = s->hreg1[index];
|
||||
|
||||
trace_usb_dwc2_hreg1_read(addr, hreg1nm[index & 7], addr >> 5, val);
|
||||
@ -941,7 +994,12 @@ static void dwc2_hreg1_write(void *ptr, hwaddr addr, int index, uint64_t val,
|
||||
int enflg = 0;
|
||||
int disflg = 0;
|
||||
|
||||
assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
|
||||
if (addr < HCCHAR(0) || addr > HCDMAB(DWC2_NB_CHAN - 1)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
mmio = &s->hreg1[index];
|
||||
old = *mmio;
|
||||
|
||||
@ -1008,7 +1066,12 @@ static uint64_t dwc2_pcgreg_read(void *ptr, hwaddr addr, int index,
|
||||
DWC2State *s = ptr;
|
||||
uint32_t val;
|
||||
|
||||
assert(addr >= PCGCTL && addr <= PCGCCTL1);
|
||||
if (addr < PCGCTL || addr > PCGCCTL1) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = s->pcgreg[index];
|
||||
|
||||
trace_usb_dwc2_pcgreg_read(addr, pcgregnm[index], val);
|
||||
@ -1023,7 +1086,12 @@ static void dwc2_pcgreg_write(void *ptr, hwaddr addr, int index,
|
||||
uint32_t *mmio;
|
||||
uint32_t old;
|
||||
|
||||
assert(addr >= PCGCTL && addr <= PCGCCTL1);
|
||||
if (addr < PCGCTL || addr > PCGCCTL1) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
mmio = &s->pcgreg[index];
|
||||
old = *mmio;
|
||||
|
||||
@ -1108,7 +1176,7 @@ static uint64_t dwc2_hreg2_read(void *ptr, hwaddr addr, unsigned size)
|
||||
{
|
||||
/* TODO - implement FIFOs to support slave mode */
|
||||
trace_usb_dwc2_hreg2_read(addr, addr >> 12, 0);
|
||||
qemu_log_mask(LOG_UNIMP, "FIFO read not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: FIFO read not implemented\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1119,7 +1187,7 @@ static void dwc2_hreg2_write(void *ptr, hwaddr addr, uint64_t val,
|
||||
|
||||
/* TODO - implement FIFOs to support slave mode */
|
||||
trace_usb_dwc2_hreg2_write(addr, addr >> 12, orig, 0, val);
|
||||
qemu_log_mask(LOG_UNIMP, "FIFO write not implemented\n");
|
||||
qemu_log_mask(LOG_UNIMP, "%s: FIFO write not implemented\n", __func__);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps dwc2_mmio_hreg2_ops = {
|
||||
|
@ -1447,24 +1447,25 @@ static int ehci_process_itd(EHCIState *ehci,
|
||||
dev = ehci_find_device(ehci, devaddr);
|
||||
if (dev == NULL) {
|
||||
ehci_trace_guest_bug(ehci, "no device found");
|
||||
qemu_sglist_destroy(&ehci->isgl);
|
||||
return -1;
|
||||
}
|
||||
pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
|
||||
ep = usb_ep_get(dev, pid, endp);
|
||||
if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) {
|
||||
usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false,
|
||||
(itd->transact[i] & ITD_XACT_IOC) != 0);
|
||||
if (usb_packet_map(&ehci->ipacket, &ehci->isgl)) {
|
||||
qemu_sglist_destroy(&ehci->isgl);
|
||||
return -1;
|
||||
}
|
||||
usb_handle_packet(dev, &ehci->ipacket);
|
||||
usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
|
||||
} else {
|
||||
DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
|
||||
ehci->ipacket.status = USB_RET_NAK;
|
||||
ehci->ipacket.status = USB_RET_NODEV;
|
||||
ehci->ipacket.actual_length = 0;
|
||||
} else {
|
||||
pid = dir ? USB_TOKEN_IN : USB_TOKEN_OUT;
|
||||
ep = usb_ep_get(dev, pid, endp);
|
||||
if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) {
|
||||
usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false,
|
||||
(itd->transact[i] & ITD_XACT_IOC) != 0);
|
||||
if (usb_packet_map(&ehci->ipacket, &ehci->isgl)) {
|
||||
qemu_sglist_destroy(&ehci->isgl);
|
||||
return -1;
|
||||
}
|
||||
usb_handle_packet(dev, &ehci->ipacket);
|
||||
usb_packet_unmap(&ehci->ipacket, &ehci->isgl);
|
||||
} else {
|
||||
DPRINTF("ISOCH: attempt to addess non-iso endpoint\n");
|
||||
ehci->ipacket.status = USB_RET_NAK;
|
||||
ehci->ipacket.actual_length = 0;
|
||||
}
|
||||
}
|
||||
qemu_sglist_destroy(&ehci->isgl);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user