Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jul 2012 06:59:13 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238055 - head/sys/dev/ath
Message-ID:  <201207030659.q636xDL5027184@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <adrian@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 <adrian@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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207030659.q636xDL5027184>