Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Experimental support for fragmentation and RTS/CTS.



details:   https://anonhg.NetBSD.org/src/rev/a60ba9a839db
branches:  trunk
changeset: 747404:a60ba9a839db
user:      dyoung <dyoung%NetBSD.org@localhost>
date:      Sun Sep 13 22:07:34 2009 +0000

description:
Experimental support for fragmentation and RTS/CTS.

Delete unused atw_voodoo and constants.

Export Tx/Rx statistics with evcnt(9).

Correct the Short Inter-Frame Space (SIFS) that we write to ADM8211's
registers; I do not recall if that corrected the SIFS that I observed
"on the air."  Use the constant IEEE80211_DUR_DS_EIFS to configure
the ADM8211's EIFS, instead of writing the same "magic" number,
0x64, that my reference driver wrote.

Do not clear OACTIVE in atw_init(), because atw_stop() cleared it
previously by calling atw_txdrain().

Use the net80211 short-preamble flag and instead of ATW_SHPREAMBLE.

Add an ADM8211 workaround from the reference driver, atw_workaround1(),
but don't compile it right now.

In at_intr(), don't stop processing the interrupt status after
restarting the receive ring, but process Tx interrupt status.  If
a packet's Tx lifetime is exceeded, reinitialize the device to get
packets moving again.  If the Tx FIFO underflows, restart the
transmitter, not the receiver!

Avoid losing synchronization with the Rx ring by replicating one
of Charles Hannum's fixes to rtw(4) here: receiving a management
packet may, as a side-effect, reset the Rx ring, so refer to the
softc's Rx ring pointer, sc_rxptr, every time through the loop in
atw_rxintr(), instead of refering to a pointer on the stack, i.

Re-synchronize DMA after reading the OWN bit on an Rx/Tx descriptor.
XXX This needs more work.

Reset sc_tx_timer as Tx descriptors are reclaimed from the device.

Shorten staircases in atw_watchdog().

Remove from softc an unused member, sc_intr_ack.

diffstat:

 sys/dev/ic/atw.c    |  214 +++++++++++++++++++++++++++++++++++----------------
 sys/dev/ic/atwvar.h |   43 +++++-----
 2 files changed, 167 insertions(+), 90 deletions(-)

diffs (truncated from 564 to 300 lines):

diff -r 3bbf371c918b -r a60ba9a839db sys/dev/ic/atw.c
--- a/sys/dev/ic/atw.c  Sun Sep 13 21:46:23 2009 +0000
+++ b/sys/dev/ic/atw.c  Sun Sep 13 22:07:34 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atw.c,v 1.144 2009/09/05 14:19:30 tsutsui Exp $  */
+/*     $NetBSD: atw.c,v 1.145 2009/09/13 22:07:34 dyoung Exp $  */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.144 2009/09/05 14:19:30 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.145 2009/09/13 22:07:34 dyoung Exp $");
 
 #include "bpfilter.h"
 
@@ -48,6 +48,7 @@
 #include <sys/ioctl.h>
 #include <sys/errno.h>
 #include <sys/device.h>
+#include <sys/kauth.h>
 #include <sys/time.h>
 #include <lib/libkern/libkern.h>
 
@@ -131,10 +132,6 @@
 
 #define ATW_REFSLAVE   /* slavishly do what the reference driver does */
 
-#define        VOODOO_DUR_11_ROUNDING          0x01 /* necessary */
-#define        VOODOO_DUR_2_4_SPECIALCASE      0x02 /* NOT necessary */
-int atw_voodoo = VOODOO_DUR_11_ROUNDING;
-
 int atw_pseudo_milli = 1;
 int atw_magic_delay1 = 100 * 1000;
 int atw_magic_delay2 = 100 * 1000;
@@ -211,7 +208,7 @@
 /* Interrupt handlers */
 void   atw_linkintr(struct atw_softc *, u_int32_t);
 void   atw_rxintr(struct atw_softc *);
-void   atw_txintr(struct atw_softc *);
+void   atw_txintr(struct atw_softc *, uint32_t);
 
 /* 802.11 state machine */
 static int     atw_newstate(struct ieee80211com *, enum ieee80211_state, int);
@@ -718,7 +715,7 @@
         * before this point releases all resources that may have been
         * allocated.
         */
