Author: adrian
Date: Tue Jul  3 06:59:12 2012
New Revision: 238055
URL: http://svn.freebsd.org/changeset/base/238055

Log:
  Begin abstracting out the RX path in preparation for RX EDMA support.
  
  The RX EDMA support requires a modified approach to the RX descriptor
  handling.
  
  Specifically:
  
  * There's now two RX queues - high and low priority;
  * The RX queues are implemented as FIFOs; they're now an array of pointers
    to buffers;
  * .. and the RX buffer and descriptor are in the same "buffer", rather than
    being separate.
  
  So to that end, this commit abstracts out most of the RX related functions
  from the bulk of the driver.  Notably, the RX DMA/buffer allocation isn't
  updated, primarily because I haven't yet fleshed out what it should look
  like.
  
  Whilst I'm here, create a set of matching but mostly unimplemented EDMA
  stubs.
  
  Tested:
  
    * AR9280, station mode
  
  TODO:
  
    * Thorough AP and other mode testing for non-EDMA chips;
    * Figure out how to allocate RX buffers suitable for RX EDMA, including
      correctly setting the mbuf length to compensate for the RX descriptor
      and completion status area.

Added:
  head/sys/dev/ath/if_ath_rx_edma.c   (contents, props changed)
  head/sys/dev/ath/if_ath_rx_edma.h   (contents, props changed)
Modified:
  head/sys/dev/ath/if_ath.c
  head/sys/dev/ath/if_ath_rx.c
  head/sys/dev/ath/if_ath_rx.h
  head/sys/dev/ath/if_athvar.h

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c   Tue Jul  3 06:56:11 2012        (r238054)
+++ head/sys/dev/ath/if_ath.c   Tue Jul  3 06:59:12 2012        (r238055)
@@ -108,6 +108,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ath/if_ath_led.h>
 #include <dev/ath/if_ath_keycache.h>
 #include <dev/ath/if_ath_rx.h>
+#include <dev/ath/if_ath_rx_edma.h>
 #include <dev/ath/if_ath_beacon.h>
 #include <dev/ath/if_athdfs.h>
 
@@ -302,6 +303,17 @@ ath_attach(u_int16_t devid, struct ath_s
 #endif
 
        /*
+        * Setup the DMA/EDMA functions based on the current
+        * hardware support.
+        *
+        * This is required before the descriptors are allocated.
+        */
+       if (ath_hal_hasedma(sc->sc_ah))
+               ath_recv_setup_edma(sc);
+       else
+               ath_recv_setup_legacy(sc);
+
+       /*
         * Check if the MAC has multi-rate retry support.
         * We do this by trying to setup a fake extended
         * descriptor.  MAC's that don't have support will
@@ -376,7 +388,7 @@ ath_attach(u_int16_t devid, struct ath_s
        taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
                "%s taskq", ifp->if_xname);
 
-       TASK_INIT(&sc->sc_rxtask, 0, ath_rx_tasklet, sc);
+       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);
        TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc);
@@ -2100,7 +2112,7 @@ ath_reset(struct ifnet *ifp, ATH_RESET_T
         * That way frames aren't dropped which shouldn't be.
         */
        ath_stoprecv(sc, (reset_type != ATH_RESET_NOLOSS));
-       ath_rx_proc(sc, 0);
+       ath_rx_flush(sc);
 
        ath_settkipmic(sc);             /* configure TKIP MIC handling */
        /* NB: indicate channel change so we do a full reset */
@@ -4018,7 +4030,7 @@ ath_chan_set(struct ath_softc *sc, struc
                /*
                 * First, handle completed TX/RX frames.
                 */
-               ath_rx_proc(sc, 0);
+               ath_rx_flush(sc);
                ath_draintxq(sc, ATH_RESET_NOLOSS);
                /*
                 * Next, flush the non-scheduled frames.

Modified: head/sys/dev/ath/if_ath_rx.c
==============================================================================
--- head/sys/dev/ath/if_ath_rx.c        Tue Jul  3 06:56:11 2012        
(r238054)
+++ head/sys/dev/ath/if_ath_rx.c        Tue Jul  3 06:59:12 2012        
(r238055)
@@ -214,8 +214,8 @@ ath_calcrxfilter(struct ath_softc *sc)
        return rfilt;
 }
 
-int
-ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
+static int
+ath_legacy_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
 {
        struct ath_hal *ah = sc->sc_ah;
        int error;
@@ -463,29 +463,6 @@ ath_handle_micerror(struct ieee80211com 
        }
 }
 
-/*
- * Only run the RX proc if it's not already running.
- * Since this may get run as part of the reset/flush path,
- * the task can't clash with an existing, running tasklet.
- */
-void
-ath_rx_tasklet(void *arg, int npending)
-{
-       struct ath_softc *sc = arg;
-
-       CTR1(ATH_KTR_INTR, "ath_rx_proc: pending=%d", npending);
-       DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
-       ATH_PCU_LOCK(sc);
-       if (sc->sc_inreset_cnt > 0) {
-               device_printf(sc->sc_dev,
-                   "%s: sc_inreset_cnt > 0; skipping\n", __func__);
-               ATH_PCU_UNLOCK(sc);
-               return;
-       }
-       ATH_PCU_UNLOCK(sc);
-       ath_rx_proc(sc, 1);
-}
-
 static int
 ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
     uint64_t tsf, int nf, struct ath_buf *bf)
@@ -814,7 +791,7 @@ rx_next:
        return (is_good);
 }
 
