if_ath_tx_edma.c revision 239204
1181053Srwatson/*-
2188313Srwatson * Copyright (c) 2012 Adrian Chadd <adrian@FreeBSD.org>
3155192Srwatson * All rights reserved.
4155192Srwatson *
5155192Srwatson * Redistribution and use in source and binary forms, with or without
6155192Srwatson * modification, are permitted provided that the following conditions
7155192Srwatson * are met:
8155192Srwatson * 1. Redistributions of source code must retain the above copyright
9155192Srwatson *    notice, this list of conditions and the following disclaimer,
10155192Srwatson *    without modification.
11155192Srwatson * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12155192Srwatson *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13180701Srwatson *    redistribution must be conditioned upon including a substantially
14155192Srwatson *    similar Disclaimer requirement for further binary redistribution.
15155192Srwatson *
16155192Srwatson * NO WARRANTY
17155192Srwatson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18155192Srwatson * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19155192Srwatson * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20155192Srwatson * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21155192Srwatson * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22155192Srwatson * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23155192Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24155192Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25155192Srwatson * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26155192Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27155192Srwatson * THE POSSIBILITY OF SUCH DAMAGES.
28155192Srwatson */
29155192Srwatson
30155192Srwatson#include <sys/cdefs.h>
31155192Srwatson__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx_edma.c 239204 2012-08-12 00:37:29Z adrian $");
32155192Srwatson
33155192Srwatson/*
34155192Srwatson * Driver for the Atheros Wireless LAN controller.
35155192Srwatson *
36155192Srwatson * This software is derived from work of Atsushi Onoe; his contribution
37156882Srwatson * is greatly appreciated.
38156882Srwatson */
39155192Srwatson
40155192Srwatson#include "opt_inet.h"
41155192Srwatson#include "opt_ath.h"
42155192Srwatson/*
43155192Srwatson * This is needed for register operations which are performed
44155192Srwatson * by the driver - eg, calls to ath_hal_gettsf32().
45155192Srwatson *
46155192Srwatson * It's also required for any AH_DEBUG checks in here, eg the
47155192Srwatson * module dependencies.
48155192Srwatson */
49155192Srwatson#include "opt_ah.h"
50155192Srwatson#include "opt_wlan.h"
51155192Srwatson
52155192Srwatson#include <sys/param.h>
53195177Ssson#include <sys/systm.h>
54155192Srwatson#include <sys/sysctl.h>
55155192Srwatson#include <sys/mbuf.h>
56155192Srwatson#include <sys/malloc.h>
57156889Srwatson#include <sys/lock.h>
58156889Srwatson#include <sys/mutex.h>
59155192Srwatson#include <sys/kernel.h>
60155192Srwatson#include <sys/socket.h>
61155192Srwatson#include <sys/sockio.h>
62155192Srwatson#include <sys/errno.h>
63155192Srwatson#include <sys/callout.h>
64155192Srwatson#include <sys/bus.h>
65161813Swsalamon#include <sys/endian.h>
66161813Swsalamon#include <sys/kthread.h>
67155192Srwatson#include <sys/taskqueue.h>
68155192Srwatson#include <sys/priv.h>
69155192Srwatson#include <sys/module.h>
70155192Srwatson#include <sys/ktr.h>
71155192Srwatson#include <sys/smp.h>	/* for mp_ncpus */
72156889Srwatson
73156889Srwatson#include <machine/bus.h>
74156889Srwatson
75155192Srwatson#include <net/if.h>
76155192Srwatson#include <net/if_dl.h>
77159269Srwatson#include <net/if_media.h>
78159269Srwatson#include <net/if_types.h>
79159269Srwatson#include <net/if_arp.h>
80155192Srwatson#include <net/ethernet.h>
81155192Srwatson#include <net/if_llc.h>
82155192Srwatson
83155192Srwatson#include <net80211/ieee80211_var.h>
84159269Srwatson#include <net80211/ieee80211_regdomain.h>
85159269Srwatson#ifdef IEEE80211_SUPPORT_SUPERG
86159269Srwatson#include <net80211/ieee80211_superg.h>
87162380Scsjp#endif
88162380Scsjp#ifdef IEEE80211_SUPPORT_TDMA
89162380Scsjp#include <net80211/ieee80211_tdma.h>
90155192Srwatson#endif
91155192Srwatson
92155192Srwatson#include <net/bpf.h>
93155192Srwatson
94155192Srwatson#ifdef INET
95155192Srwatson#include <netinet/in.h>
96155192Srwatson#include <netinet/if_ether.h>
97155192Srwatson#endif
98156889Srwatson
99156889Srwatson#include <dev/ath/if_athvar.h>
100156889Srwatson#include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
101156889Srwatson#include <dev/ath/ath_hal/ah_diagcodes.h>
102156889Srwatson
103156889Srwatson#include <dev/ath/if_ath_debug.h>
104156889Srwatson#include <dev/ath/if_ath_misc.h>
105155192Srwatson#include <dev/ath/if_ath_tsf.h>
106155192Srwatson#include <dev/ath/if_ath_tx.h>
107155192Srwatson#include <dev/ath/if_ath_sysctl.h>
108195177Ssson#include <dev/ath/if_ath_led.h>
109195177Ssson#include <dev/ath/if_ath_keycache.h>
110155192Srwatson#include <dev/ath/if_ath_rx.h>
111155192Srwatson#include <dev/ath/if_ath_beacon.h>
112155192Srwatson#include <dev/ath/if_athdfs.h>
113180709Srwatson
114155192Srwatson#ifdef ATH_TX99_DIAG
115155192Srwatson#include <dev/ath/ath_tx99/ath_tx99.h>
116156889Srwatson#endif
117156889Srwatson
118156889Srwatson#include <dev/ath/if_ath_tx_edma.h>
119156889Srwatson
120155192Srwatson/*
121155192Srwatson * some general macros
122191270Srwatson */
123191270Srwatson#define	INCR(_l, _sz)		(_l) ++; (_l) &= ((_sz) - 1)
124191270Srwatson#define	DECR(_l, _sz)		(_l) --; (_l) &= ((_sz) - 1)
125191270Srwatson
126191270Srwatson/*
127191270Srwatson * XXX doesn't belong here, and should be tunable
128191270Srwatson */
129191270Srwatson#define	ATH_TXSTATUS_RING_SIZE	512
130191270Srwatson
131191270SrwatsonMALLOC_DECLARE(M_ATHDEV);
132191270Srwatson
133191270Srwatson/*
134191270Srwatson * Re-initialise the DMA FIFO with the current contents of
135155192Srwatson * said TXQ.
136155192Srwatson *
137191270Srwatson * This should only be called as part of the chip reset path, as it
138191270Srwatson * assumes the FIFO is currently empty.
139191270Srwatson *
140155192Srwatson * TODO: verify that a cold/warm reset does clear the TX FIFO, so
141191270Srwatson * writing in a partially-filled FIFO will not cause double-entries
142191270Srwatson * to appear.
143155192Srwatson */
144155192Srwatsonstatic void
145155192Srwatsonath_edma_dma_restart(struct ath_softc *sc, struct ath_txq *txq)
146155192Srwatson{
147155192Srwatson
148155192Srwatson	device_printf(sc->sc_dev, "%s: called: txq=%p, qnum=%d\n",
149191270Srwatson	    __func__,
150155192Srwatson	    txq,
151155192Srwatson	    txq->axq_qnum);
152184856Scsjp}
153155192Srwatson
154155192Srwatson/*
155155192Srwatson * Hand off this frame to a hardware queue.
156156889Srwatson *
157156889Srwatson * Things are a bit hairy in the EDMA world.  The TX FIFO is only
158156889Srwatson * 8 entries deep, so we need to keep track of exactly what we've
159155192Srwatson * pushed into the FIFO and what's just sitting in the TX queue,
160155192Srwatson * waiting to go out.
161155192Srwatson *
162155192Srwatson * So this is split into two halves - frames get appended to the
163155192Srwatson * TXQ; then a scheduler is called to push some frames into the
164155192Srwatson * actual TX FIFO.
165155192Srwatson */
166155192Srwatsonstatic void
167155192Srwatsonath_edma_xmit_handoff_hw(struct ath_softc *sc, struct ath_txq *txq,
168155192Srwatson    struct ath_buf *bf)
169155192Srwatson{
170155192Srwatson	struct ath_hal *ah = sc->sc_ah;
171155192Srwatson
172156889Srwatson	ATH_TXQ_LOCK_ASSERT(txq);
173156889Srwatson
174156889Srwatson	KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0,
175156889Srwatson	    ("%s: busy status 0x%x", __func__, bf->bf_flags));
176156889Srwatson
177156889Srwatson	/*
178156889Srwatson	 * XXX TODO: write a hard-coded check to ensure that
179156889Srwatson	 * the queue id in the TX descriptor matches txq->axq_qnum.
180168688Scsjp	 */
181156889Srwatson
182155192Srwatson	/* Update aggr stats */
183155192Srwatson	if (bf->bf_state.bfs_aggr)
184156889Srwatson		txq->axq_aggr_depth++;
185156889Srwatson
186156889Srwatson	/* Push and update frame stats */
187156889Srwatson	ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
188156889Srwatson
189156889Srwatson	/* Only schedule to the FIFO if there's space */
190156889Srwatson	if (txq->axq_fifo_depth < HAL_TXFIFO_DEPTH) {
191156889Srwatson		ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
192156889Srwatson		ath_hal_txstart(ah, txq->axq_qnum);
193168688Scsjp	}
194156889Srwatson}
195156889Srwatson
196156889Srwatson/*
197156889Srwatson * Hand off this frame to a multicast software queue.
198156889Srwatson *
199195925Srwatson * Unlike legacy DMA, this doesn't chain together frames via the
200195925Srwatson * link pointer.  Instead, they're just added to the queue.
201156889Srwatson * When it comes time to populate the CABQ, these frames should
202156889Srwatson * be individually pushed into the FIFO as appropriate.
203156889Srwatson *
204156889Srwatson * Yes, this does mean that I'll eventually have to flesh out some
205246691Spjd * replacement code to handle populating the CABQ, rather than
206156889Srwatson * what's done in ath_beacon_generate().  It'll have to push each
207156889Srwatson * frame from the HW CABQ to the FIFO rather than just appending
208156889Srwatson * it to the existing TXQ and kicking off DMA.
209156889Srwatson */
210156889Srwatsonstatic void
211156889Srwatsonath_edma_xmit_handoff_mcast(struct ath_softc *sc, struct ath_txq *txq,
212156889Srwatson    struct ath_buf *bf)
213156889Srwatson{
214156889Srwatson
215156889Srwatson	ATH_TXQ_LOCK_ASSERT(txq);
216156889Srwatson	KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0,
217156889Srwatson	    ("%s: busy status 0x%x", __func__, bf->bf_flags));
218156889Srwatson
219156889Srwatson	/*
220156889Srwatson	 * XXX this is mostly duplicated in ath_tx_handoff_mcast().
221156889Srwatson	 */
222246691Spjd	if (ATH_TXQ_FIRST(txq) != NULL) {
223156889Srwatson		struct ath_buf *bf_last = ATH_TXQ_LAST(txq, axq_q_s);
224156889Srwatson		struct ieee80211_frame *wh;
225161813Swsalamon
226161813Swsalamon		/* mark previous frame */
227161813Swsalamon		wh = mtod(bf_last->bf_m, struct ieee80211_frame *);
228161813Swsalamon		wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
229156889Srwatson
230156889Srwatson		/* sync descriptor to memory */
231164011Scsjp		bus_dmamap_sync(sc->sc_dmat, bf_last->bf_dmamap,
232224181Sjonathan		   BUS_DMASYNC_PREWRITE);
233245573Scsjp	}
234155192Srwatson
235155192Srwatson	ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
236155192Srwatson}
237155192Srwatson
238155192Srwatson/*
239155192Srwatson * Handoff this frame to the hardware.
240155192Srwatson *
241195939Srwatson * For the multicast queue, this will treat it as a software queue
242195939Srwatson * and append it to the list, after updating the MORE_DATA flag
243195939Srwatson * in the previous frame.  The cabq processing code will ensure
244195939Srwatson * that the queue contents gets transferred over.
245195939Srwatson *
246195939Srwatson * For the hardware queues, this will queue a frame to the queue
247195939Srwatson * like before, then populate the FIFO from that.  Since the
248195939Srwatson * EDMA hardware has 8 FIFO slots per TXQ, this ensures that
249195939Srwatson * frames such as management frames don't get prematurely dropped.
250195939Srwatson *
251195939Srwatson * This does imply that a similar flush-hwq-to-fifoq method will
252195939Srwatson * need to be called from the processq function, before the
253195939Srwatson * per-node software scheduler is called.
254195939Srwatson */
255195939Srwatsonstatic void
256195939Srwatsonath_edma_xmit_handoff(struct ath_softc *sc, struct ath_txq *txq,
257195939Srwatson    struct ath_buf *bf)
258195939Srwatson{
259195939Srwatson
260195939Srwatson	ATH_TXQ_LOCK_ASSERT(txq);
261195939Srwatson
262195939Srwatson	device_printf(sc->sc_dev, "%s: called; bf=%p, txq=%p, qnum=%d\n",
263195939Srwatson	    __func__,
264195939Srwatson	    bf,
265195939Srwatson	    txq,
266195939Srwatson	    txq->axq_qnum);
267195939Srwatson
268195939Srwatson	if (txq->axq_qnum == ATH_TXQ_SWQ)
269195939Srwatson		ath_edma_xmit_handoff_mcast(sc, txq, bf);
270195939Srwatson	else
271195939Srwatson		ath_edma_xmit_handoff_hw(sc, txq, bf);
272195939Srwatson
273195939Srwatson#if 0
274195939Srwatson	/*
275195939Srwatson	 * XXX For now this is a placeholder; free the buffer
276195939Srwatson	 * and inform the stack that the TX failed.
277195939Srwatson	 */
278195939Srwatson	ath_tx_default_comp(sc, bf, 1);
279195939Srwatson#endif
280195939Srwatson}
281195939Srwatson
282195939Srwatsonstatic int
283195939Srwatsonath_edma_setup_txfifo(struct ath_softc *sc, int qnum)
284195939Srwatson{
285195939Srwatson	struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum];
286195939Srwatson
287195939Srwatson	te->m_fifo = malloc(sizeof(struct ath_buf *) * HAL_TXFIFO_DEPTH,
288195939Srwatson	    M_ATHDEV,
289195939Srwatson	    M_NOWAIT | M_ZERO);
290195939Srwatson	if (te->m_fifo == NULL) {
291195939Srwatson		device_printf(sc->sc_dev, "%s: malloc failed\n",
292195939Srwatson		    __func__);
293224181Sjonathan		return (-ENOMEM);
294195939Srwatson	}
295195939Srwatson
296195939Srwatson	/*
297155192Srwatson	 * Set initial "empty" state.
298155192Srwatson	 */
299155192Srwatson	te->m_fifo_head = te->m_fifo_tail = te->m_fifo_depth = 0;
300155192Srwatson
301195926Srwatson	return (0);
302195926Srwatson}
303195926Srwatson
304155192Srwatsonstatic int
305155192Srwatsonath_edma_free_txfifo(struct ath_softc *sc, int qnum)
306155192Srwatson{
307156889Srwatson	struct ath_tx_edma_fifo *te = &sc->sc_txedma[qnum];
308156889Srwatson
309155192Srwatson	/* XXX TODO: actually deref the ath_buf entries? */
310155192Srwatson	free(te->m_fifo, M_ATHDEV);
311156889Srwatson	return (0);
312156889Srwatson}
313156889Srwatson
314156889Srwatsonstatic int
315156889Srwatsonath_edma_dma_txsetup(struct ath_softc *sc)
316156889Srwatson{
317155192Srwatson	int error;
318156888Srwatson	int i;
319155192Srwatson
320155192Srwatson	error = ath_descdma_alloc_desc(sc, &sc->sc_txsdma,
321155192Srwatson	    NULL, "txcomp", sc->sc_tx_statuslen, ATH_TXSTATUS_RING_SIZE);
322155192Srwatson	if (error != 0)
323155192Srwatson		return (error);
324155192Srwatson
325156888Srwatson	ath_hal_setuptxstatusring(sc->sc_ah,
326155192Srwatson	    (void *) sc->sc_txsdma.dd_desc,
327155192Srwatson	    sc->sc_txsdma.dd_desc_paddr,
328155192Srwatson	    ATH_TXSTATUS_RING_SIZE);
329155192Srwatson
330155192Srwatson	for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
331155192Srwatson		ath_edma_setup_txfifo(sc, i);
332155192Srwatson	}
333156291Srwatson
334156889Srwatson
335156889Srwatson	return (0);
336155192Srwatson}
337155192Srwatson
338155192Srwatsonstatic int
339155192Srwatsonath_edma_dma_txteardown(struct ath_softc *sc)
340156889Srwatson{
341156889Srwatson	int i;
342155192Srwatson
343155192Srwatson	for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
344155192Srwatson		ath_edma_free_txfifo(sc, i);
345155192Srwatson	}
346156889Srwatson
347156889Srwatson	ath_descdma_cleanup(sc, &sc->sc_txsdma, NULL);
348156889Srwatson	return (0);
349155192Srwatson}
350156888Srwatson
351156888Srwatson/*
352156888Srwatson * Drain all TXQs, potentially after completing the existing completed
353156888Srwatson * frames.
354156889Srwatson */
355159261Srwatsonstatic void
356159261Srwatsonath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
357156889Srwatson{
358191270Srwatson
359191270Srwatson	device_printf(sc->sc_dev, "%s: called\n", __func__);
360156889Srwatson}
361156888Srwatson
362156888Srwatson/*
363155192Srwatson * Completely drain the TXQ, completing frames that were completed.
364155192Srwatson *
365155192Srwatson * This is only called to _explictly_ drain the frames from a queue
366155192Srwatson * without caring if they were completed or not.
367155192Srwatson */
368155192Srwatsonstatic void
369155192Srwatsonath_edma_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
370155192Srwatson{
371155192Srwatson
372155192Srwatson	device_printf(sc->sc_dev, "%s: called\n", __func__);
373155192Srwatson}
374156889Srwatson
375170196Srwatson/*
376155192Srwatson * Process the TX status queue.
377155192Srwatson */
378155192Srwatsonstatic void
379155192Srwatsonath_edma_tx_proc(void *arg, int npending)
380155192Srwatson{
381155192Srwatson	struct ath_softc *sc = (struct ath_softc *) arg;
382159269Srwatson	struct ath_hal *ah = sc->sc_ah;
383159269Srwatson	HAL_STATUS status;
384155192Srwatson	struct ath_tx_status ts;
385155192Srwatson	struct ath_txq *txq;
386155192Srwatson
387176690Srwatson	device_printf(sc->sc_dev, "%s: called, npending=%d\n",
388176690Srwatson	    __func__, npending);
389195925Srwatson
390188313Srwatson	for (;;) {
391188313Srwatson		ATH_TXSTATUS_LOCK(sc);
392243726Spjd		status = ath_hal_txprocdesc(ah, NULL, (void *) &ts);
393243726Spjd		ATH_TXSTATUS_UNLOCK(sc);
394188313Srwatson
395155192Srwatson		if (status != HAL_OK)
396155192Srwatson			break;
397155192Srwatson
398155192Srwatson		/*
399155192Srwatson		 * At this point we have a valid status descriptor.
400155192Srwatson		 * The QID and descriptor ID (which currently isn't set)
401176686Srwatson		 * is part of the status.
402155192Srwatson		 *
403155192Srwatson		 * We then assume that the descriptor in question is the
404184858Srwatson		 * -head- of the given QID.  Eventually we should verify
405184858Srwatson		 * this by using the descriptor ID.
406184858Srwatson		 */
407184858Srwatson		device_printf(sc->sc_dev, "%s: qcuid=%d\n",
408184858Srwatson		    __func__,
409184858Srwatson		    ts.ts_queue_id);
410155192Srwatson
411155192Srwatson		txq = &sc->sc_txq[ts.ts_queue_id];
412155192Srwatson	}
413156888Srwatson}
414155192Srwatson
415155192Srwatsonstatic void
416155192Srwatsonath_edma_attach_comp_func(struct ath_softc *sc)
417156888Srwatson{
418155192Srwatson
419155408Srwatson	TASK_INIT(&sc->sc_txtask, 0, ath_edma_tx_proc, sc);
420155408Srwatson}
421155408Srwatson
422159269Srwatsonvoid
423159269Srwatsonath_xmit_setup_edma(struct ath_softc *sc)
424159269Srwatson{
425159269Srwatson
426159269Srwatson	/* Fetch EDMA field and buffer sizes */
427155408Srwatson	(void) ath_hal_gettxdesclen(sc->sc_ah, &sc->sc_tx_desclen);
428156882Srwatson	(void) ath_hal_gettxstatuslen(sc->sc_ah, &sc->sc_tx_statuslen);
429	(void) ath_hal_getntxmaps(sc->sc_ah, &sc->sc_tx_nmaps);
430
431	device_printf(sc->sc_dev, "TX descriptor length: %d\n",
432	    sc->sc_tx_desclen);
433	device_printf(sc->sc_dev, "TX status length: %d\n",
434	    sc->sc_tx_statuslen);
435	device_printf(sc->sc_dev, "TX buffers per descriptor: %d\n",
436	    sc->sc_tx_nmaps);
437
438	sc->sc_tx.xmit_setup = ath_edma_dma_txsetup;
439	sc->sc_tx.xmit_teardown = ath_edma_dma_txteardown;
440	sc->sc_tx.xmit_attach_comp_func = ath_edma_attach_comp_func;
441
442	sc->sc_tx.xmit_dma_restart = ath_edma_dma_restart;
443	sc->sc_tx.xmit_handoff = ath_edma_xmit_handoff;
444	sc->sc_tx.xmit_drainq = ath_edma_tx_draintxq;
445	sc->sc_tx.xmit_drain = ath_edma_tx_drain;
446}
447