-       sc->sc_flags |= ATWF_ATTACHED /* | ATWF_RTSCTS */;
+       sc->sc_flags |= ATWF_ATTACHED;
 
        ATW_DPRINTF((" SROM MAC %04x%04x%04x",
            htole16(sc->sc_srom[ATW_SR_MAC00]),
@@ -1158,10 +1155,10 @@
         * Go figure.
         */
        ifst = __SHIFTIN(IEEE80211_DUR_DS_SLOT, ATW_IFST_SLOT_MASK) |
-             __SHIFTIN(22 * 5 /* IEEE80211_DUR_DS_SIFS */ /* # of 22 MHz cycles */,
+             __SHIFTIN(22 * 10 /* IEEE80211_DUR_DS_SIFS */ /* # of 22 MHz cycles */,
                     ATW_IFST_SIFS_MASK) |
              __SHIFTIN(IEEE80211_DUR_DS_DIFS, ATW_IFST_DIFS_MASK) |
-             __SHIFTIN(0x64 /* IEEE80211_DUR_DS_EIFS */, ATW_IFST_EIFS_MASK);
+             __SHIFTIN(IEEE80211_DUR_DS_EIFS, ATW_IFST_EIFS_MASK);
 
        ATW_WRITE(sc, ATW_IFST, ifst);
 }
@@ -1436,7 +1433,6 @@
         * Note that the interface is now running.
         */
        ifp->if_flags |= IFF_RUNNING;
-       ifp->if_flags &= ~IFF_OACTIVE;
 
        /* send no beacons, yet. */
        atw_start_beacon(sc, 0);
@@ -1447,7 +1443,7 @@
                error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
  out:
        if (error) {
-               ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+               ifp->if_flags &= ~IFF_RUNNING;
                sc->sc_tx_timer = 0;
                ifp->if_timer = 0;
                printf("%s: interface not running\n", device_xname(sc->sc_dev));
@@ -2368,7 +2364,7 @@
        /* TBD use ni_capinfo */
 
        capinfo = 0;
-       if (sc->sc_flags & ATWF_SHORT_PREAMBLE)
+       if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
                capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
        if (ic->ic_flags & IEEE80211_F_PRIVACY)
                capinfo |= IEEE80211_CAPINFO_PRIVACY;
@@ -2677,8 +2673,7 @@
        /*
         * Mark the interface down and cancel the watchdog timer.
         */
-       ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-       sc->sc_tx_timer = 0;
+       ifp->if_flags &= ~IFF_RUNNING;
        ifp->if_timer = 0;
 
        if (disable) {
@@ -2777,6 +2772,30 @@
        return true;
 }
 
+#if 0
+static void
+atw_workaround1(struct atw_softc *sc)
+{
+       uint32_t test1;
+
+       test1 = ATW_READ(sc, ATW_TEST1);
+
+       sc->sc_misc_ev.ev_count++;
+
+       if ((test1 & ATW_TEST1_RXPKT1IN) != 0) {
+               sc->sc_rxpkt1in_ev.ev_count++;
+               return;
+       }
+       if (__SHIFTOUT(test1, ATW_TEST1_RRA_MASK) ==
+           __SHIFTOUT(test1, ATW_TEST1_RWA_MASK)) {
+               sc->sc_rxamatch_ev.ev_count++;
+               return;
+       }
+       sc->sc_workaround1_ev.ev_count++;
+       (void)atw_init(&sc->sc_if);
+}
+#endif
+
 int
 atw_intr(void *arg)
 {
@@ -2863,17 +2882,17 @@
                                    device_xname(sc->sc_dev));
                                /* Get the receive process going again. */
                                ATW_WRITE(sc, ATW_RDR, 0x1);
-                               break;
                        }
                }
 
                if (txstatus) {
                        /* Sweep up transmit descriptors. */
-                       atw_txintr(sc);
+                       atw_txintr(sc, txstatus);
 
                        if (txstatus & ATW_INTR_TLT) {
                                DPRINTF(sc, ("%s: tx lifetime exceeded\n",
                                    device_xname(sc->sc_dev)));
+                               (void)atw_init(&sc->sc_if);
                        }
 
                        if (txstatus & ATW_INTR_TRT) {
@@ -2903,7 +2922,7 @@
                                 */
                                ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
                                DELAY(atw_nar_delay);
-                               ATW_WRITE(sc, ATW_RDR, 0x1);
+                               ATW_WRITE(sc, ATW_TDR, 0x1);
                                /* XXX Log every Nth underrun from
                                 * XXX now on?
                                 */
@@ -3073,7 +3092,7 @@
        int i, len, rate, rate0;
        u_int32_t rssi, ctlrssi;
 
-       for (i = sc->sc_rxptr;; i = ATW_NEXTRX(i)) {
+       for (i = sc->sc_rxptr;; i = sc->sc_rxptr) {
                rxs = &sc->sc_rxsoft[i];
 
                ATW_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
@@ -3082,8 +3101,12 @@
                ctlrssi = le32toh(sc->sc_rxdescs[i].ar_ctlrssi);
                rate0 = __SHIFTOUT(rxstat, ATW_RXSTAT_RXDR_MASK);
 
-               if (rxstat & ATW_RXSTAT_OWN)
-                       break; /* We have processed all receive buffers. */
+               if (rxstat & ATW_RXSTAT_OWN) {
+                       ATW_CDRXSYNC(sc, i, BUS_DMASYNC_PREREAD);
+                       break;
+               }
+
+               sc->sc_rxptr = ATW_NEXTRX(i);
 
                DPRINTF3(sc,
                    ("%s: rx stat %08x ctlrssi %08x buf1 %08x buf2 %08x\n",
@@ -3224,9 +3247,6 @@
                ieee80211_input(ic, m, ni, (int)rssi, 0);
                ieee80211_free_node(ni);
        }
-
-       /* Update the receive pointer. */
-       sc->sc_rxptr = i;
 }
 
 /*
@@ -3235,7 +3255,7 @@
  *     Helper; handle transmit interrupts.
  */
 void
-atw_txintr(struct atw_softc *sc)
+atw_txintr(struct atw_softc *sc, uint32_t status)
 {
        static char txstat_buf[sizeof("ffffffff<>" ATW_TXSTAT_FMT)];
        struct ifnet *ifp = &sc->sc_if;
@@ -3273,17 +3293,20 @@
                                if (i == txs->txs_lastdesc)
                                        break;
                        }
+                       ATW_CDTXSYNC(sc, txs->txs_firstdesc,
+                           txs->txs_ndescs - 1, BUS_DMASYNC_PREREAD);
                }
 #endif
 
                txstat = le32toh(sc->sc_txdescs[txs->txs_lastdesc].at_stat);
-               if (txstat & ATW_TXSTAT_OWN)
+               if (txstat & ATW_TXSTAT_OWN) {
+                       ATW_CDTXSYNC(sc, txs->txs_lastdesc, 1,
+                           BUS_DMASYNC_PREREAD);
                        break;
+               }
 
                SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
 
-               sc->sc_txfree += txs->txs_ndescs;
-
                bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
                    0, txs->txs_dmamap->dm_mapsize,
                    BUS_DMASYNC_POSTWRITE);
@@ -3291,10 +3314,11 @@
                m_freem(txs->txs_mbuf);
                txs->txs_mbuf = NULL;
 
+               sc->sc_txfree += txs->txs_ndescs;
                SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
 
-               KASSERT(!(SIMPLEQ_EMPTY(&sc->sc_txfreeq) ||
-                       sc->sc_txfree == 0));
+               KASSERT(!SIMPLEQ_EMPTY(&sc->sc_txfreeq) && sc->sc_txfree != 0);
+               sc->sc_tx_timer = 0;
                ifp->if_flags &= ~IFF_OACTIVE;
 
                if ((ifp->if_flags & IFF_DEBUG) != 0 &&
@@ -3306,20 +3330,21 @@
                            __SHIFTOUT(txstat, ATW_TXSTAT_ARC_MASK));
                }
 
+               sc->sc_xmit_ev.ev_count++;
+
                /*
                 * Check for errors and collisions.
                 */
                if (txstat & ATW_TXSTAT_TUF)
-                       sc->sc_stats.ts_tx_tuf++;
+                       sc->sc_tuf_ev.ev_count++;
                if (txstat & ATW_TXSTAT_TLT)
-                       sc->sc_stats.ts_tx_tlt++;
+                       sc->sc_tlt_ev.ev_count++;
                if (txstat & ATW_TXSTAT_TRT)
-                       sc->sc_stats.ts_tx_trt++;
+                       sc->sc_trt_ev.ev_count++;
                if (txstat & ATW_TXSTAT_TRO)
-                       sc->sc_stats.ts_tx_tro++;
-               if (txstat & ATW_TXSTAT_SOFBR) {
-                       sc->sc_stats.ts_tx_sofbr++;
-               }
+                       sc->sc_tro_ev.ev_count++;
+               if (txstat & ATW_TXSTAT_SOFBR)
+                       sc->sc_sofbr_ev.ev_count++;
 
                if ((txstat & ATW_TXSTAT_ES) == 0)
                        ifp->if_collisions +=
@@ -3330,14 +3355,7 @@
                ifp->if_opackets++;
        }
 
-       /*
-        * If there are no more pending transmissions, cancel the watchdog
-        * timer.
-        */
-       if (txs == NULL) {
-               KASSERT((ifp->if_flags & IFF_OACTIVE) == 0);
-               sc->sc_tx_timer = 0;
-       }
+       KASSERT(txs != NULL || (ifp->if_flags & IFF_OACTIVE) == 0);
 }
 
 /*
@@ -3355,18 +3373,14 @@
        if (ATW_IS_ENABLED(sc) == 0)
                return;
 
-       if (sc->sc_rescan_timer) {
-               if (--sc->sc_rescan_timer == 0)
-                       (void)ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-       }
-       if (sc->sc_tx_timer) {
-               if (--sc->sc_tx_timer == 0 &&



Home | Main Index | Thread Index | Old Index