| Age | Commit message (Collapse) | Author |
|
|
|
Just use kmem_zalloc; don't memset it to zero, especially not after
we just inserted it into the list, with the side effect of deleting
the rest of the list!
|
|
This way one device driver can have multiple video0, video1, &c.,
interfaces attached, using independent state and a common parent.
|
|
|
|
|
|
The device is gone so control transfers won't complete anyway. This
obviates the need to wait for usbd_do_request to time out.
Seems like maybe we should make _all_ xfers fail with USBD_CANCELLED
when the device is detached, but there's no list of pipes we can just
walk down to suspend them, so we'd have to find another way to do so.
For now, we'll just keep having drivers suspend/abort pipes other
than the control pipe.
|
|
|
|
The xfer callback must not be invoked synchronously, because it might
need to take a lock that the caller holds.
However, the hci might return failure to the caller, meaning the xfer
callback will not be invoked at all.
|
|
This simplifies the code and fixes races with abort. Access to the
pipe's queue is now done exclusively while the pipe is locked.
|
|
Otherwise this test is racy and can cause the bad state of a pipe
with a transfer that will never be completed in a pipe that's about
to close under the expectation that the pipe is empty.
|
|
This makes it clearer which part happens irrespective of error
(putting it on the queue -- unconditional, not rolled back by
usb_insert_transfer) and what the possible `errors' mean (neither of
which is an error, per se).
|
|
- New usbd_suspend_pipe to persistently stop transfers on a pipe and
cancel pending ones or wait for their callbacks to finish.
Idempotent.
- New usbd_resume_pipe to allow transfers again. Idempotent, but no
new xfers may be submitted before repeating this.
This way it is safe to usbd_abort_pipe in two threads concurrently,
e.g. if one thread is closing a device while another is revoking it
-- but the threads have to agree on when it is done being aborted
before starting to use it again.
- Existing usbd_abort_pipe now does suspend then resume. No change
in semantics so drivers that relied on being able to submit
transfers again won't be broken any worse than the already are
broken.
This allows drivers to avoid races such as:
/* read */
if (sc->sc_dying)
return ENXIO;
/* (*) */
err = usbd_bulk_transfer(...);
/* detach or or close */
sc->sc_dying = true;
usbd_abort_pipe(...);
wait_for_io_to_drain(...);
The detach or close logic might happen at the same time as (*), with
no way to stop the bulk transfer before it starts, leading to
deadlock when detach/close waits for I/O operations like read to
drain. Instead, the close routine can use usbd_suspend_pipe, and the
usbd_bulk_transfer is guaranteed to fail.
But some drivers such as ucom(4) don't close and reopen pipes after
aborting them -- they open on attach and close on detach, and just
abort when the /dev node is closed, expecting that xfers will
continue to work when next opened. These drivers can instead use
usbd_suspend_pipe on close and usbd_resume_pipe on open. Perhaps it
would be better to make them open pipes on open and close pipes on
close, but these functions make for a less intrusive transition.
|
|
No functional change.
|
|
|
|
|
|
|
|
|
|
Prune dead branches as a result of this change.
|
|
Prune dead branches as a result of this change.
|
|
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.
|
|
|
|
|
|
uno_stop is supposed to have exclusive access to the hardware; this
ensures that any concurrent uno_rx_loop has completed before we enter
uno_stop.
|
|
|
|
|
|
|
|
Make it private; no need for drivers to call it any more.
|
|
|
|
|
|
|
|
Only those drivers where *_uno_stop is just *_reset, and *_uno_init
immediately calls *_reset afterward, are affected.
|
|
Make usbnet_stop private now that no drivers use it.
None of the driver-independent logic in usbnet_stop has any effect at
this point because we are guaranteed not to be running, so only the
driver-dependent logic in *_uno_stop (at most) is needed.
For drivers with no *_uno_stop, just omit the call to usbnet_stop
altogether.
Some of this logic is obviously redundant with the subsequent call to
*_reset -- to be addressed in a subsequent commit.
|
|
usbnet(9) guarantees !IFF_RUNNING now before calling it.
|
|
The network stack _shouldn't_ ever call us if so, but I'm not yet
sure it _won't_.
|
|
usbnet(9) already checks this immediately before calling *_uno_init.
|
|
Init/stop and ioctl happen under IFNET_LOCK. Multicast updates only
happen after init and before stop. Core lock is no longer a relevant
part of the API. Internally, it serves essentially just to lock out
asynchronous mii activity during init/stop.
|
|
XXX definitely need to test this one
|
|
During attach, the caller has exclusive access to the usbnet until
usbnet_attach_ifp. At other times, register access is serialized
either by the usbnet multicast lock or by IFNET_LOCK.
|
|
No drivers need to use these.
|
|
Some callers don't check the error code, e.g. ~all the mii phy
drivers using PHY_READ. Just return zero if the device is gone or
the xfer fails for any other reason.
|
|
The usbnet wrappers don't add anything important. We already test
usbnet_isdying in axen_cmd, and that's already a best-effort thing
(which should probably be done better by having usbd_do_request fail
promptly if detaching anyway).
|
|
These only happen either during the transition up or down (init or
stop), or while that transition is excluded (ioctl).
This may be called from ioctl or from init, which both hold the ifnet
lock.
XXX smsc_setoe_locked should maybe trigger reinit because the rx loop
behaves differently depending on whether checksumming is enabled.
XXX mue_sethwcsum_locked needs to exclude mcast updates.
|
|
This can change at any moment; no software lock can prevent the
device from being detached. Any test of it is necessarily
best-effort just to avoid wasting time later on waiting for requests
to fail or time out.
|
|
|
|
This way, we still have exclusive access to the registers before
calls to aue_uno_mcast can start happening without the usbnet core
lock.
|
|
|
|
To make this work:
1. Do it only under a new lock, unp_mcastlock. This lock lives at
IPL_SOFTCLOCK so it can be taken from network stack callouts. It
is forbidden to acquire the usbnet core lock under unp_mcastlock.
2. Do it only after usbnet_init_rx_tx and before usbnet_stop; if
issued at any other time, drop the update on the floor.
3. Make usbnet_init_rx_tx apply any pending multicast filter updates
under the lock before setting the flag that allows SIOCADDMULTI or
SIOCDELMULTI to apply the updates.
4. Remove core lock asserts from various drivers' register access
routines. This is necessary because the multicast filter updates
are done with register reads/writes, but _cannot_ take the core
lock when the caller holds softnet_lock.
This now programs the hardware multicast filter redundantly in many
drivers which already explicitly call *_uno_mcast from the *_uno_init
routines. This is probably harmless, but it will likely be better to
remove the explicit calls.
|
|
This legacy flag is a figment of userland's imagination. The actual
kernel state is ec->ec_flags & ETHER_F_ALLMULTI, protected by the
ETHER_LOCK, so that multicast filter updates -- which run without
IFNET_LOCK -- need not attempt to write racily to ifp->if_flags.
|
|
uno_mcast is now called with the core lock already held so there is
no need for a separate locked subroutine.
|
|
This operation only needs to update the hardware to reflect
SIOCADDMULTI/SIOCDELMULTI. Not clear that everything in aue(4) needs
to be reset -- in fact I'm pretty sure that's undesirable!
WARNING: I have not tested this with a real aue(4) device.
|