| Age | Commit message (Collapse) | Author |
|
Patches from sc.dying in kern/56115:
- Set proper Max ESIT Payload value for interrupt/isoc endpoint context.
- Set proper Average TRB Length value.
- Not tested on superspeed/superspeedplus isochronous device.
- Add handling of some error paths for isochronous transfers.
|
|
|
|
Rather than try to recover from this, just make new commands fail so
at least we don't deadlock.
XXX pullup-9
XXX pullup-10
|
|
Root intr xfers require taking adaptive locks, which is forbidden
while polling.
This is not great -- any USB transfer completion callbacks might try
to take adaptive locks, not just uhub_intr, and that will always
causes trouble. We get lucky with ukbd_intr because it's not
MP-safe, so it relies only on the kernel lock (a spin lock) anyway.
But this change brings xhci in line with ehci.
PR kern/57326
XXX pullup-8
XXX pullup-9
XXX pullup-10
|
|
|
|
|
|
- Example:
xhci4 at pci17 dev 0 function 0: AMD product 15b8 (rev. 0x00)
xhci4: 64-bit DMA
allocated pic msix10 type edge pin 0 level 6 to cpu0 slot 32 idt entry 107
xhci4: interrupting at msix10 vec 0
xhci4: xHCI version 1.20
xhci4: hcs1=1000840 hcs2=140000f1 hcs3=7000a
xhci4: hcc=0x110ffc5<XECP=0x110,MAXPSA=0xf,CFC,SEC,SPC,PAE,NSS,LTC,CSZ,AC64>
xhci4: xECP 440
xhci4: hcc2=0x3f<CIC,LEC,CTC,FSC,CMC,U3C>
xhci4: ECR: 0x00000401
xhci4: ECR: 0x02000402
xhci4: SP: 0x02000402 0x20425355 0x00180101 0x00000000
xhci4: hs ports 1 - 1
xhci4: ECR: 0x000f000a
xhci4: PAGESIZE 0x00000001
xhci4: sc_pgsz 0x00001000
xhci4: sc_maxslots 0x00000040
xhci4: sc_maxports 1
xhci4: sc_maxspbuf 2
xhci4: eventst: 0x000000013ee60fc0 0xffffb08826f5afc0 1000
xhci4: dcbaa: 0x000000013ee63000 0xffffb08826f5b000 1000
xhci4: current IMOD 0
(snip)
usb8 at xhci4: USB revision 3.1
usb9 at xhci4: USB revision 2.0
uhub8 at usb8: NetBSD (0x0000) xHCI root hub (0x0000), class 9/0, rev 3.00/1.00, addr 0
uhub8: 0 ports with 0 removable, self powered
uhub8: no ports, hub ignored
uhub8: WARNING: power management not supported
autoconfiguration error: usb8: root device is not a hub
usb8: WARNING: power management not supported
uhub9 at usb9: NetBSD (0x0000) xHCI root hub (0x0000), class 9/0, rev 2.00/1.00, addr 0
uhub9: 1 port with 1 removable, self powered
- To resolve this problem, keep number of ports of SS and HS and use
it to attach child device(s).
- Tested on ASUS TUF GAMING X670E-PLUS.
- OK'd by skrll@.
|
|
revision 1.103
date: 2019-01-11 15:43:51 +0000; author: skrll; state: Exp; lines: +12 -2; commitid: RYSytjLNOZrFCn7B;
Add a bs_barrier to make ThunderX xhci work. Not sure why this is
needed, but I'll work it out later.
Turns out bus_dma.c needed fixing which I did with
revision 1.115
date: 2019-06-14 10:09:12 +0100; author: skrll; state: Exp; lines: +39 -34; commitid: GKW2p7ijoslyu8rB;
Simplify the _ARM32_NEED_BUS_DMA_BOUNCE #ifdefs and rely on compiler
optimisation of the bouncing = false case.
Drain the write buf (aka DSB) in more cases
Catch all CPUs that support speculation. (thunderx isn't CPU_CORTEX)
|
|
Serializes access with xhci_intr.
XXX Need to ensure the interrupt handler is quiesced at this point or
else it will trip over the assertion in xhci_intr about having at
least one child.
|
|
Commands might not work after this but let's at least not deadlock --
give them an opportunity to time out or fail.
XXX Maybe set sc_dying here to skip the timeout.
|
|
|
|
If suspend failed, at least we can stop it from blocking all
subsequent xhci commands or making a second suspend crash.
|
|
|
|
|
|
On successful usbd_xfer_trycomplete, caller must set ux_status and
call usb_transfer_complete before releasing the pipe (bus) lock.
Failing to call usb_transfer_complete is a mistake. Presumably this
was intended to claim the xfer to complete it only on the last
packet.
I previously introduced the violation of this rule when the code
looked like
xfer->ux_status = err;
if (trb stuff)
usb_transfer_complete(xfer);
I mostly mechanically changed all the assignments of xfer->ux_status
to do usbd_xfer_trycomplete first and then usb_transfer_complete.
In the original, the extra assignment of xfer->ux_status in the event
we _don't_ immediately call usb_transfer_complete was likely
redundant and (except insofar as the abort protocol was broken)
harmless. But now it is a problem because of the contract between
usbd_xfer_trycomplete and usb_transfer_complete under the pipe (bus)
lock. In retrospect, the original probably should have been
if (trb stuff) {
xfer->ux_status = err;
usb_transfer_complete(xfer);
}
and my mechanical transformation should have worked, but also in
retrospect I should have put more thought into the change and done it
a little less mechanically.
|
|
|
|
|
|
Both xhci_roothub_ctrl and xhci_suspend/resume do r/m/w on them, so
use a mutex to serialize access to avoid stomping on each other.
|
|
In revision 1.155, I made the logic to abort the hardware
asynchronous, under the misapprehension that it is necessary for
ubm_abortx not to release the bus lock.
Not only is this not necessary, but it is harmful to for the logic to
be asynchronous because the caller assumes the hardware won't use any
DMA buffers by the time ubm_abortx has returned so it is safe to
recycle them -- which is false if we don't synchronously wait for the
hardware to stop.
|
|
We may still need a mechanism to serialize access to the portsc
registers between xhci_roothub_ctrl and xhci_suspend/resume, but the
bus lock is no longer that, and holding the bus lock across
usb_delay_ms may lead to deadlock by blocking the softints that wake
usb_delay_ms.
|
|
This isn't quite correct, but it avoids a deadlock:
- *_roothub_ctrl holds bus lock, waits in usb_delay_ms for kpause
- softint waits for bus lock, holds up kpause wakeup
The deadlock is new since recent changes to hold the bus lock over
upm_start/upm_transfer. Making this change regresses to other
problems:
- *_suspend/resume and *_roothub_ctrl often touch the same portsc
registers
- roothub_ctrl_abort needs to wait for ubm_rhctrl to complete.
When the bus lock was held across both, a noop served here, but we
can't hold the bus lock across both, so that doesn't work.
However, these problems -- which we've had for a long time -- seem to
be less bad than the deadlock. So let's avoid the deadlock for now
and then work out another way to serialize suspend/resume/rhctrl and
aborts.
Candidate fix for PR kern/56739.
|
|
This simplifies the code and fixes races with abort. Access to the
pipe's queue is now done exclusively while the pipe is locked.
|
|
|
|
Almost every upm_transfer function starts with:
mutex_enter(&sc->sc_lock);
err = usb_insert_transfer(xfer);
mutex_exit(&sc->sc_lock);
if (err)
return err;
Some of them have debug messages sprinkled in here too, or assert
that err == USBD_NORMAL_COMPLETION (alternative is USBD_IN_PROGRESS,
only for pipes with up_running or up_serialise, presumably not
applicable for these types of pipes). Some of them also assert
xfer->ux_status == USBD_NOT_STARTED, which is guaranteed on entry and
preserved by usb_insert_transer.
Exceptions:
- arch/mips/adm5120/dev/ahci.c ahci_device_isoc_transfer just returns
USBD_NORMAL_COMPLETION, but I'm pretty sure this is and always has
been broken anyway, so won't make anything worse (if anything, might
make it better...)
- external/bsd/dwc2/dwc2.c dwc2_device_bulk_transfer and
dwc2_device_isoc_transfer _also_ issue dwc2_device_start(xfer)
under the lock. This is probably a better way to do it, but let's
do it uniformly across all HCIs at once.
- rump/dev/lib/libugenhc/ugenhc.c rumpusb_device_bulk_transfer
sometimes returns USBD_IN_PROGRESS _without_ queueing the transfer,
in the !rump_threads case. Not really sure how this is supposed to
work... If it actually breaks anything, we can figure it out.
|
|
Use the same asynchronous task resetting a stalled/halted endpoint
and stopping a running endpoint -- either way we need to put the
endpoint back into a known state and, if there are transfers waiting
to run, start them up again.
- xhci_abortx must not drop the pipe (bus) lock -- usbdi(9) requires
this. So arrange to stop the endpoint and empty the queue
asynchronously.
- If the xhci softint claims an xfer for completion with
usbd_xfer_trycomplete, it must call usb_transfer_complete without
ever releasing the pipe (bus) lock -- it can't claim the xfer and
then defer the usb_transfer_complete to a task. So arrange to
reset the endpoint asynchronously, hold up new transfers until the
endpoint has been reset, and then do usb_transfer_complete
immediately.
|
|
|
|
4.15.2.1 is device-initiated resume, but we are doing host-initiated.
No functional change.
|
|
|
|
a struct usbd_bus *.
This allows an HCD to use more than one tag.
|
|
Access the 64-bit registers in their entirety at all times, independent
of the AC64 parameter of the hardware implementation.
Makes xhci(4) work on SolidRun MACCHIATObin (Marvell 8040 SoC)
|
|
Instead of waiting for USB_PORT_ROOT_RESET_DELAY (250ms) before checking
the port reset status, poll the PORTSC register and return early if the
reset has completed.
|
|
mainly because copy paste code big amount of files are affected.
|
|
|
|
Rules:
1. After usbd_setup_pipe*, must usbd_kill_pipe.
2. After usbd_open_pipe*, must usbd_close_pipe.
Still haven't merged the logic in usbd_kill_pipe and usbd_close_pipe,
but getting closer.
|
|
|
|
avoids KASSERT() on next xhci_open()
should fix PR kern/56194 by nia
|
|
Better to use the named constant, and although the spec says 20 ms is
enough, apparently for some devices it's not.
|
|
|
|
_Either_ an existing command in progress, _or_ an existing suspend in
progress that is not done by us, should block us; the logic I wrote
previously erroneously blocked only if both conditions happened at
the same time.
Should fix issue reported by Andrius V in the PR kern/56050 followup
discussion.
|
|
|
|
Work almost entirely done and tested by maya@ based on xhci 1.2 spec;
tidied up and tweaked by me.
Not sure about issuing Stop Endpoint commands or ensuring the Command
Ring is in the Stopped or Idle state, but this seems to work as is,
so it's already an improvement over what we had before which was no
xhci suspend/resume at all.
In particular, it's not clear to us:
- if we don't have any pending USB activity whether we need to issue
the Stop Endpoints or quiesce the command ring; but
- if we do have any pending USB activity whether issuing Stop
Endpoint is enough or whether we also need to do anything to
synchronize with other software logic to quiesce it too.
|
|
This time it's the turn of usb_allocmem.
|
|
|
|
These assertions were only valid for pipes at UE_IN_DIR, UE_INTERRUPT
endpoints created with usbd_open_pipe_intr, which uses up_intrxfer to
pass the struct usbd_xfer object to usbd_close_pipe to free later.
In contrast, for pipes at UE_OUT_DIR, UE_INTERRUPT endpoints,
up_intrxfer is never initialized, so the assertion cannot be right.
In principle we might even have more than one outstanding interrupt
transfer at a time, rendering the point of the assertion moot anyway.
Found by interrupting a uhidev write to a u2f device.
ok nick
|
|
Barriers will be applied to the entire XHCI register space.
|
|
Needs more cleanup, and more work, particularly transaction scheduling
may need to be examined with bus analyzer (to check if too frequent/
infrequent) or various isoc pipe consumers (to check if too infrequent)
and fixed if incorrect.
Begins to address PR kern/55574.
|
|
We'll need more than just the AC64 bit for the Isoc support coming up;
and we don't need to keep all the bits as bools in the softc.
|
|
|
|
|
|
|