-void
+static void
 ath_rx_proc(struct ath_softc *sc, int resched)
 {
 #define        PA2DESC(_sc, _pa) \
@@ -965,10 +942,41 @@ rx_proc_next:
 }
 
 /*
+ * Only run the RX proc if it's not already running.
+ * Since this may get run as part of the reset/flush path,
+ * the task can't clash with an existing, running tasklet.
+ */
+static void
+ath_legacy_rx_tasklet(void *arg, int npending)
+{
+       struct ath_softc *sc = arg;
+
+       CTR1(ATH_KTR_INTR, "ath_rx_proc: pending=%d", npending);
+       DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
+       ATH_PCU_LOCK(sc);
+       if (sc->sc_inreset_cnt > 0) {
+               device_printf(sc->sc_dev,
+                   "%s: sc_inreset_cnt > 0; skipping\n", __func__);
+               ATH_PCU_UNLOCK(sc);
+               return;
+       }
+       ATH_PCU_UNLOCK(sc);
+
+       ath_rx_proc(sc, 1);
+}
+
+static void
+ath_legacy_flushrecv(struct ath_softc *sc)
+{
+
+       ath_rx_proc(sc, 0);
+}
+
+/*
  * Disable the receive h/w in preparation for a reset.
  */
-void
-ath_stoprecv(struct ath_softc *sc, int dodelay)
+static void
+ath_legacy_stoprecv(struct ath_softc *sc, int dodelay)
 {
 #define        PA2DESC(_sc, _pa) \
        ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
@@ -1019,8 +1027,8 @@ ath_stoprecv(struct ath_softc *sc, int d
 /*
  * Enable the receive h/w following a reset.
  */
-int
-ath_startrecv(struct ath_softc *sc)
+static int
+ath_legacy_startrecv(struct ath_softc *sc)
 {
        struct ath_hal *ah = sc->sc_ah;
        struct ath_buf *bf;
@@ -1044,3 +1052,17 @@ ath_startrecv(struct ath_softc *sc)
        ath_hal_startpcurecv(ah);       /* re-enable PCU/DMA engine */
        return 0;
 }
+
+
+void
+ath_recv_setup_legacy(struct ath_softc *sc)
+{
+
+       device_printf(sc->sc_dev, "DMA setup: legacy\n");
+
+       sc->sc_rx.recv_start = ath_legacy_startrecv;
+       sc->sc_rx.recv_stop = ath_legacy_stoprecv;
+       sc->sc_rx.recv_flush = ath_legacy_flushrecv;
+       sc->sc_rx.recv_tasklet = ath_legacy_rx_tasklet;
+       sc->sc_rx.recv_rxbuf_init = ath_legacy_rxbuf_init;
+}

Modified: head/sys/dev/ath/if_ath_rx.h
==============================================================================
--- head/sys/dev/ath/if_ath_rx.h        Tue Jul  3 06:56:11 2012        
(r238054)
+++ head/sys/dev/ath/if_ath_rx.h        Tue Jul  3 06:59:12 2012        
(r238055)
@@ -32,12 +32,26 @@
 #define        __IF_ATH_RX_H__
 
 extern u_int32_t ath_calcrxfilter(struct ath_softc *sc);
-extern int ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf);
 extern void ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
            int subtype, int rssi, int nf);
