diff options
Diffstat (limited to 'sys')
29 files changed, 257 insertions, 509 deletions
diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index 94abe09..13eaaad 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -54,8 +54,6 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, unsigned int func, regs[4]; enum x2apic_state x2apic_state; - func = *eax; - /* * Requests for invalid CPUID levels should map to the highest * available level instead. @@ -70,6 +68,8 @@ x86_emulate_cpuid(struct vm *vm, int vcpu_id, *eax = cpu_high; } + func = *eax; + /* * In general the approach used for CPU topology is to * advertise a flat topology where all CPUs are packages with diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c index b3939d4..d2f2bc3 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c @@ -238,6 +238,16 @@ lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n) #endif /* + * FreeBSD: can't use GCC's __builtin_ctz when using sparc64 because + * gcc currently rely on libcompiler_rt. + * + * TODO: revisit this when situation changes. + */ +#if defined(__sparc64__) +#define LZ4_FORCE_SW_BITCOUNT +#endif + +/* * Compiler Options */ #if __STDC_VERSION__ >= 199901L /* C99 */ @@ -378,9 +388,38 @@ static inline int LZ4_NbCommonBytes(register U64 val) { #if defined(LZ4_BIG_ENDIAN) +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clzll(val) >> 3); #else + int r; + if (!(val >> 32)) { + r = 4; + } else { + r = 0; + val >>= 32; + } + if (!(val >> 16)) { + r += 2; + val >>= 8; + } else { + val >>= 24; + } + r += (!val); + return (r); +#endif +#else +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctzll(val) >> 3); +#else + static const int DeBruijnBytePos[64] = + { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, + 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, + 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, + 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 + }; + return DeBruijnBytePos[((U64) ((val & -val) * 0x0218A392CDABBD3F)) >> + 58]; +#endif #endif } @@ -390,9 +429,33 @@ static inline int LZ4_NbCommonBytes(register U32 val) { #if defined(LZ4_BIG_ENDIAN) +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clz(val) >> 3); #else + int r; + if (!(val >> 16)) { + r = 2; + val >>= 8; + } else { + r = 0; + val >>= 24; + } + r += (!val); + return (r); +#endif +#else +#if !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_ctz(val) >> 3); +#else + static const int DeBruijnBytePos[32] = { + 0, 0, 3, 0, 3, 1, 3, 0, + 3, 2, 2, 1, 3, 2, 0, 1, + 3, 3, 1, 2, 2, 2, 2, 0, + 3, 1, 2, 0, 1, 0, 1, 1 + }; + return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> + 27]; +#endif #endif } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c index 53ffa90..e81dc02 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c @@ -101,9 +101,8 @@ int metaslab_smo_bonus_pct = 150; * Should we be willing to write data to degraded vdevs? */ boolean_t zfs_write_to_degraded = B_FALSE; -SYSCTL_INT(_vfs_zfs, OID_AUTO, write_to_degraded, CTLFLAG_RW, - &zfs_write_to_degraded, 0, - "Allow writing data to degraded vdevs"); +SYSCTL_INT(_vfs_zfs, OID_AUTO, write_to_degraded, CTLFLAG_RWTUN, + &zfs_write_to_degraded, 0, "Allow writing data to degraded vdevs"); TUNABLE_INT("vfs.zfs.write_to_degraded", &zfs_write_to_degraded); /* diff --git a/sys/conf/files b/sys/conf/files index af256db..7790529 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1294,7 +1294,8 @@ dev/fb/splash.c optional splash dev/fdt/fdt_common.c optional fdt dev/fdt/fdt_pci.c optional fdt pci dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand -dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static +dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \ + dependency "$S/boot/fdt/dts/${FDT_DTS_FILE}" dev/fdt/fdtbus.c optional fdt dev/fdt/simplebus.c optional fdt dev/fe/if_fe.c optional fe diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 7679fd2..b6b4217 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -152,6 +152,7 @@ static void ath_init(void *); static void ath_stop_locked(struct ifnet *); static void ath_stop(struct ifnet *); static int ath_reset_vap(struct ieee80211vap *, u_long); +static void ath_start_queue(struct ifnet *ifp); static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); static int ath_ioctl(struct ifnet *, u_long, caddr_t); @@ -212,14 +213,6 @@ static void ath_dfs_tasklet(void *, int); static void ath_node_powersave(struct ieee80211_node *, int); static int ath_node_set_tim(struct ieee80211_node *, int); -static int ath_transmit(struct ifnet *ifp, struct mbuf *m); -static void ath_qflush(struct ifnet *ifp); - -static void ath_txq_qinit(struct ifnet *ifp); -static void ath_txq_qflush(struct ifnet *ifp); -static int ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0); -static void ath_txq_qrun(struct ifnet *ifp); - #ifdef IEEE80211_SUPPORT_TDMA #include <dev/ath/if_ath_tdma.h> #endif @@ -436,21 +429,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", ifp->if_xname); - /* - * This taskqueue doesn't get any higher priority - * than the ath(4) taskqueue (PI_NET) so TX won't - * pre-empt RX and other task priorities. - * - * This may not be optimal - the previous behaviour - * was to direct-dispatch frames via the sending - * task context, rather than (always) software - * queuing. - */ - sc->sc_tx_tq = taskqueue_create("ath_tx_taskq", M_NOWAIT, - taskqueue_thread_enqueue, &sc->sc_tx_tq); - taskqueue_start_threads(&sc->sc_tx_tq, 1, PI_NET, - "%s TX taskq", ifp->if_xname); - TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc); TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc); TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc); @@ -579,18 +557,13 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ifp->if_softc = sc; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - /* XXX net80211 uses if_start to re-start ifnet processing */ - ifp->if_start = ath_start; - ifp->if_transmit = ath_transmit; - ifp->if_qflush = ath_qflush; + ifp->if_start = ath_start_queue; ifp->if_ioctl = ath_ioctl; ifp->if_init = ath_init; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); - ath_txq_qinit(ifp); - ic->ic_ifp = ifp; /* XXX not right but it's not used anywhere important */ ic->ic_phytype = IEEE80211_T_OFDM; @@ -996,7 +969,6 @@ ath_detach(struct ath_softc *sc) ath_stop(ifp); ieee80211_ifdetach(ifp->if_l2com); taskqueue_free(sc->sc_tq); - taskqueue_free(sc->sc_tx_tq); #ifdef ATH_TX99_DIAG if (sc->sc_tx99 != NULL) sc->sc_tx99->detach(sc->sc_tx99); @@ -1005,7 +977,6 @@ ath_detach(struct ath_softc *sc) #ifdef ATH_DEBUG_ALQ if_ath_alq_tidyup(&sc->sc_alq); #endif - ath_txq_qflush(ifp); ath_spectral_detach(sc); ath_dfs_detach(sc); ath_desc_free(sc); @@ -2145,7 +2116,6 @@ ath_txrx_start(struct ath_softc *sc) { taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } /* @@ -2246,7 +2216,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Try to (stop any further TX/RX from occuring */ taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); ATH_PCU_LOCK(sc); ath_hal_intrset(ah, 0); /* disable interrupts */ @@ -2546,70 +2515,13 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype) } static void -ath_qflush(struct ifnet *ifp) -{ - - /* XXX complete/suspend TX */ - ath_txq_qflush(ifp); - - /* Unsuspend TX? */ -} - -/* - * Transmit a frame from net80211. - */ -static int -ath_transmit(struct ifnet *ifp, struct mbuf *m) +ath_start_queue(struct ifnet *ifp) { - struct ieee80211_node *ni; - struct ath_softc *sc = (struct ath_softc *) ifp->if_softc; - - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - - if (ath_txq_qadd(ifp, m) < 0) { - /* - * If queuing fails, the if_transmit() API makes the - * callee responsible for freeing the mbuf (rather than - * the caller, who just assumes the mbuf has been dealt - * with somehow). - * - * BUT, net80211 will free node references if if_transmit() - * fails _on encapsulated buffers_. Since drivers - * only get fully encapsulated frames from net80211 (via - * raw or otherwise APIs), we must be absolutely careful - * to not free the node ref or things will get loopy - * down the track. - * - * For tx fragments, the TX code must free whatever - * new references it created, but NOT the original - * TX node ref that was passed in. - */ - ath_freetx(m); - return (ENOBUFS); - } + struct ath_softc *sc = ifp->if_softc; - /* - * Unconditionally kick the taskqueue. - * - * Now, there's a subtle race condition possible here if we - * went down the path of only kicking the taskqueue if it - * wasn't running. If we're not absolutely, positively - * careful, we could have a small race window between - * finishing the taskqueue and clearing the TX flag, which - * would be interpreted in _this_ context as "we don't need - * to kick the TX taskqueue, as said taskqueue is already - * running." - * - * It's a problem in some of the 1GE/10GE NIC drivers. - * So until a _correct_ method for implementing this is - * drafted up and written, which avoids (potentially) - * large amounts of locking contention per-frame, let's - * just do the inefficient "kick taskqueue each time" - * method. - */ + ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: start"); ath_tx_kick(sc); - - return (0); + ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_queue: finished"); } void @@ -2636,7 +2548,9 @@ ath_start_task(void *arg, int npending) sc->sc_txstart_cnt++; ATH_PCU_UNLOCK(sc); - ath_txq_qrun(ifp); + ATH_TX_LOCK(sc); + ath_start(sc->sc_ifp); + ATH_TX_UNLOCK(sc); ATH_PCU_LOCK(sc); sc->sc_txstart_cnt--; @@ -2644,292 +2558,91 @@ ath_start_task(void *arg, int npending) ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: finished"); } -/* - * Pending TX buffer chain management routines. - */ - - -/* - * Initialise the TX queue! - */ -static void -ath_txq_qinit(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - - TAILQ_INIT(&sc->sc_txbuf_list); -} - -/* - * Add this mbuf to the TX buffer chain. - * - * This allocates an ath_buf, links the mbuf into it, and - * appends it to the end of the TX buffer chain. - * It doesn't fill out the ath_buf in any way besides - * that. - * - * Since the mbuf may be a list of mbufs representing - * 802.11 fragments, handle allocating ath_bufs for each - * of the mbuf fragments. - * - * If we queued it, 0 is returned. Else, < 0 is returned. - * - * If <0 is returned, the sender is responsible for - * freeing the mbuf if appropriate. - */ -static int -ath_txq_qadd(struct ifnet *ifp, struct mbuf *m0) +void +ath_start(struct ifnet *ifp) { struct ath_softc *sc = ifp->if_softc; - struct ath_buf *bf; - ath_bufhead frags; struct ieee80211_node *ni; - struct mbuf *m; - - /* XXX recursive TX completion -> TX? */ - ATH_TX_IC_UNLOCK_ASSERT(sc); - - /* - * We grab the node pointer, but we don't deref - * the node. The caller must be responsible for - * freeing the node reference if it decides to - * free the mbuf. - */ - ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif; - - ATH_TXBUF_LOCK(sc); - if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) { - /* XXX increment counter? */ - ATH_TXBUF_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - return (-1); - } - ATH_TXBUF_UNLOCK(sc); - - /* - * Grab a TX buffer and associated resources. - */ - bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL); - if (bf == NULL) { - device_printf(sc->sc_dev, - "%s: couldn't allocate a buffer\n", - __func__); - return (-1); - } - - /* Setup the initial buffer node contents */ - bf->bf_m = m0; - bf->bf_node = ni; - - /* - * Check for fragmentation. If this frame - * has been broken up verify we have enough - * buffers to send all the fragments so all - * go out or none... - */ - TAILQ_INIT(&frags); - if (m0->m_flags & M_FRAG) - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: txfrag\n", __func__); - if ((m0->m_flags & M_FRAG) && - !ath_txfrag_setup(sc, &frags, m0, ni)) { - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: out of txfrag buffers\n", __func__); - sc->sc_stats.ast_tx_nofrag++; - ifp->if_oerrors++; - goto bad; - } - - /* - * Don't stuff the non-fragment frame onto the fragment - * queue. ath_txfrag_cleanup() should only be called on fragments - - * ie, the _extra_ ieee80211_node references - and not the single - * node reference already done as part of the net08211 TX call - * into the driver. - */ - - ATH_TX_IC_LOCK(sc); - - /* - * Throw the single frame onto the queue. - */ - TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list); - - /* - * Update next packet duration length if it's a fragment. - * It's needed for accurate NAV calculations (which for - * fragments include the length of the NEXT fragment.) - */ - if (m0->m_nextpkt != NULL) - bf->bf_state.bfs_nextpktlen = - m0->m_nextpkt->m_pkthdr.len; - - /* - * Append the fragments. We have to populate bf and node - * references here as although the txfrag setup code does - * create buffers and increment the node ref, it doesn't - * populate the fields for us. - */ - m = m0->m_nextpkt; - while ( (bf = TAILQ_FIRST(&frags)) != NULL) { - bf->bf_m = m; - bf->bf_node = ni; - device_printf(sc->sc_dev, "%s: adding bf=%p, m=%p, ni=%p\n", - __func__, - bf, - bf->bf_m, - bf->bf_node); - TAILQ_REMOVE(&frags, bf, bf_list); - TAILQ_INSERT_TAIL(&sc->sc_txbuf_list, bf, bf_list); - - /* - * For duration (NAV) calculations, we need - * to know the next fragment size. - * - * XXX This isn't entirely accurate as it doesn't - * take pad bytes and such into account, but it'll do - * for fragment length / NAV calculations. - */ - if (m->m_nextpkt != NULL) - bf->bf_state.bfs_nextpktlen = - m->m_nextpkt->m_pkthdr.len; - - m = m->m_nextpkt; - } - ATH_TX_IC_UNLOCK(sc); - - return (0); -bad: - device_printf(sc->sc_dev, "%s: bad?!\n", __func__); - bf->bf_m = NULL; - bf->bf_node = NULL; - ATH_TXBUF_LOCK(sc); - ath_returnbuf_head(sc, bf); - ath_txfrag_cleanup(sc, &frags, ni); - ATH_TXBUF_UNLOCK(sc); - return (-1); -} - -/* - * Flush the pending TX buffer chain. - */ -static void -ath_txq_qflush(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - ath_bufhead txlist; struct ath_buf *bf; - - device_printf(sc->sc_dev, "%s: called\n", __func__); - TAILQ_INIT(&txlist); - - /* Grab lock */ - ATH_TX_IC_LOCK(sc); - - /* Copy everything out of sc_txbuf_list into txlist */ - TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); - - /* Unlock */ - ATH_TX_IC_UNLOCK(sc); - - /* Now, walk the list, freeing things */ - while ((bf = TAILQ_FIRST(&txlist)) != NULL) { - TAILQ_REMOVE(&txlist, bf, bf_list); - - if (bf->bf_node) - ieee80211_free_node(bf->bf_node); - - m_free(bf->bf_m); - - /* XXX paranoia! */ - bf->bf_m = NULL; - bf->bf_node = NULL; - - /* - * XXX Perhaps do a second pass with the TXBUF lock - * held and free them all at once? - */ - ATH_TXBUF_LOCK(sc); - ath_returnbuf_head(sc, bf); - ATH_TXBUF_UNLOCK(sc); - } -} - -/* - * Walk the TX buffer queue and call ath_tx_start() on each - * of them. - */ -static void -ath_txq_qrun(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - ath_bufhead txlist; - struct ath_buf *bf, *bf_next; - struct ieee80211_node *ni; - struct mbuf *m; + struct mbuf *m, *next; + ath_bufhead frags; + int npkts = 0; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) return; - TAILQ_INIT(&txlist); + ATH_TX_LOCK_ASSERT(sc); - /* - * Grab the frames to transmit from the tx queue - */ + ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called"); - /* Copy everything out of sc_txbuf_list into txlist */ - ATH_TX_IC_LOCK(sc); - TAILQ_CONCAT(&txlist, &sc->sc_txbuf_list, bf_list); - ATH_TX_IC_UNLOCK(sc); - - /* - * Attempt to transmit each frame. - * - * In the old code path - if a TX fragment fails, subsequent - * fragments in that group would be aborted. - * - * It would be nice to chain together TX fragments in this - * way so they can be aborted together. - */ - ATH_TX_LOCK(sc); - TAILQ_FOREACH_SAFE(bf, &txlist, bf_list, bf_next) { + for (;;) { + ATH_TXBUF_LOCK(sc); + if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) { + /* XXX increment counter? */ + ATH_TXBUF_UNLOCK(sc); + IF_LOCK(&ifp->if_snd); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + IF_UNLOCK(&ifp->if_snd); + break; + } + ATH_TXBUF_UNLOCK(sc); + /* - * Clear, because we're going to reuse this - * as a real ath_buf now + * Grab a TX buffer and associated resources. */ - ni = bf->bf_node; - m = bf->bf_m; - - bf->bf_node = NULL; - bf->bf_m = NULL; + bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL); + if (bf == NULL) + break; + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) { + ATH_TXBUF_LOCK(sc); + ath_returnbuf_head(sc, bf); + ATH_TXBUF_UNLOCK(sc); + break; + } + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + npkts ++; /* - * Remove it from the list. + * Check for fragmentation. If this frame + * has been broken up verify we have enough + * buffers to send all the fragments so all + * go out or none... */ - TAILQ_REMOVE(&txlist, bf, bf_list); - + TAILQ_INIT(&frags); + if ((m->m_flags & M_FRAG) && + !ath_txfrag_setup(sc, &frags, m, ni)) { + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: out of txfrag buffers\n", __func__); + sc->sc_stats.ast_tx_nofrag++; + ifp->if_oerrors++; + ath_freetx(m); + goto bad; + } + ifp->if_opackets++; + nextfrag: /* - * If we fail, free this buffer and go to the next one; - * ath_tx_start() frees the mbuf but not the node - * reference. + * Pass the frame to the h/w for transmission. + * Fragmented frames have each frag chained together + * with m_nextpkt. We know there are sufficient ath_buf's + * to send all the frags because of work done by + * ath_txfrag_setup. We leave m_nextpkt set while + * calling ath_tx_start so it can use it to extend the + * the tx duration to cover the subsequent frag and + * so it can reclaim all the mbufs in case of an error; + * ath_tx_start clears m_nextpkt once it commits to + * handing the frame to the hardware. */ + next = m->m_nextpkt; if (ath_tx_start(sc, ni, bf, m)) { - /* - * XXX m is freed by ath_tx_start(); node reference - * is not! - */ - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: failed; bf=%p, ni=%p, m=%p\n", - __func__, - bf, - ni, - m); + bad: ifp->if_oerrors++; + reclaim: bf->bf_m = NULL; bf->bf_node = NULL; ATH_TXBUF_LOCK(sc); ath_returnbuf_head(sc, bf); + ath_txfrag_cleanup(sc, &frags, ni); ATH_TXBUF_UNLOCK(sc); /* * XXX todo, free the node outside of @@ -2937,86 +2650,38 @@ ath_txq_qrun(struct ifnet *ifp) */ if (ni != NULL) ieee80211_free_node(ni); - } else { - /* - * Check here if the node is in power save state. - * XXX we should hold a node ref here, and release - * it after the TX has completed. - */ - ath_tx_update_tim(sc, ni, 1); - ifp->if_opackets++; + continue; } /* - * XXX should check for state change and flip out - * if needed. + * Check here if the node is in power save state. */ - } - ATH_TX_UNLOCK(sc); + ath_tx_update_tim(sc, ni, 1); - /* - * If we break out early (eg a state change) we should prepend these - * frames onto the TX queue. - */ -} - -/* - * This is now primarily used by the net80211 layer to kick-start - * queue processing. - */ -void -ath_start(struct ifnet *ifp) -{ - struct mbuf *m; - struct ath_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - int npkts = 0; - - ATH_TX_UNLOCK_ASSERT(sc); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) - return; - - /* - * If we're below the free buffer limit, don't dequeue anything. - * The original code would not dequeue anything from the queue - * if allocating an ath_buf failed. - * - * For if_transmit, we have to either queue or drop the frame. - * So we have to try and queue it _somewhere_. - */ - for (;;) { - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) { - break; + if (next != NULL) { + /* + * Beware of state changing between frags. + * XXX check sta power-save state? + */ + if (ni->ni_vap->iv_state != IEEE80211_S_RUN) { + DPRINTF(sc, ATH_DEBUG_XMIT, + "%s: flush fragmented packet, state %s\n", + __func__, + ieee80211_state_name[ni->ni_vap->iv_state]); + ath_freetx(next); + goto reclaim; + } + m = next; + bf = TAILQ_FIRST(&frags); + KASSERT(bf != NULL, ("no buf for txfrag")); + TAILQ_REMOVE(&frags, bf, bf_list); + goto nextfrag; } - /* - * If we do fail here, just break out for now - * and wait until we've transmitted something - * before we attempt again? - */ - if (ath_txq_qadd(ifp, m) < 0) { - DPRINTF(sc, ATH_DEBUG_XMIT, - "%s: ath_txq_qadd failed\n", - __func__); - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (ni != NULL) - ieee80211_free_node(ni); - ath_freetx(m); - break; - } - npkts++; + sc->sc_wd_timer = 5; } - - /* - * Kick the taskqueue into activity, but only if we - * queued something. - */ - if (npkts > 0) - ath_tx_kick(sc); + ATH_KTR(sc, ATH_KTR_TX, 1, "ath_start: finished; npkts=%d", npkts); } - static int ath_media_change(struct ifnet *ifp) { @@ -3039,7 +2704,6 @@ ath_key_update_begin(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */ } @@ -3052,7 +2716,6 @@ ath_key_update_end(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); IF_UNLOCK(&ifp->if_snd); taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } static void @@ -4273,11 +3936,11 @@ ath_tx_proc_q0(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); - ath_txq_qrun(ifp); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); + + ath_tx_kick(sc); } /* @@ -4326,11 +3989,11 @@ ath_tx_proc_q0123(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); - ath_txq_qrun(ifp); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); + + ath_tx_kick(sc); } /* @@ -4371,11 +4034,11 @@ ath_tx_proc(void *arg, int npending) if (sc->sc_softled) ath_led_event(sc, sc->sc_txrix); - ath_txq_qrun(ifp); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); + + ath_tx_kick(sc); } #undef TXQACTIVE @@ -4726,7 +4389,6 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) /* (Try to) stop TX/RX from occuring */ taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); ATH_PCU_LOCK(sc); ath_hal_intrset(ah, 0); /* Stop new RX/TX completion */ @@ -5116,7 +4778,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS); sc->sc_beacons = 0; taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } ni = ieee80211_ref_node(vap->iv_bss); @@ -5282,7 +4943,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) "%s: calibration disabled\n", __func__); } taskqueue_unblock(sc->sc_tq); - taskqueue_unblock(sc->sc_tx_tq); } else if (nstate == IEEE80211_S_INIT) { /* * If there are no vaps left in RUN state then @@ -5296,7 +4956,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* disable interrupts */ ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL); taskqueue_block(sc->sc_tq); - taskqueue_block(sc->sc_tx_tq); sc->sc_beacons = 0; } #ifdef IEEE80211_SUPPORT_TDMA diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index f35fc11..167c826 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -127,7 +127,9 @@ static inline void ath_tx_kick(struct ath_softc *sc) { - taskqueue_enqueue(sc->sc_tx_tq, &sc->sc_txpkttask); + ATH_TX_LOCK(sc); + ath_start(sc->sc_ifp); + ATH_TX_UNLOCK(sc); } /* diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index e19a637..64c4378 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -1124,11 +1124,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf) dur = rt->info[rix].lpAckDuration; if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { dur += dur; /* additional SIFS+ACK */ - if (bf->bf_state.bfs_nextpktlen == 0) { - device_printf(sc->sc_dev, - "%s: next txfrag len=0?\n", - __func__); - } + KASSERT(bf->bf_m->m_nextpkt != NULL, ("no fragment")); /* * Include the size of next fragment so NAV is * updated properly. The last fragment uses only @@ -1139,7 +1135,7 @@ ath_tx_calc_duration(struct ath_softc *sc, struct ath_buf *bf) * first fragment! */ dur += ath_hal_computetxtime(ah, rt, - bf->bf_state.bfs_nextpktlen, + bf->bf_m->m_nextpkt->m_pkthdr.len, rix, shortPreamble); } if (isfrag) { diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 52ed6d8..36923cc 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -279,8 +279,6 @@ struct ath_buf { int32_t bfs_keyix; /* crypto key index */ int32_t bfs_txantenna; /* TX antenna config */ - uint16_t bfs_nextpktlen; /* length of next frag pkt */ - /* Make this an 8 bit value? */ enum ieee80211_protmode bfs_protmode; @@ -525,7 +523,6 @@ struct ath_softc { struct mtx sc_tx_ic_mtx; /* TX queue mutex */ char sc_tx_ic_mtx_name[32]; struct taskqueue *sc_tq; /* private task queue */ - struct taskqueue *sc_tx_tq; /* private TX task queue */ struct ath_hal *sc_ah; /* Atheros HAL */ struct ath_ratectrl *sc_rc; /* tx rate control support */ struct ath_tx99 *sc_tx99; /* tx99 adjunct state */ @@ -815,6 +812,8 @@ struct ath_softc { MA_OWNED) #define ATH_TX_UNLOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_tx_mtx, \ MA_NOTOWNED) +#define ATH_TX_TRYLOCK(_sc) (mtx_owned(&(_sc)->sc_tx_mtx) != 0 && \ + mtx_trylock(&(_sc)->sc_tx_mtx)) /* * The IC TX lock is non-reentrant and serialises packet queuing from diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c index cf2ae7a..a28d612 100644 --- a/sys/dev/usb/controller/usb_controller.c +++ b/sys/dev/usb/controller/usb_controller.c @@ -427,6 +427,7 @@ usb_bus_suspend(struct usb_proc_msg *pm) struct usb_bus *bus; struct usb_device *udev; usb_error_t err; + uint8_t do_unlock; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; @@ -447,7 +448,7 @@ usb_bus_suspend(struct usb_proc_msg *pm) bus_generic_shutdown(bus->bdev); - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); if (err) @@ -464,7 +465,8 @@ usb_bus_suspend(struct usb_proc_msg *pm) if (bus->methods->set_hw_power_sleep != NULL) (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND); - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_BUS_LOCK(bus); } @@ -480,6 +482,7 @@ usb_bus_resume(struct usb_proc_msg *pm) struct usb_bus *bus; struct usb_device *udev; usb_error_t err; + uint8_t do_unlock; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; @@ -489,7 +492,7 @@ usb_bus_resume(struct usb_proc_msg *pm) USB_BUS_UNLOCK(bus); - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); #if 0 DEVMETHOD(usb_take_controller, NULL); /* dummy */ #endif @@ -523,7 +526,8 @@ usb_bus_resume(struct usb_proc_msg *pm) "attach root HUB\n"); } - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_BUS_LOCK(bus); } @@ -539,6 +543,7 @@ usb_bus_shutdown(struct usb_proc_msg *pm) struct usb_bus *bus; struct usb_device *udev; usb_error_t err; + uint8_t do_unlock; bus = ((struct usb_bus_msg *)pm)->bus; udev = bus->devices[USB_ROOT_HUB_ADDR]; @@ -550,7 +555,7 @@ usb_bus_shutdown(struct usb_proc_msg *pm) bus_generic_shutdown(bus->bdev); - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); if (err) @@ -567,7 +572,8 @@ usb_bus_shutdown(struct usb_proc_msg *pm) if (bus->methods->set_hw_power_sleep != NULL) (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN); - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_BUS_LOCK(bus); } diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c index 565c26e..21479a1 100644 --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -378,6 +378,7 @@ static const STRUCT_USB_HOST_ID uftdi_devs[] = { UFTDI_DEV(FTDI, IPLUS2, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, IRTRANS, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, KBS, UFTDI_TYPE_8U232AM), + UFTDI_DEV(FTDI, KTLINK, UFTDI_TYPE_8U232AM), UFTDI_DEV(FTDI, LENZ_LIUSB, UFTDI_TYPE_AUTO), UFTDI_DEV(FTDI, LK202, UFTDI_TYPE_8U232AM), UFTDI_DEV(FTDI, LK204, UFTDI_TYPE_8U232AM), diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index c4264c5..9bf430b 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -218,10 +218,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd, mtx_unlock(&usb_ref_lock); /* - * We need to grab the sx-lock before grabbing the - * FIFO refs to avoid deadlock at detach! + * We need to grab the enumeration SX-lock before + * grabbing the FIFO refs to avoid deadlock at detach! */ - usbd_enum_lock(cpd->udev); + crd->do_unlock = usbd_enum_lock(cpd->udev); mtx_lock(&usb_ref_lock); @@ -282,9 +282,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd, return (0); error: - if (crd->is_uref) { + if (crd->do_unlock) usbd_enum_unlock(cpd->udev); + if (crd->is_uref) { if (--(cpd->udev->refcount) == 0) { cv_signal(&cpd->udev->ref_cv); } @@ -336,7 +337,7 @@ usb_unref_device(struct usb_cdev_privdata *cpd, DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref); - if (crd->is_uref) + if (crd->do_unlock) usbd_enum_unlock(cpd->udev); mtx_lock(&usb_ref_lock); diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h index 3c75701..f87ba53 100644 --- a/sys/dev/usb/usb_dev.h +++ b/sys/dev/usb/usb_dev.h @@ -84,6 +84,7 @@ struct usb_cdev_refdata { uint8_t is_write; /* location has write access */ uint8_t is_uref; /* USB refcount decr. needed */ uint8_t is_usbfs; /* USB-FS is active */ + uint8_t do_unlock; /* USB enum unlock needed */ }; struct usb_fs_privdata { diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index fdc734c..1c40815 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1546,9 +1546,6 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, return (NULL); } /* initialise our SX-lock */ - sx_init_flags(&udev->ctrl_sx, "USB device SX lock", SX_DUPOK); - - /* initialise our SX-lock */ sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK); sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS); @@ -2119,7 +2116,6 @@ usb_free_device(struct usb_device *udev, uint8_t flag) &udev->cs_msg[0], &udev->cs_msg[1]); USB_BUS_UNLOCK(udev->bus); - sx_destroy(&udev->ctrl_sx); sx_destroy(&udev->enum_sx); sx_destroy(&udev->sr_sx); diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h index 22a4652..b194256 100644 --- a/sys/dev/usb/usb_device.h +++ b/sys/dev/usb/usb_device.h @@ -181,7 +181,6 @@ union usb_device_scratch { struct usb_device { struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall * messages */ - struct sx ctrl_sx; struct sx enum_sx; struct sx sr_sx; struct mtx device_mtx; diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 34b7778..9557686 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -1841,6 +1841,17 @@ ugen_get_power_mode(struct usb_fifo *f) } static int +ugen_get_power_usage(struct usb_fifo *f) +{ + struct usb_device *udev = f->udev; + + if (udev == NULL) + return (0); + + return (udev->power); +} + +static int ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no, uint8_t set, uint16_t feature) { @@ -2202,6 +2213,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) *u.pint = ugen_get_power_mode(f); break; + case USB_GET_POWER_USAGE: + *u.pint = ugen_get_power_usage(f); + break; + case USB_SET_PORT_ENABLE: error = ugen_do_port_feature(f, *u.pint, 1, UHF_PORT_ENABLE); diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c index a775d67..7f3cdc6 100644 --- a/sys/dev/usb/usb_handle_request.c +++ b/sys/dev/usb/usb_handle_request.c @@ -149,6 +149,7 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) { struct usb_device *udev = xfer->xroot->udev; usb_error_t err = 0; + uint8_t do_unlock; /* * We need to protect against other threads doing probe and @@ -156,7 +157,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) */ USB_XFER_UNLOCK(xfer); - usbd_enum_lock(udev); + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (conf_no == USB_UNCONFIG_NO) { conf_no = USB_UNCONFIG_INDEX; @@ -179,7 +181,8 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) goto done; } done: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (err); } @@ -221,6 +224,7 @@ usb_handle_iface_request(struct usb_xfer *xfer, int error; uint8_t iface_index; uint8_t temp_state; + uint8_t do_unlock; if ((req.bmRequestType & 0x1F) == UT_INTERFACE) { iface_index = req.wIndex[0]; /* unicast */ @@ -234,7 +238,8 @@ usb_handle_iface_request(struct usb_xfer *xfer, */ USB_XFER_UNLOCK(xfer); - usbd_enum_lock(udev); + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); error = ENXIO; @@ -350,17 +355,20 @@ tr_repeat: goto tr_stalled; } tr_valid: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (0); tr_short: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (USB_ERR_SHORT_XFER); tr_stalled: - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (USB_ERR_STALLED); } diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 1d87a3f..a359ee2 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -243,7 +243,9 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up) /* check if device should be re-enumerated */ if (child->flags.usb_mode == USB_MODE_HOST) { - usbd_enum_lock(child); + uint8_t do_unlock; + + do_unlock = usbd_enum_lock(child); if (child->re_enumerate_wait) { err = usbd_set_config_index(child, USB_UNCONFIG_INDEX); @@ -262,7 +264,8 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up) child->re_enumerate_wait = 0; err = 0; } - usbd_enum_unlock(child); + if (do_unlock) + usbd_enum_unlock(child); } /* check if probe and attach should be done */ @@ -716,6 +719,7 @@ uhub_explore(struct usb_device *udev) usb_error_t err; uint8_t portno; uint8_t x; + uint8_t do_unlock; hub = udev->hub; sc = hub->hubsoftc; @@ -737,7 +741,7 @@ uhub_explore(struct usb_device *udev) * Make sure we don't race against user-space applications * like LibUSB: */ - usbd_enum_lock(udev); + do_unlock = usbd_enum_lock(udev); for (x = 0; x != hub->nports; x++) { up = hub->ports + x; @@ -817,7 +821,8 @@ uhub_explore(struct usb_device *udev) up->restartcnt = 0; } - usbd_enum_unlock(udev); + if (do_unlock) + usbd_enum_unlock(udev); /* initial status checked */ sc->sc_flags |= UHUB_FLAG_DID_EXPLORE; diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 1d9b223..979240f 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -277,7 +277,8 @@ struct usb_gen_quirk { #define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int) #define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t) #define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir) -/* 128 - 135 unused */ +/* 128 - 134 unused */ +#define USB_GET_POWER_USAGE _IOR ('U', 135, int) #define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int) #define USB_SET_TX_TIMEOUT _IOW ('U', 137, int) #define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int) diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c index 4db5b7d..1a366d6 100644 --- a/sys/dev/usb/usb_request.c +++ b/sys/dev/usb/usb_request.c @@ -389,9 +389,8 @@ usbd_get_hr_func(struct usb_device *udev) * than 30 seconds is treated like a 30 second timeout. This USB stack * does not allow control requests without a timeout. * - * NOTE: This function is thread safe. All calls to - * "usbd_do_request_flags" will be serialised by the use of an - * internal "sx_lock". + * NOTE: This function is thread safe. All calls to "usbd_do_request_flags" + * will be serialized by the use of the USB device enumeration lock. * * Returns: * 0: Success @@ -415,7 +414,7 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, uint16_t length; uint16_t temp; uint16_t acttemp; - uint8_t enum_locked; + uint8_t do_unlock; if (timeout < 50) { /* timeout is too small */ @@ -427,8 +426,6 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, } length = UGETW(req->wLength); - enum_locked = usbd_enum_is_locked(udev); - DPRINTFN(5, "udev=%p bmRequestType=0x%02x bRequest=0x%02x " "wValue=0x%02x%02x wIndex=0x%02x%02x wLength=0x%02x%02x\n", udev, req->bmRequestType, req->bRequest, @@ -459,17 +456,16 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, } /* - * We need to allow suspend and resume at this point, else the - * control transfer will timeout if the device is suspended! + * Grab the USB device enumeration SX-lock serialization is + * achieved when multiple threads are involved: */ - if (enum_locked) - usbd_sr_unlock(udev); + do_unlock = usbd_enum_lock(udev); /* - * Grab the default sx-lock so that serialisation - * is achieved when multiple threads are involved: + * We need to allow suspend and resume at this point, else the + * control transfer will timeout if the device is suspended! */ - sx_xlock(&udev->ctrl_sx); + usbd_sr_unlock(udev); hr_func = usbd_get_hr_func(udev); @@ -713,10 +709,10 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx, USB_XFER_UNLOCK(xfer); done: - sx_xunlock(&udev->ctrl_sx); + usbd_sr_lock(udev); - if (enum_locked) - usbd_sr_lock(udev); + if (do_unlock) + usbd_enum_unlock(udev); if ((mtx != NULL) && (mtx != &Giant)) mtx_lock(mtx); diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index aff55fd..6242047 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1717,6 +1717,7 @@ product FTDI 232H 0x6014 FTDI compatible adapter product FTDI SERIAL_2232D 0x9e90 FT2232D Dual port Serial product FTDI SERIAL_4232H 0x6011 FT4232H Quad port Serial product FTDI BEAGLEBONE 0xa6d0 BeagleBone +product FTDI KTLINK 0xbbe2 KT-LINK Embedded Hackers Multitool product FTDI TURTELIZER2 0xbdc8 egnite Turtelizer 2 JTAG/RS232 Adapter /* Gude Analog- und Digitalsysteme products also uses FTDI's id: */ product FTDI TACTRIX_OPENPORT_13M 0xcc48 OpenPort 1.3 Mitsubishi diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 7f70d5a..0467100 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -1567,7 +1567,6 @@ upgt_tx_done(struct upgt_softc *sc, uint8_t *data) data_tx->ni = NULL; data_tx->addr = 0; data_tx->m = NULL; - data_tx->use = 0; DPRINTF(sc, UPGT_DEBUG_TX_PROC, "TX done: memaddr=0x%08x, status=0x%04x, rssi=%d, ", diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h index fd38be1..6ef699f 100644 --- a/sys/dev/usb/wlan/if_upgtvar.h +++ b/sys/dev/usb/wlan/if_upgtvar.h @@ -352,7 +352,6 @@ struct upgt_data { struct ieee80211_node *ni; struct mbuf *m; uint32_t addr; - uint8_t use; STAILQ_ENTRY(upgt_data) next; }; typedef STAILQ_HEAD(, upgt_data) upgt_datahead; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 87d75ea..fc74bdb 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -776,7 +776,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } fhold(fp); FILEDESC_SUNLOCK(fdp); - if (arg != 0) { + if (arg >= 0) { vp = fp->f_vnode; error = vn_lock(vp, LK_SHARED); if (error != 0) { diff --git a/sys/powerpc/booke/platform_bare.c b/sys/powerpc/booke/platform_bare.c index c5739f7..65fb554 100644 --- a/sys/powerpc/booke/platform_bare.c +++ b/sys/powerpc/booke/platform_bare.c @@ -89,7 +89,7 @@ static platform_method_t bare_methods[] = { PLATFORMMETHOD(platform_reset, booke_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t bare_platform = { diff --git a/sys/powerpc/include/platformvar.h b/sys/powerpc/include/platformvar.h index b7c011d..21a1d04 100644 --- a/sys/powerpc/include/platformvar.h +++ b/sys/powerpc/include/platformvar.h @@ -81,7 +81,8 @@ typedef struct platform_kobj *platform_t; typedef struct kobj_class platform_def_t; #define platform_method_t kobj_method_t -#define PLATFORMMETHOD KOBJMETHOD +#define PLATFORMMETHOD KOBJMETHOD +#define PLATFORMMETHOD_END KOBJMETHOD_END #define PLATFORM_DEF(name) DATA_SET(platform_set, name) diff --git a/sys/powerpc/powermac/platform_powermac.c b/sys/powerpc/powermac/platform_powermac.c index 978b33a..52d5c4a 100644 --- a/sys/powerpc/powermac/platform_powermac.c +++ b/sys/powerpc/powermac/platform_powermac.c @@ -77,7 +77,7 @@ static platform_method_t powermac_methods[] = { PLATFORMMETHOD(platform_reset, powermac_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t powermac_platform = { diff --git a/sys/powerpc/ps3/platform_ps3.c b/sys/powerpc/ps3/platform_ps3.c index f06c2cf..61ce873 100644 --- a/sys/powerpc/ps3/platform_ps3.c +++ b/sys/powerpc/ps3/platform_ps3.c @@ -89,7 +89,7 @@ static platform_method_t ps3_methods[] = { PLATFORMMETHOD(platform_reset, ps3_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t ps3_platform = { diff --git a/sys/powerpc/wii/platform_wii.c b/sys/powerpc/wii/platform_wii.c index dcf1fc0..2bb6022 100644 --- a/sys/powerpc/wii/platform_wii.c +++ b/sys/powerpc/wii/platform_wii.c @@ -69,7 +69,7 @@ static platform_method_t wii_methods[] = { PLATFORMMETHOD(platform_timebase_freq, wii_timebase_freq), PLATFORMMETHOD(platform_reset, wii_reset), - { 0, 0 } + PLATFORMMETHOD_END }; static platform_def_t wii_platform = { diff --git a/sys/sys/param.h b/sys/sys/param.h index c290466..26db635 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1000027 /* Master, propagated to newvers */ +#define __FreeBSD_version 1000028 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, |