summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2013-02-14 15:35:58 +0000
committerattilio <attilio@FreeBSD.org>2013-02-14 15:35:58 +0000
commit8dfc0ddbd33b346cefd47e11711579b57c7eae85 (patch)
treed4f8ac86fbe0096edb9909d61f9461520907f27d /sys
parente403650531652add76cee5a4c90e0b856b582026 (diff)
parentdafec87d6530b11c5bda97895b6008e28d4686f2 (diff)
downloadFreeBSD-src-8dfc0ddbd33b346cefd47e11711579b57c7eae85.zip
FreeBSD-src-8dfc0ddbd33b346cefd47e11711579b57c7eae85.tar.gz
MFC
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/vmm/x86.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c63
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c5
-rw-r--r--sys/conf/files3
-rw-r--r--sys/dev/ath/if_ath.c541
-rw-r--r--sys/dev/ath/if_ath_misc.h4
-rw-r--r--sys/dev/ath/if_ath_tx.c8
-rw-r--r--sys/dev/ath/if_athvar.h5
-rw-r--r--sys/dev/usb/controller/usb_controller.c18
-rw-r--r--sys/dev/usb/serial/uftdi.c1
-rw-r--r--sys/dev/usb/usb_dev.c11
-rw-r--r--sys/dev/usb/usb_dev.h1
-rw-r--r--sys/dev/usb/usb_device.c4
-rw-r--r--sys/dev/usb/usb_device.h1
-rw-r--r--sys/dev/usb/usb_generic.c15
-rw-r--r--sys/dev/usb/usb_handle_request.c20
-rw-r--r--sys/dev/usb/usb_hub.c13
-rw-r--r--sys/dev/usb/usb_ioctl.h3
-rw-r--r--sys/dev/usb/usb_request.c28
-rw-r--r--sys/dev/usb/usbdevs1
-rw-r--r--sys/dev/usb/wlan/if_upgt.c1
-rw-r--r--sys/dev/usb/wlan/if_upgtvar.h1
-rw-r--r--sys/kern/kern_descrip.c2
-rw-r--r--sys/powerpc/booke/platform_bare.c2
-rw-r--r--sys/powerpc/include/platformvar.h3
-rw-r--r--sys/powerpc/powermac/platform_powermac.c2
-rw-r--r--sys/powerpc/ps3/platform_ps3.c2
-rw-r--r--sys/powerpc/wii/platform_wii.c2
-rw-r--r--sys/sys/param.h2
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,
OpenPOWER on IntegriCloud