+
+#define        ath_stoprecv(_sc, _dodelay)             \
+           (_sc)->sc_rx.recv_stop((_sc), (_dodelay))
+#define        ath_startrecv(_sc)                      \
+           (_sc)->sc_rx.recv_start((_sc))
+#define        ath_rx_flush(_sc)                       \
+           (_sc)->sc_rx.recv_flush((_sc))
+#define        ath_rxbuf_init(_sc, _bf)                \
+           (_sc)->sc_rx.recv_rxbuf_init((_sc), (_bf))
+
+#if 0
+extern int ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf);
 extern void ath_rx_tasklet(void *arg, int npending);
 extern void ath_rx_proc(struct ath_softc *sc, int resched);
 extern void ath_stoprecv(struct ath_softc *sc, int dodelay);
 extern int ath_startrecv(struct ath_softc *sc);
+#endif
+
+extern void ath_recv_setup_legacy(struct ath_softc *sc);
 
 #endif

Added: head/sys/dev/ath/if_ath_rx_edma.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/ath/if_ath_rx_edma.c   Tue Jul  3 06:59:12 2012        
(r238055)
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2012 Adrian Chadd <adr...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Driver for the Atheros Wireless LAN controller.
+ *
+ * This software is derived from work of Atsushi Onoe; his contribution
+ * is greatly appreciated.
+ */
+
+#include "opt_inet.h"
+#include "opt_ath.h"
+/*
+ * This is needed for register operations which are performed
+ * by the driver - eg, calls to ath_hal_gettsf32().
+ *
+ * It's also required for any AH_DEBUG checks in here, eg the
+ * module dependencies.
+ */
+#include "opt_ah.h"
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/errno.h>
+#include <sys/callout.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kthread.h>
+#include <sys/taskqueue.h>
+#include <sys/priv.h>
+#include <sys/module.h>
+#include <sys/ktr.h>
+#include <sys/smp.h>   /* for mp_ncpus */
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_llc.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
+#ifdef IEEE80211_SUPPORT_TDMA
+#include <net80211/ieee80211_tdma.h>
+#endif
+
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <dev/ath/if_athvar.h>
+#include <dev/ath/ath_hal/ah_devid.h>          /* XXX for softled */
+#include <dev/ath/ath_hal/ah_diagcodes.h>
+
+#include <dev/ath/if_ath_debug.h>
+#include <dev/ath/if_ath_misc.h>
+#include <dev/ath/if_ath_tsf.h>
+#include <dev/ath/if_ath_tx.h>
+#include <dev/ath/if_ath_sysctl.h>
+#include <dev/ath/if_ath_led.h>
+#include <dev/ath/if_ath_keycache.h>
+#include <dev/ath/if_ath_rx.h>
+#include <dev/ath/if_ath_beacon.h>
+#include <dev/ath/if_athdfs.h>
+
+#ifdef ATH_TX99_DIAG
+#include <dev/ath/ath_tx99/ath_tx99.h>
+#endif
+
+#include <dev/ath/if_ath_rx_edma.h>
+
+static void
+ath_edma_stoprecv(struct ath_softc *sc, int dodelay)
+{
+       struct ath_hal *ah = sc->sc_ah;
+
+       ath_hal_stoppcurecv(ah);
+       ath_hal_setrxfilter(ah, 0);
+       ath_hal_stopdmarecv(ah);
+
+       DELAY(3000);
+
+       if (sc->sc_rxpending != NULL) {
+               m_freem(sc->sc_rxpending);
+               sc->sc_rxpending = NULL;
+       }
+
+       sc->sc_rxlink = NULL;
+}
+
+static int
+ath_edma_startrecv(struct ath_softc *sc)
+{
+       struct ath_hal *ah = sc->sc_ah;
+
+       sc->sc_rxlink = NULL;
+       sc->sc_rxpending = NULL;
+
+       /* XXX setup HP RX queue FIFO pointer */
+       /* XXX setup LP RX queue FIFO pointer */
+       /* XXX ath_hal_rxena() */
+       ath_mode_init(sc);
+       ath_hal_startpcurecv(ah);
+       return (0);
+}
+
+static void
+ath_edma_recv_flush(struct ath_softc *sc)
+{
+
+       device_printf(sc->sc_dev, "%s: called\n", __func__);
+}
+
+static void
+ath_edma_recv_tasklet(void *arg, int npending)
+{
+       struct ath_softc *sc = (struct ath_softc *) arg;
+
+       device_printf(sc->sc_dev, "%s: called; npending=%d\n",
+           __func__,
+           npending);
+       /* XXX TODO */
+}
+
+static int
+ath_edma_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
+{
+
+       device_printf(sc->sc_dev, "%s: called; bf=%p\n", __func__, bf);
+       return (EIO);
+}
+
+void
+ath_recv_setup_edma(struct ath_softc *sc)
+{
+
+       device_printf(sc->sc_dev, "DMA setup: EDMA\n");
+
+       sc->sc_rx.recv_stop = ath_edma_stoprecv;
+       sc->sc_rx.recv_start = ath_edma_startrecv;
+       sc->sc_rx.recv_flush = ath_edma_recv_flush;
+       sc->sc_rx.recv_tasklet = ath_edma_recv_tasklet;
+       sc->sc_rx.recv_rxbuf_init = ath_edma_rxbuf_init;
+}

