| Age | Commit message (Collapse) | Author |
|
This time for real!
|
|
fixes an assert reported by msaitoh@. also fix another missing miilock
assert in usbnet_stop() that triggered for me.
|
|
|
|
Instead, consult unp->unp_txstopped -- but the caller already
guarantees it is not stopped, so turn the conditional into an
assertion anyway.
|
|
Replaces ifp->if_flags & IFF_PROMISC in multicast filter updates.
|
|
No functional change intended.
|
|
Bringing the interface up or down is serialized by IFNET_LOCK, and we
prevent further mii callbacks with mii_down, so there's no need for
another lock to serialize uno_init, uno_stop, and the mii callbacks.
|
|
|
|
|
|
The one driver that uses it, cue(4), uses it just for statistics
gathering; hard to imagine that order could be important here. But
this will allow for some simplification of the surrounding code.
|
|
This is only allowed to be called via the uno_statchg callback, which
in turn is called only with the core lock held. (usbnet_set_link is
also called internally in usbnet(9) with the core lock held.)
|
|
In practical terms this could be done with one variable and an atomic
store, but serializing all access with a lock makes reasoning easier,
and the locks have to be taken by the logic that queries the
variables anyway, and the variables are set only under heavy-weight
configuration changes anyway.
What this accomplishes is disentangling lock order between rxlock and
txlock: they are never taken at the same time, so no order is needed.
I renamed unp_stopping to unp_stopped for a compiler-assisted audit
to make sure I reviewed every case of it.
|
|
This access was unprotected by a lock, but it's not necessary anyway:
usbnet_stop aborts the pipes, and the xfer doesn't call usbd_transfer
to reschedule itself -- it's an intr pipe, so it's rescheduled
internally by usbdi(9) in a way that usbd_abort_pipe atomically
prevents.
|
|
un->un_intr can't change after attach, and we don't open the pipe if
it's null. So no need to test it.
|
|
Not sure why I thought otherwise.
|
|
We are called without IFNET_LOCK held here, so touching ifp->if_flags
is forbidden, but that's the first thing ether_mediachange does.
XXX not right either, need to eliminate the check from
ether_mediachange
|
|
While here, use inline, not __inline__, since this is not a header
file where inline might be redefined by the user.
|
|
In usbnet.c rev. 1.16, usbnet_newbuf was first passed a buffer length
to verify it fits within MCLBYTES. It also changed m_adj to go
before, not after, setting m_len and m_pkthdr.len -- which had the
effect of making the m_adj a no-op, because after MGETHDR the mbuf
has zero length and m_adj stops at the length of the mbuf, so nothing
was aligned as intended.
To make this aligned as intended, we require the buffer length to be
_below_ MCLBYTES, by ETHER_ALIGN, so there's room for the ethernet
header in a maximum-length payload. Once we do that, it is safe to
initialize m_len = m_pkthdr.len = ETHER_ALIGN + buflen, which is
below the actual size of the mbuf (MHLEN or MCLBYTES, depending), and
_then_ do m_adj to align the pointer.
|
|
|
|
Update assertion and man page accordingly.
|
|
Prune dead branches as a result of this change.
|
|
Prune dead branches as a result of this change.
|
|
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.
|
|
|
|
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.
|
|
The network stack _shouldn't_ ever call us if so, but I'm not yet
sure it _won't_.
|
|
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.
|
|
No drivers need to use these.
|
|
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.
|
|
Every driver does this already. This will enable us to change the
lock that serializes access to the registers so we can go back to
doing this synchronously in SIOCADDMULTI/SIOCDELMULTI.
|
|
The only state this touches is unp_if_flags, and all paths touching
it also hold IFNET_LOCK -- not to mention this is the only path that
touches unp_if_flags in the first place!
|
|
Suffice it for the drivers to know that uno_tx_prepare and
uno_rx_loop have exclusive access to the chain, and, for tx,
exclusive access to the mbuf.
|
|
|
|
After mii_detach, these have all completed and no new ones can be
made, and detach doesn't start destroying anything until after
mii_detach has returned, so there is no need to hang onto a reference
count here.
|
|
These run with IFNET_LOCK held, and the interface cannot be detached
until the IFNET_LOCK is released, so there is no need to hang onto a
reference count here.
|
|
|
|
Now that is tested and set with atomic_load/store, there is no need
to hold the lock -- which means we can set it while the core lock is
held during, e.g., a reset sequence, and use that to interrupt the
sequence so it doesn't get stuck waiting to time out when the device
is physically removed.
|
|
This way we don't need to hold the core lock to avoid upsetting
sanitizers (which probably find the current code upsetting), and we
can use it to exit early from timeout loops that run under the core
lock (which is probably not necessary for them to do anyway, but
let's worry about that later).
|
|
I don't think there can be any, but this message, if printed, would
falsify my hypothesis!
|
|
This reduces code in all drivers except urndis(4) and aue(4).
However, it's still safe for urndis to drop the core lock because the
ifnet is locked, and the ifnet lock covers the DOWN->UP (uno_init)
and UP->DOWN (uno_stop) transitions.
|
|
|
|
|
|
The hardware is most likely gone, so trying to write to its registers
(and, in some cases, wait until a timeout for a device to reset) is a
waste of time. Even if it was detached only in software with drvctl,
reattaching it will reset the device anyway.
|
|
|
|
No need to take the lock again -- which might not be necessary
because the callout and task have completed, but let's obviate the
need to think about that.
|
|
usbnet_stop waits for the task to complete before resetting the
hardware, and usbnet_detach waits for usbnet_stop to complete before
destroying anything, so there's no need for any of this.
|
|
It's harmless for us to schedule the tick task even if unp_dying or
unp_stopping is set by now, because usbnet_stop will just wait for it
to finish anyway, and the callout can't be scheduled again until the
interface is done stopping and is brought back up again.
No need for unp == NULL test -- un->un_pri is initialized well before
this callout can be scheduled, and is nulled out only at the end of
usbnet_detach, at which point we have already halted this callout.
|