summaryrefslogtreecommitdiff
path: root/sys/dev/usb/uhci.c
AgeCommit message (Collapse)Author
2022-08-17uhci(4): Fix wrong lock in callout_halt in uhci_suspend.riastradh
Maybe this should just be unconditional and outside the lock to make it simpler. Found by code inspection. Maybe someone should test uhci suspend resume...
2022-03-13uhci(4): Stop taking the intr lock in uhci_run.riastradh
Not needed for anything here.
2022-03-13uhci(4): Simplify uhci_run.riastradh
`locked' is always 0 now. No functional change intended.
2022-03-13uhci(4): Fix synchronization between suspend/resume and poll hub.riastradh
- sc_intr_lock is not relevant to anything here -- stop using it. - Never schedule the callout while suspended. - Don't futz with usepolling; it makes sense only when all other CPUs and threads are quiesced, which is not the case here.
2022-03-09usb: Provisionally release bus lock around ubm_rhctrl.riastradh
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.
2022-03-03usb: Hold pipe lock across upm_transfer and upm_start.riastradh
This simplifies the code and fixes races with abort. Access to the pipe's queue is now done exclusively while the pipe is locked.
2022-03-03usb: Factor usb_transfer_complete out of ubm_abortx method.riastradh
2022-03-03usb: Factor usb_insert_transfer out of upm_transfer and make private.riastradh
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.
2021-12-21Change the usb_mem API to take a bus_dma_tag_t in usb_allocmem instead ofskrll
a struct usbd_bus *. This allows an HCD to use more than one tag.
2021-10-04remove duplicate the article in comments.andvar
2021-01-05More converstion from usbd_status to int for function error reporting.skrll
This time it's the turn of usb_allocmem.
2020-12-22usb: Omit bogus assertions about struct usbd_pipe::up_intrxfer.riastradh
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
2020-07-07KASSERT polling or holding sc_lock in a few more places.skrll
kern/52569: Entering ddb using USB keyboard panics with "locking against myself"
2020-05-26Copyright maintenanceskrll
2020-05-25Be more careful with transfer descriptors and crossing page boundariesskrll
Enable USBMALLOC_MULTISEG
2020-05-15Update ux_length in usbd_setup_isoc_xfer and use this to usb_syncmemskrll
in the HCDs
2020-04-05Switch USB to use non-coherent buffers for data transfers in theskrll
same way as OpenBSD. The use of coherent (uncacheable on ARM and other arches) mappings for transfer buffers impacts performance, espcially where memcpys are involved. Audit the necessary usb_syncmem operations - a few were missing.
2020-03-15Fix a commentskrll
2020-03-15Move some commentsskrll
2020-03-15Use howmany. NFCI.skrll
2020-03-14revert the 0x% -> %# change for fixed width formats pointed out by uwe.christos
2020-03-13PR/55068: sc.dying: Fix printf formats:christos
- no %s/%p for kernel log - 0x% -> %# - always %j for kernel log
2020-02-21Fix a memory leak. Spotted by nat@skrll
2020-02-15Fix mistakes in previous sloppy change with root intr xfers.riastradh
- Make sure ux_status is set to USBD_IN_PROGRESS when started. Otherwise, if it is still in flight when we abort the pipe, usbd_ar_pipe will skip calling upm_abort. - Initialize ux_status under the lock; in principle a completion interrupt (or a delay) could race with the initialization. - KASSERT that the xfer is in progress when we're about to complete it. Candidate fix for PR kern/54963 for other HCI drivers than uhci. ok nick ok phone (This is the change that nick evidently MEANT to ok when he ok'd the previous one!)
2020-02-14Set ux_isdone in uhci_poll_hub for DIAGNOSTIC.riastradh
2020-02-14Initialize xfer->ux_status in uhci_root_intr_start.riastradh
Otherwise, it will be USBD_NOT_STARTED, so usbd_ar_pipe will skip calling upm_abort. Candidate fix for PR kern/54963, same problem as reported at: https://mail-index.NetBSD.org/current-users/2020/02/13/msg037740.html
2020-02-12Fix steady state of root intr xfers.riastradh
Why? - Avoid completing a root intr xfer multiple times in races. - Avoid potential use-after-free in poll_hub callouts (uhci, ahci). How? - Use sc->sc_intr_xfer or equivalent to store only a pending xfer that has not yet completed -- whether successfully, by timeout, or by synchronous abort. When any of those happens, set it to null under the lock, so the xfer is completed only once. - For hci drivers that use a callout to poll the root hub (uhci, ahci): . Pass the softc pointer, not the xfer, to the callout, so the callout is not even tempted to use xfer after free -- if the callout fires, but the xfer is synchronously aborted before the callout can do anything, the xfer might be freed by the time the callout starts to examine it. . Teach the callout to do nothing if it is callout_pending after it has fired. This way: 1. completion or synchronous abort can just callout_stop 2. start can just callout_schedule If the callout had already fired before (1), and doesn't acquire the bus lock until after (2), it may be tempted to abort the new root intr xfer just after submission, which would be wrong -- so instead we just have the callout do nothing if it notices it has been rescheduled, since it will fire again after the appropriate time has elapsed.
2020-02-12Factor out HCI-independent xfer completion logic.riastradh
New API for HCI drivers to synchronize hardware completion interrupts, synchronous aborts, and asynchronous timeouts: - When submitting an xfer to hardware, call usbd_xfer_schedule_timeout(xfer). - On HCI completion interrupt for xfer completion: if (!usbd_xfer_trycomplete(xfer)) return; /* timed out or aborted, ignore it */ - In upm_abort methods, call usbd_xfer_abort(xfer). For HCI drivers that use this API (not needed in drivers that don't, or for xfers like root intr xfers that don't use it): - New ubm_abortx method serves role of former *hci_abort_xfer, but without any logic for wrangling timeouts/callouts/tasks -- caller in usbd_xfer_abort has already handled them. - New ubm_dying method, returns true if the device is in the process of detaching, used by the timeout logic. Converted and tested: - ehci - ohci Converted and compile-tested: - ahci (XXX did this ever work?) - dwc2 - motg (XXX missing usbd_xfer_schedule_timeout in motg_*_start?) - uhci - xhci Not changed: - slhci (sys/dev/ic/sl811hs.c) -- doesn't use a separate per-xfer callout for timeouts (XXX but maybe should?) - ugenhc (sys/rump/dev/lib/libugenhc/ugenhc.c) -- doesn't manage its own transfer timeouts - vhci -- times transfers out only on detach; could be adapted easily if we wanted to use the xfer->ux_callout
2019-02-17Fix assertion failures triggered by usbdi.c,v 1.182, when devicesrin
are detached. This is because xfers of USBD_NOT_STARTED can be removed from queue in an invisible way to host controller drivers. Discussed on tech-kern.
2019-02-07join lines. NFC.skrll
2019-01-22Revert the KASSERTskrll
2019-01-22Add a KASSERTskrll
2018-09-16consolidate the handling of polling across HC drivers, and generic USB:mrg
- don't take mutexes if polling - normalise the code across all drivers - add some not yet code to block discovery to/from polling - minor CSE - adjust comment for usbd_set_polling() to reality now i properly understand what it is used for and why. this, with a hack to make RB_ASKNAME to wait 5 seconds allows boot -a work with USB keyboards. there are still multiple issues remaining: - discovery and polling need to be mutually exclusive - attachment of ukbd and wskbd is not handled by config_pending, and the 5 second delay isn't going to always be enough.
2018-09-03Rename min/max -> uimin/uimax for better honesty.riastradh
These functions are defined on unsigned int. The generic name min/max should not silently truncate to 32 bits on 64-bit systems. This is purely a name change -- no functional change intended. HOWEVER! Some subsystems have #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) even though our standard name for that is MIN/MAX. Although these may invite multiple evaluation bugs, these do _not_ cause integer truncation. To avoid `fixing' these cases, I first changed the name in libkern, and then compile-tested every file where min/max occurred in order to confirm that it failed -- and thus confirm that nothing shadowed min/max -- before changing it. I have left a handful of bootloaders that are too annoying to compile-test, and some dead code: cobalt ews4800mips hp300 hppa ia64 luna68k vax acorn32/if_ie.c (not included in any kernels) macppc/if_gm.c (superseded by gem(4)) It should be easy to fix the fallout once identified -- this way of doing things fails safe, and the goal here, after all, is to _avoid_ silent integer truncations, not introduce them. Maybe one day we can reintroduce min/max as type-generic things that never silently truncate. But we should avoid doing that for a while, so that existing code has a chance to be detected by the compiler for conversion to uimin/uimax without changing the semantics until we can properly audit it all. (Who knows, maybe in some cases integer truncation is actually intended!)
2018-08-09Sprinkle __diagusedprlw1
2018-08-09pull across abort fixes from nick-nhusb. add more abort fixes, usingmrg
ideas from Taylor and Nick, and myself. special thanks to both who inspired much of the code here, if not wrote it directly. among other problems, this assert should no longer trigger: panic: kernel diagnostic assertion "xfer->ux_state == XFER_ONQU" failed: file "/current/src/sys/dev/usb/usbdi.c", line 914 using usbhist i was able to track down my instance of it being related to userland close() beginning, dropping the sc_lock, and then the usb softintr completes the transfer normally, and when it is done, the abort path attempts to re-complete the transfer, and the above assert is tripped. changes from nhusb were commited with these logs: -- Move the struct usb_task to struct usbd_xfer for everyone to use. -- Set device transfer status to USBD_IN_PROGRESS if start methods succeeds -- Actually set the transfer status on transfers in ohci_abort_xfer and the controller is dying -- Don't supply the lock to callout_halt when polling as it won't be held -- Improve transfer abort -- Mark device transfers as USBD_IN_PROGRESS appropriately and improve abort handling -- #ifdef DIAGNOSTIC -> KASSERT and add another KASSERT -- Mark device transfers as USBD_IN_PROGRESS appropriately and improve abort handling -- additional changes include: - initialise the usb abort task in the HCI allocx routine, so that it can be safely usb_rem_task()'d. - rework the handling of softintr vs cancellation vs timeout abort based upon a scheme from Taylor: when completing a transfer normally: - if the status is not in progress, it must be cancelled or timed out, and we should not process this xfer. - set the status as normal. - unconditionallly callout_stop() and usb_rem_task(). they're safe and either aren't running, or will run and do nothing. - finally call usb_transfer_complete(). when aborting a transfer: - status should be cancelled or timed out. - if cancelling, callout_halt and usb_rem_task_wait() to make sure the timer is either done or cancelled. - at this point, the ux_status must not be cancelled or timed out, and if it is not in progress we're done. - set the status. - if the controller is dying, just return. - perform HCI-specific tasks to abort this xfer. - finally call usb_transfer_complete(). for the timeout and timeout task: - if the HCI is not dying, and the ux_status is in progress, then trigger the usb abort task. - remove UXFER_ABORTWAIT and UXFER_ABORTING. tested on: - multiple PC systems with several types of devices: ugen/UPS, ucom, umass with disk, ssd and cdrom backends, kbd, ms, using uhci, ehci and xhci. - erlite3: sd@umass on dwc2. - sunblade2000: kbd/ms and umass disk on ohci. untested: - motg, slhci and ahci. motg has some portion of the new scheme applied, but slhci and ahci require more study. future work includes pushing a lot of the common abort handling into usbdi.c and leaving upm_abort() for HC specific tasks, but this change is pullup-able to netbsd-7 and netbsd-8 as it does not change any external API, as well as removing over 100 lines of code while adding over 30 new asserts. XXX: pullup-7, pullup-8.
2018-04-09Stop potential misuse of vendor names and USB vendor IDs in root hubjakllsch
device and string descriptors. Firstly: Few vendors have identical PCI-SIG vendor IDs and USB-IF vendor IDs. As such, using the PCI vendor ID as a USB vendor ID may trample on whomever is allocated that USB vendor ID. Secondly: The vendor of the host controller hardware implementation has little to nothing to do with our usbroothub implementation. Thus we should not potentially associate any problems therewith to such third party. This change will result in root hubs being identified by USB Vendor ID 0x0000. Root hub vendor string will now be "NetBSD" (or, specifically: ostype). Product ID (0x0000) and product strings remain unchanged.
2017-11-17s/PR_NOWAIT/PR_WAITOK/ in HCD allocx (allocate xfer) methodskrll
2017-11-16don't lock if we are polling because we are already holding a spin lockchristos
from uhci_poll().
2017-10-28Update the kernhist(9) kernel history code to address issues identifiedpgoyette
in PR kern/52639, as well as some general cleaning-up... (As proposed on tech-kern@ with additional changes and enhancements.) Details of changes: * All history arguments are now stored as uintmax_t values[1], both in the kernel and in the structures used for exporting the history data to userland via sysctl(9). This avoids problems on some architectures where passing a 64-bit (or larger) value to printf(3) can cause it to process the value as multiple arguments. (This can be particularly problematic when printf()'s format string is not a literal, since in that case the compiler cannot know how large each argument should be.) * Update the data structures used for exporting kernel history data to include a version number as well as the length of history arguments. * All [2] existing users of kernhist(9) have had their format strings updated. Each format specifier now includes an explicit length modifier 'j' to refer to numeric values of the size of uintmax_t. * All [2] existing users of kernhist(9) have had their format strings updated to replace uses of "%p" with "%#jx", and the pointer arguments are now cast to (uintptr_t) before being subsequently cast to (uintmax_t). This is needed to avoid compiler warnings about casting "pointer to integer of a different size." * All [2] existing users of kernhist(9) have had instances of "%s" or "%c" format strings replaced with numeric formats; several instances of mis-match between format string and argument list have been fixed. * vmstat(1) has been modified to handle the new size of arguments in the history data as exported by sysctl(9). * vmstat(1) now provides a warning message if the history requested with the -u option does not exist (previously, this condition was silently ignored, with only a single blank line being printed). * vmstat(1) now checks the version and argument length included in the data exported via sysctl(9) and exits if they do not match the values with which vmstat was built. * The kernhist(9) man-page has been updated to note the additional requirements imposed on the format strings, along with several other minor changes and enhancements. [1] It would have been possible to use an explicit length (for example, uint64_t) for the history arguments. But that would require another "rototill" of all the users in the future when we add support for an architecture that supports a larger size. Also, the printf(3) format specifiers for explicitly-sized values, such as "%"PRIu64, are much more verbose (and less aesthetically appealing, IMHO) than simply using "%ju". [2] I've tried very hard to find "all [the] existing users of kernhist(9)" but it is possible that I've missed some of them. I would be glad to update any stragglers that anyone identifies.
2017-07-14Only call uhci_free_stds if there are TDs to free.skrll
In uhci_alloc_std_chain ensure we fill the TD array correctly and note the number of allocated TDs so that uhci_free_stds will do the right thing Fixes a problem seen by anon
2017-06-01remove checks for failure after memory allocation calls that cannot fail:chs
kmem_alloc() with KM_SLEEP kmem_zalloc() with KM_SLEEP percpu_alloc() pserialize_create() psref_class_create() all of these paths include an assertion that the allocation has not failed, so callers should not assert that again.
2016-12-04Whitespaceskrll
2016-05-10sprinkle _KERNEL_OPTpooka
2016-05-06- don't require the lock if we are polling (early autoconf)christos
- unfold a line
2016-05-06usb is attached with config_interrupts so we can G/C the code to supportskrll
transfers when this wasn't the case.
2016-04-25Don't use uninitialized data variable when len == 0.joerg
2016-04-23Fix non-DIAGNOSTIC buildskrll
2016-04-23Merge nick-nhusbskrll
- API / infrastructure changes to support memory management changes. - Memory management improvements and bug fixes. - HCDs should now be MP safe - conversion to KERNHIST based debug - FS/LS isoc support on ehci(4). - conversion to kmem(9) - Some USB 3 support - mostly from Takahiro HAYASHI (t-hash). - interrupt transfers now get proper DMA operations - general bug fixes - kern/48308 - uhub status notification improvements - umass(4) probe fix (applied to HEAD already) - ohci(4) short transfer fix
2016-03-13KNFskrll