Added: head/sys/dev/ath/if_ath_rx_edma.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/ath/if_ath_rx_edma.h   Tue Jul  3 06:59:12 2012        
(r238055)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2012 Adrian Chadd <adr...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#ifndef        __IF_ATH_RX_EDMA_H__
+#define        __IF_ATH_RX_EDMA_H__
+
+extern void ath_recv_setup_edma(struct ath_softc *sc);
+
+#endif

Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h        Tue Jul  3 06:56:11 2012        
(r238054)
+++ head/sys/dev/ath/if_athvar.h        Tue Jul  3 06:59:12 2012        
(r238055)
@@ -372,6 +372,15 @@ typedef enum {
        ATH_RESET_FULL = 2,
 } ATH_RESET_TYPE;
 
+struct ath_rx_methods {
+       void            (*recv_stop)(struct ath_softc *sc, int dodelay);
+       int             (*recv_start)(struct ath_softc *sc);
+       void            (*recv_flush)(struct ath_softc *sc);
+       void            (*recv_tasklet)(void *arg, int npending);
+       int             (*recv_rxbuf_init)(struct ath_softc *sc,
+                           struct ath_buf *bf);
+};
+
 struct ath_softc {
        struct ifnet            *sc_ifp;        /* interface common */
        struct ath_stats        sc_stats;       /* interface statistics */
@@ -385,6 +394,8 @@ struct ath_softc {
        u_int8_t                sc_nbssid0;     /* # vap's using base mac */
        uint32_t                sc_bssidmask;   /* bssid mask */
 
+       struct ath_rx_methods   sc_rx;
+
        void                    (*sc_node_cleanup)(struct ieee80211_node *);
        void                    (*sc_node_free)(struct ieee80211_node *);
        device_t                sc_dev;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to