[Midnightbsd-cvs] src: dev/ath: merge

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Tue Nov 25 11:43:08 EST 2008


Log Message:
-----------
merge

Modified Files:
--------------
    src/sys/dev/ath/ath_rate/amrr:
        amrr.c (r1.1.1.2 -> r1.2)
    src/sys/dev/ath/ath_rate/onoe:
        onoe.c (r1.1.1.2 -> r1.2)
        onoe.h (r1.1.1.1 -> r1.2)
    src/sys/dev/ath/ath_rate/sample:
        sample.c (r1.2 -> r1.3)
        sample.h (r1.1.1.2 -> r1.2)

Added Files:
-----------
    src/sys/dev/ath:
        ah_osdep.c (r1.1)
        ah_osdep.h (r1.1)

-------------- next part --------------
--- /dev/null
+++ sys/dev/ath/ah_osdep.c
@@ -0,0 +1,434 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * 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: src/sys/dev/ath/ah_osdep.c,v 1.3 2007/06/06 15:49:15 sam Exp $
+ */
+#include "opt_ah.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+
+#include <machine/stdarg.h>
+
+#include <net/ethernet.h>		/* XXX for ether_sprintf */
+
+#include <contrib/dev/ath/ah.h>
+
+/*
+ * WiSoC boards overload the bus tag with information about the
+ * board layout.  We must extract the bus space tag from that
+ * indirect structure.  For everyone else the tag is passed in
+ * directly.
+ * XXX cache indirect ref privately
+ */
+#ifdef AH_SUPPORT_AR5312
+#define	BUSTAG(ah) \
+	((bus_space_tag_t) ((struct ar531x_config *)((ah)->ah_st))->tag)
+#else
+#define	BUSTAG(ah)	((bus_space_tag_t) (ah)->ah_st)
+#endif
+
+extern	void ath_hal_printf(struct ath_hal *, const char*, ...)
+		__printflike(2,3);
+extern	void ath_hal_vprintf(struct ath_hal *, const char*, __va_list)
+		__printflike(2, 0);
+extern	const char* ath_hal_ether_sprintf(const u_int8_t *mac);
+extern	void *ath_hal_malloc(size_t);
+extern	void ath_hal_free(void *);
+#ifdef AH_ASSERT
+extern	void ath_hal_assert_failed(const char* filename,
+		int lineno, const char* msg);
+#endif
+#ifdef AH_DEBUG
+extern	void HALDEBUG(struct ath_hal *ah, const char* fmt, ...);
+extern	void HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...);
+#endif /* AH_DEBUG */
+
+/* NB: put this here instead of the driver to avoid circular references */
+SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters");
+SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters");
+
+#ifdef AH_DEBUG
+static	int ath_hal_debug = 0;
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug,
+	    0, "Atheros HAL debugging printfs");
+TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug);
+#endif /* AH_DEBUG */
+
+SYSCTL_STRING(_hw_ath_hal, OID_AUTO, version, CTLFLAG_RD, ath_hal_version, 0,
+	"Atheros HAL version");
+
+/* NB: these are deprecated; they exist for now for compatibility */
+int	ath_hal_dma_beacon_response_time = 2;	/* in TU's */
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, dma_brt, CTLFLAG_RW,
+	   &ath_hal_dma_beacon_response_time, 0,
+	   "Atheros HAL DMA beacon response time");
+int	ath_hal_sw_beacon_response_time = 10;	/* in TU's */
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, sw_brt, CTLFLAG_RW,
+	   &ath_hal_sw_beacon_response_time, 0,
+	   "Atheros HAL software beacon response time");
+int	ath_hal_additional_swba_backoff = 0;	/* in TU's */
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, swba_backoff, CTLFLAG_RW,
+	   &ath_hal_additional_swba_backoff, 0,
+	   "Atheros HAL additional SWBA backoff time");
+
+MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data");
+
+void*
+ath_hal_malloc(size_t size)
+{
+	return malloc(size, M_ATH_HAL, M_NOWAIT | M_ZERO);
+}
+
+void
+ath_hal_free(void* p)
+{
+	return free(p, M_ATH_HAL);
+}
+
+void
+ath_hal_vprintf(struct ath_hal *ah, const char* fmt, va_list ap)
+{
+	vprintf(fmt, ap);
+}
+
+void
+ath_hal_printf(struct ath_hal *ah, const char* fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	ath_hal_vprintf(ah, fmt, ap);
+	va_end(ap);
+}
+
+const char*
+ath_hal_ether_sprintf(const u_int8_t *mac)
+{
+	return ether_sprintf(mac);
+}
+
+#ifdef AH_DEBUG
+void
+HALDEBUG(struct ath_hal *ah, const char* fmt, ...)
+{
+	if (ath_hal_debug) {
+		__va_list ap;
+		va_start(ap, fmt);
+		ath_hal_vprintf(ah, fmt, ap);
+		va_end(ap);
+	}
+}
+
+void
+HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...)
+{
+	if (ath_hal_debug >= level) {
+		__va_list ap;
+		va_start(ap, fmt);
+		ath_hal_vprintf(ah, fmt, ap);
+		va_end(ap);
+	}
+}
+#endif /* AH_DEBUG */
+
+#ifdef AH_DEBUG_ALQ
+/*
+ * ALQ register tracing support.
+ *
+ * Setting hw.ath.hal.alq=1 enables tracing of all register reads and
+ * writes to the file /tmp/ath_hal.log.  The file format is a simple
+ * fixed-size array of records.  When done logging set hw.ath.hal.alq=0
+ * and then decode the file with the arcode program (that is part of the
+ * HAL).  If you start+stop tracing the data will be appended to an
+ * existing file.
+ *
+ * NB: doesn't handle multiple devices properly; only one DEVICE record
+ *     is emitted and the different devices are not identified.
+ */
+#include <sys/alq.h>
+#include <sys/pcpu.h>
+#include <contrib/dev/ath/ah_decode.h>
+
+static	struct alq *ath_hal_alq;
+static	int ath_hal_alq_emitdev;	/* need to emit DEVICE record */
+static	u_int ath_hal_alq_lost;		/* count of lost records */
+static	const char *ath_hal_logfile = "/tmp/ath_hal.log";
+static	u_int ath_hal_alq_qsize = 64*1024;
+
+static int
+ath_hal_setlogging(int enable)
+{
+	int error;
+
+	if (enable) {
+		error = alq_open(&ath_hal_alq, ath_hal_logfile,
+			curthread->td_ucred, ALQ_DEFAULT_CMODE,
+			sizeof (struct athregrec), ath_hal_alq_qsize);
+		ath_hal_alq_lost = 0;
+		ath_hal_alq_emitdev = 1;
+		printf("ath_hal: logging to %s enabled\n",
+			ath_hal_logfile);
+	} else {
+		if (ath_hal_alq)
+			alq_close(ath_hal_alq);
+		ath_hal_alq = NULL;
+		printf("ath_hal: logging disabled\n");
+		error = 0;
+	}
+	return (error);
+}
+
+static int
+sysctl_hw_ath_hal_log(SYSCTL_HANDLER_ARGS)
+{
+	int error, enable;
+
+	enable = (ath_hal_alq != NULL);
+        error = sysctl_handle_int(oidp, &enable, 0, req);
+        if (error || !req->newptr)
+                return (error);
+	else
+		return (ath_hal_setlogging(enable));
+}
+SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq, CTLTYPE_INT|CTLFLAG_RW,
+	0, 0, sysctl_hw_ath_hal_log, "I", "Enable HAL register logging");
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_size, CTLFLAG_RW,
+	&ath_hal_alq_qsize, 0, "In-memory log size (#records)");
+SYSCTL_INT(_hw_ath_hal, OID_AUTO, alq_lost, CTLFLAG_RW,
+	&ath_hal_alq_lost, 0, "Register operations not logged");
+
+static struct ale *
+ath_hal_alq_get(struct ath_hal *ah)
+{
+	struct ale *ale;
+
+	if (ath_hal_alq_emitdev) {
+		ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
+		if (ale) {
+			struct athregrec *r =
+				(struct athregrec *) ale->ae_data;
+			r->op = OP_DEVICE;
+			r->reg = 0;
+			r->val = ah->ah_devid;
+			alq_post(ath_hal_alq, ale);
+			ath_hal_alq_emitdev = 0;
+		} else
+			ath_hal_alq_lost++;
+	}
+	ale = alq_get(ath_hal_alq, ALQ_NOWAIT);
+	if (!ale)
+		ath_hal_alq_lost++;
+	return ale;
+}
+
+void
+ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
+{
+	bus_space_tag_t tag = BUSTAG(ah);
+	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
+
+	if (ath_hal_alq) {
+		struct ale *ale = ath_hal_alq_get(ah);
+		if (ale) {
+			struct athregrec *r = (struct athregrec *) ale->ae_data;
+			r->op = OP_WRITE;
+			r->reg = reg;
+			r->val = val;
+			alq_post(ath_hal_alq, ale);
+		}
+	}
+#if _BYTE_ORDER == _BIG_ENDIAN
+	if (reg >= 0x4000 && reg < 0x5000)
+		bus_space_write_4(tag, h, reg, val);
+	else
+#endif
+		bus_space_write_stream_4(tag, h, reg, val);
+}
+
+u_int32_t
+ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
+{
+	bus_space_tag_t tag = BUSTAG(ah);
+	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
+	u_int32_t val;
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+	if (reg >= 0x4000 && reg < 0x5000)
+		val = bus_space_read_4(tag, h, reg);
+	else
+#endif
+		val = bus_space_read_stream_4(tag, h, reg);
+	if (ath_hal_alq) {
+		struct ale *ale = ath_hal_alq_get(ah);
+		if (ale) {
+			struct athregrec *r = (struct athregrec *) ale->ae_data;
+			r->op = OP_READ;
+			r->reg = reg;
+			r->val = val;
+			alq_post(ath_hal_alq, ale);
+		}
+	}
+	return val;
+}
+
+void
+OS_MARK(struct ath_hal *ah, u_int id, u_int32_t v)
+{
+	if (ath_hal_alq) {
+		struct ale *ale = ath_hal_alq_get(ah);
+		if (ale) {
+			struct athregrec *r = (struct athregrec *) ale->ae_data;
+			r->op = OP_MARK;
+			r->reg = id;
+			r->val = v;
+			alq_post(ath_hal_alq, ale);
+		}
+	}
+}
+#elif defined(AH_DEBUG) || defined(AH_REGOPS_FUNC)
+/*
+ * Memory-mapped device register read/write.  These are here
+ * as routines when debugging support is enabled and/or when
+ * explicitly configured to use function calls.  The latter is
+ * for architectures that might need to do something before
+ * referencing memory (e.g. remap an i/o window).
+ *
+ * NB: see the comments in ah_osdep.h about byte-swapping register
+ *     reads and writes to understand what's going on below.
+ */
+
+void
+ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
+{
+	bus_space_tag_t tag = BUSTAG(ah);
+	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+	if (reg >= 0x4000 && reg < 0x5000)
+		bus_space_write_4(tag, h, reg, val);
+	else
+#endif
+		bus_space_write_stream_4(tag, h, reg, val);
+}
+
+u_int32_t
+ath_hal_reg_read(struct ath_hal *ah, u_int32_t reg)
+{
+	bus_space_tag_t tag = BUSTAG(ah);
+	bus_space_handle_t h = (bus_space_handle_t) ah->ah_sh;
+	u_int32_t val;
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+	if (reg >= 0x4000 && reg < 0x5000)
+		val = bus_space_read_4(tag, h, reg);
+	else
+#endif
+		val = bus_space_read_stream_4(tag, h, reg);
+	return val;
+}
+#endif /* AH_DEBUG || AH_REGOPS_FUNC */
+
+#ifdef AH_ASSERT
+void
+ath_hal_assert_failed(const char* filename, int lineno, const char *msg)
+{
+	printf("Atheros HAL assertion failure: %s: line %u: %s\n",
+		filename, lineno, msg);
+	panic("ath_hal_assert");
+}
+#endif /* AH_ASSERT */
+
+/*
+ * Delay n microseconds.
+ */
+void
+ath_hal_delay(int n)
+{
+	DELAY(n);
+}
+
+u_int32_t
+ath_hal_getuptime(struct ath_hal *ah)
+{
+	struct bintime bt;
+	getbinuptime(&bt);
+	return (bt.sec * 1000) +
+		(((uint64_t)1000 * (uint32_t)(bt.frac >> 32)) >> 32);
+}
+
+void
+ath_hal_memzero(void *dst, size_t n)
+{
+	bzero(dst, n);
+}
+
+void *
+ath_hal_memcpy(void *dst, const void *src, size_t n)
+{
+	return memcpy(dst, src, n);
+}
+
+/*
+ * Module glue.
+ */
+
+static int
+ath_hal_modevent(module_t mod, int type, void *unused)
+{
+	const char *sep;
+	int i;
+
+	switch (type) {
+	case MOD_LOAD:
+		printf("ath_hal: %s (", ath_hal_version);
+		sep = "";
+		for (i = 0; ath_hal_buildopts[i] != NULL; i++) {
+			printf("%s%s", sep, ath_hal_buildopts[i]);
+			sep = ", ";
+		}
+		printf(")\n");
+		return 0;
+	case MOD_UNLOAD:
+		return 0;
+	}
+	return EINVAL;
+}
+
+static moduledata_t ath_hal_mod = {
+	"ath_hal",
+	ath_hal_modevent,
+	0
+};
+DECLARE_MODULE(ath_hal, ath_hal_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
+MODULE_VERSION(ath_hal, 1);
--- /dev/null
+++ sys/dev/ath/ah_osdep.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * 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: src/sys/dev/ath/ah_osdep.h,v 1.2 2007/06/06 15:49:15 sam Exp $
+ */
+#ifndef _ATH_AH_OSDEP_H_
+#define _ATH_AH_OSDEP_H_
+/*
+ * Atheros Hardware Access Layer (HAL) OS Dependent Definitions.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+
+/*
+ * Delay n microseconds.
+ */
+extern	void ath_hal_delay(int);
+#define	OS_DELAY(_n)	ath_hal_delay(_n)
+
+#define	OS_INLINE	__inline
+#define	OS_MEMZERO(_a, _n)	ath_hal_memzero((_a), (_n))
+extern void ath_hal_memzero(void *, size_t);
+#define	OS_MEMCPY(_d, _s, _n)	ath_hal_memcpy(_d,_s,_n)
+extern void *ath_hal_memcpy(void *, const void *, size_t);
+
+#define	abs(_a)		__builtin_abs(_a)
+
+struct ath_hal;
+extern	u_int32_t ath_hal_getuptime(struct ath_hal *);
+#define	OS_GETUPTIME(_ah)	ath_hal_getuptime(_ah)
+
+/*
+ * Register read/write operations are either handled through
+ * platform-dependent routines (or when debugging is enabled
+ * with AH_DEBUG); or they are inline expanded using the macros
+ * defined below.  For public builds we inline expand only for
+ * platforms where it is certain what the requirements are to
+ * read/write registers--typically they are memory-mapped and
+ * no explicit synchronization or memory invalidation operations
+ * are required (e.g. i386).
+ */
+#if defined(AH_DEBUG) || defined(AH_REGOPS_FUNC) || defined(AH_DEBUG_ALQ)
+#define	OS_REG_WRITE(_ah, _reg, _val)	ath_hal_reg_write(_ah, _reg, _val)
+#define	OS_REG_READ(_ah, _reg)		ath_hal_reg_read(_ah, _reg)
+
+extern	void ath_hal_reg_write(struct ath_hal *ah, u_int reg, u_int32_t val);
+extern	u_int32_t ath_hal_reg_read(struct ath_hal *ah, u_int reg);
+#else
+/*
+ * The hardware registers are native little-endian byte order.
+ * Big-endian hosts are handled by enabling hardware byte-swap
+ * of register reads and writes at reset.  But the PCI clock
+ * domain registers are not byte swapped!  Thus, on big-endian
+ * platforms we have to explicitly byte-swap those registers.
+ * Most of this code is collapsed at compile time because the
+ * register values are constants.
+ */
+#define	AH_LITTLE_ENDIAN	1234
+#define	AH_BIG_ENDIAN		4321
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define OS_REG_WRITE(_ah, _reg, _val) do {				\
+	if ( (_reg) >= 0x4000 && (_reg) < 0x5000)			\
+		bus_space_write_4((bus_space_tag_t)(_ah)->ah_st,	\
+		    (bus_space_handle_t)(_ah)->ah_sh, (_reg), (_val));	\
+	else								\
+		bus_space_write_stream_4((bus_space_tag_t)(_ah)->ah_st,	\
+		    (bus_space_handle_t)(_ah)->ah_sh, (_reg), (_val));	\
+} while (0)
+#define OS_REG_READ(_ah, _reg)						\
+	(((_reg) >= 0x4000 && (_reg) < 0x5000) ?			\
+		bus_space_read_4((bus_space_tag_t)(_ah)->ah_st,		\
+		    (bus_space_handle_t)(_ah)->ah_sh, (_reg)) :		\
+		bus_space_read_stream_4((bus_space_tag_t)(_ah)->ah_st,	\
+		    (bus_space_handle_t)(_ah)->ah_sh, (_reg)))
+#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
+#define	OS_REG_WRITE(_ah, _reg, _val)					\
+	bus_space_write_4((bus_space_tag_t)(_ah)->ah_st,		\
+	    (bus_space_handle_t)(_ah)->ah_sh, (_reg), (_val))
+#define	OS_REG_READ(_ah, _reg)						\
+	bus_space_read_4((bus_space_tag_t)(_ah)->ah_st,			\
+	    (bus_space_handle_t)(_ah)->ah_sh, (_reg))
+#endif /* _BYTE_ORDER */
+#endif /* AH_DEBUG || AH_REGFUNC || AH_DEBUG_ALQ */
+
+#ifdef AH_DEBUG_ALQ
+extern	void OS_MARK(struct ath_hal *, u_int id, u_int32_t value);
+#else
+#define	OS_MARK(_ah, _id, _v)
+#endif
+
+#endif /* _ATH_AH_OSDEP_H_ */
Index: amrr.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ath/ath_rate/amrr/amrr.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/ath/ath_rate/amrr/amrr.c -L sys/dev/ath/ath_rate/amrr/amrr.c -u -r1.1.1.2 -r1.2
--- sys/dev/ath/ath_rate/amrr/amrr.c
+++ sys/dev/ath/ath_rate/amrr/amrr.c
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/amrr/amrr.c,v 1.8.2.3 2006/02/24 19:51:11 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/amrr/amrr.c,v 1.14 2007/07/27 11:59:55 rwatson Exp $");
 
 /*
  * AMRR rate control. See:
@@ -142,11 +142,12 @@
 
 void
 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
-	const struct ath_desc *ds, const struct ath_desc *ds0)
+	const struct ath_buf *bf)
 {
 	struct amrr_node *amn = ATH_NODE_AMRR(an);
-	int sr = ds->ds_txstat.ts_shortretry;
-	int lr = ds->ds_txstat.ts_longretry;
+	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
+	int sr = ts->ts_shortretry;
+	int lr = ts->ts_longretry;
 	int retry_count = sr + lr;
 
 	amn->amn_tx_try0_cnt++;
@@ -296,27 +297,27 @@
 			/* NB: the rate set is assumed sorted */
 			for (; srate >= 0 && RATE(srate) > 72; srate--)
 				;
-			KASSERT(srate >= 0, ("bogus rate set"));
 		}
 	} else {
 		/*
-		 * A fixed rate is to be used; ic_fixed_rate is an
-		 * index into the supported rate set.  Convert this
+		 * A fixed rate is to be used; ic_fixed_rate is the
+		 * IEEE code for this rate (sans basic bit).  Convert this
 		 * to the index into the negotiated rate set for
 		 * the node.  We know the rate is there because the
 		 * rate set is checked when the station associates.
 		 */
-		const struct ieee80211_rateset *rs =
-			&ic->ic_sup_rates[ic->ic_curmode];
-		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
 		/* NB: the rate set is assumed sorted */
 		srate = ni->ni_rates.rs_nrates - 1;
-		for (; srate >= 0 && RATE(srate) != r; srate--)
+		for (; srate >= 0 && RATE(srate) != ic->ic_fixed_rate; srate--)
 			;
-		KASSERT(srate >= 0,
-			("fixed rate %d not in rate set", ic->ic_fixed_rate));
 	}
-	ath_rate_update(sc, ni, srate);
+	/*
+	 * The selected rate may not be available due to races
+	 * and mode settings.  Also orphaned nodes created in
+	 * adhoc mode may not have any rate set so this lookup
+	 * can fail.  This is not fatal.
+	 */
+	ath_rate_update(sc, ni, srate < 0 ? 0 : srate);
 #undef RATE
 }
 
@@ -503,7 +504,7 @@
 	if (asc == NULL)
 		return NULL;
 	asc->arc.arc_space = sizeof(struct amrr_node);
-	callout_init(&asc->timer, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
+	callout_init(&asc->timer, CALLOUT_MPSAFE);
 	ath_rate_sysctlattach(sc);
 
 	return &asc->arc;
Index: onoe.h
===================================================================
RCS file: /home/cvs/src/sys/dev/ath/ath_rate/onoe/onoe.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/dev/ath/ath_rate/onoe/onoe.h -L sys/dev/ath/ath_rate/onoe/onoe.h -u -r1.1.1.1 -r1.2
--- sys/dev/ath/ath_rate/onoe/onoe.h
+++ sys/dev/ath/ath_rate/onoe/onoe.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -7,18 +7,11 @@
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer,
-    without modification.
+ *    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.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
  *
  * NO WARRANTY
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -33,7 +26,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGES.
  *
- * $FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.h,v 1.2 2004/12/31 22:41:45 sam Exp $
+ * $FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.h,v 1.3 2007/06/06 15:49:16 sam Exp $
  */
 
 /*
Index: onoe.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ath/ath_rate/onoe/onoe.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/ath/ath_rate/onoe/onoe.c -L sys/dev/ath/ath_rate/onoe/onoe.c -u -r1.1.1.2 -r1.2
--- sys/dev/ath/ath_rate/onoe/onoe.c
+++ sys/dev/ath/ath_rate/onoe/onoe.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -12,13 +12,6 @@
  *    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.
- * 3. Neither the names of the above-listed copyright holders nor the names
- *    of any contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
  *
  * NO WARRANTY
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
@@ -35,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.8.2.3 2006/02/24 19:51:11 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.15 2007/07/27 11:59:55 rwatson Exp $");
 
 /*
  * Atsushi Onoe's rate control algorithm.
@@ -159,16 +152,17 @@
 
 void
 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
-	const struct ath_desc *ds, const struct ath_desc *ds0)
+	const struct ath_buf *bf)
 {
 	struct onoe_node *on = ATH_NODE_ONOE(an);
+	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
 
-	if (ds->ds_txstat.ts_status == 0)
+	if (ts->ts_status == 0)
 		on->on_tx_ok++;
 	else
 		on->on_tx_err++;
-	on->on_tx_retr += ds->ds_txstat.ts_shortretry
-			+ ds->ds_txstat.ts_longretry;
+	on->on_tx_retr += ts->ts_shortretry
+			+ ts->ts_longretry;
 }
 
 void
@@ -280,27 +274,27 @@
 			/* NB: the rate set is assumed sorted */
 			for (; srate >= 0 && RATE(srate) > 72; srate--)
 				;
-			KASSERT(srate >= 0, ("bogus rate set"));
 		}
 	} else {
 		/*
-		 * A fixed rate is to be used; ic_fixed_rate is an
-		 * index into the supported rate set.  Convert this
+		 * A fixed rate is to be used; ic_fixed_rate is the
+		 * IEEE code for this rate (sans basic bit).  Convert this
 		 * to the index into the negotiated rate set for
 		 * the node.  We know the rate is there because the
 		 * rate set is checked when the station associates.
 		 */
-		const struct ieee80211_rateset *rs =
-			&ic->ic_sup_rates[ic->ic_curmode];
-		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
 		/* NB: the rate set is assumed sorted */
 		srate = ni->ni_rates.rs_nrates - 1;
-		for (; srate >= 0 && RATE(srate) != r; srate--)
+		for (; srate >= 0 && RATE(srate) != ic->ic_fixed_rate; srate--)
 			;
-		KASSERT(srate >= 0,
-			("fixed rate %d not in rate set", ic->ic_fixed_rate));
 	}
-	ath_rate_update(sc, ni, srate);
+	/*
+	 * The selected rate may not be available due to races
+	 * and mode settings.  Also orphaned nodes created in
+	 * adhoc mode may not have any rate set so this lookup
+	 * can fail.  This is not fatal.
+	 */
+	ath_rate_update(sc, ni, srate < 0 ? 0 : srate);
 #undef RATE
 }
 
@@ -484,7 +478,7 @@
 	if (osc == NULL)
 		return NULL;
 	osc->arc.arc_space = sizeof(struct onoe_node);
-	callout_init(&osc->timer, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
+	callout_init(&osc->timer, CALLOUT_MPSAFE);
 	ath_rate_sysctlattach(sc);
 
 	return &osc->arc;
Index: sample.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ath/ath_rate/sample/sample.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/ath/ath_rate/sample/sample.c -L sys/dev/ath/ath_rate/sample/sample.c -u -r1.2 -r1.3
--- sys/dev/ath/ath_rate/sample/sample.c
+++ sys/dev/ath/ath_rate/sample/sample.c
@@ -32,10 +32,11 @@
  * 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: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.8.2.3 2006/03/14 23:22:27 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.18.2.1 2007/10/16 19:07:26 sam Exp $");
 
 /*
  * John Bicket's SampleRate control algorithm.
@@ -78,14 +79,18 @@
 #define	SAMPLE_DEBUG
 #ifdef SAMPLE_DEBUG
 enum {
-	ATH_DEBUG_RATE		= 0x00000010	/* rate control */
+	ATH_DEBUG_NODE		= 0x00080000,	/* node management */
+	ATH_DEBUG_RATE		= 0x00000010,	/* rate control */
+	ATH_DEBUG_ANY		= 0xffffffff
 };
-#define	DPRINTF(sc, _fmt, ...) do {				\
-	if (sc->sc_debug & ATH_DEBUG_RATE)			\
-		printf(_fmt, __VA_ARGS__);			\
+#define	DPRINTF(sc, m, fmt, ...) do {				\
+	if (sc->sc_debug & (m))					\
+		printf(fmt, __VA_ARGS__);			\
 } while (0)
 #else
-#define	DPRINTF(sc, _fmt, ...)
+#define	DPRINTF(sc, m, fmt, ...) do {				\
+	(void) sc;						\
+} while (0)
 #endif
 
 /*
@@ -147,14 +152,14 @@
 void
 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
 {
-	DPRINTF(sc, "%s:\n", __func__);
+	DPRINTF(sc, ATH_DEBUG_NODE, "%s:\n", __func__);
 	/* NB: assumed to be zero'd by caller */
 }
 
 void
 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 {
-	DPRINTF(sc, "%s:\n", __func__);
+	DPRINTF(sc, ATH_DEBUG_NODE, "%s:\n", __func__);
 }
 
 
@@ -318,18 +323,19 @@
 			
 			if (change_rates) {
 				if (best_ndx != sn->current_rate[size_bin]) {
-					DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n",
-						__func__,
-						ether_sprintf(an->an_node.ni_macaddr),
-						packet_size_bins[size_bin],
-						sn->rates[sn->current_rate[size_bin]].rate,
-						sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
-						sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
-						sn->rates[best_ndx].rate,
-						sn->stats[size_bin][best_ndx].average_tx_time,
-						sn->stats[size_bin][best_ndx].perfect_tx_time,
-						sn->packets_since_switch[size_bin],
-						mrr);
+					DPRINTF(sc, ATH_DEBUG_RATE,
+"%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n",
+					    __func__,
+					    ether_sprintf(an->an_node.ni_macaddr),
+					    packet_size_bins[size_bin],
+					    sn->rates[sn->current_rate[size_bin]].rate,
+					    sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
+					    sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
+					    sn->rates[best_ndx].rate,
+					    sn->stats[size_bin][best_ndx].average_tx_time,
+					    sn->stats[size_bin][best_ndx].perfect_tx_time,
+					    sn->packets_since_switch[size_bin],
+					    mrr);
 				}
 				sn->packets_since_switch[size_bin] = 0;
 				sn->current_rate[size_bin] = best_ndx;
@@ -406,30 +412,51 @@
 
 	size_bin = size_to_bin(frame_size);
 	size = bin_to_size(size_bin);
+
+	if (!(0 <= ndx0 && ndx0 < sn->num_rates)) {
+		printf("%s: bogus ndx0 %d, max %u, mode %u\n",
+		    __func__, ndx0, sn->num_rates, sc->sc_curmode);
+		return;
+	}
 	rate = sn->rates[ndx0].rate;
 
 	tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix, 
-					short_tries-1, 
+					short_tries,
 					MIN(tries0, tries) - 1);
 	tries_so_far += tries0;
 	if (tries1 && tries0 < tries) {
+		if (!(0 <= ndx1 && ndx1 < sn->num_rates)) {
+			printf("%s: bogus ndx1 %d, max %u, mode %u\n",
+			    __func__, ndx1, sn->num_rates, sc->sc_curmode);
+			return;
+		}
 		tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx1].rix, 
-						short_tries-1, 
+						short_tries,
 						MIN(tries1 + tries_so_far, tries) - tries_so_far - 1);
 	}
 	tries_so_far += tries1;
 
 	if (tries2 && tries0 + tries1 < tries) {
+		if (!(0 <= ndx2 && ndx2 < sn->num_rates)) {
+			printf("%s: bogus ndx2 %d, max %u, mode %u\n",
+			    __func__, ndx2, sn->num_rates, sc->sc_curmode);
+			return;
+		}
 		tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx2].rix, 
-					       short_tries-1, 
+					       short_tries,
 						MIN(tries2 + tries_so_far, tries) - tries_so_far - 1);
 	}
 
 	tries_so_far += tries2;
 
 	if (tries3 && tries0 + tries1 + tries2 < tries) {
+		if (!(0 <= ndx3 && ndx3 < sn->num_rates)) {
+			printf("%s: bogus ndx3 %d, max %u, mode %u\n",
+			    __func__, ndx3, sn->num_rates, sc->sc_curmode);
+			return;
+		}
 		tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx3].rix, 
-						short_tries-1, 
+						short_tries,
 						MIN(tries3 + tries_so_far, tries) - tries_so_far - 1);
 	}
 	if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) {
@@ -467,12 +494,14 @@
 
 
 	if (ndx0 == sn->current_sample_ndx[size_bin]) {
-		DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n", 
-			__func__, ether_sprintf(an->an_node.ni_macaddr), 
-			size, rate, short_tries, tries, tt, 
-			sn->stats[size_bin][ndx0].average_tx_time,
-			sn->stats[size_bin][ndx0].perfect_tx_time,
-			status);
+		DPRINTF(sc, ATH_DEBUG_RATE,
+"%s: %s size %d %s sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d)\n", 
+		    __func__, ether_sprintf(an->an_node.ni_macaddr), 
+		    size,
+		    status ? "FAIL" : "OK",
+		    rate, short_tries, tries, tt, 
+		    sn->stats[size_bin][ndx0].average_tx_time,
+		    sn->stats[size_bin][ndx0].perfect_tx_time);
 		sn->sample_tt[size_bin] = tt;
 		sn->current_sample_ndx[size_bin] = -1;
 	}
@@ -480,117 +509,116 @@
 
 void
 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
-	const struct ath_desc *ds, const struct ath_desc *ds0)
+	const struct ath_buf *bf)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
-	const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
+	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
+	const struct ath_desc *ds0 = &bf->bf_desc[0];
 	int final_rate, short_tries, long_tries, frame_size;
-	int ndx = -1;
 	int mrr;
 
-	final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
-	short_tries = ds->ds_txstat.ts_shortretry + 1;
-	long_tries = ds->ds_txstat.ts_longretry + 1;
+	final_rate = sc->sc_hwmap[ts->ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
+	short_tries = ts->ts_shortretry;
+	long_tries = ts->ts_longretry + 1;
 	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
 	if (frame_size == 0)		    /* NB: should not happen */
 		frame_size = 1500;
 
 	if (sn->num_rates <= 0) {
-		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
-			"no rates yet\n", 
-			__func__, ether_sprintf(an->an_node.ni_macaddr),
-			bin_to_size(size_to_bin(frame_size)),
-			ds->ds_txstat.ts_status,
-			short_tries, long_tries);
+		DPRINTF(sc, ATH_DEBUG_RATE,
+		    "%s: %s size %d %s rate/try %d/%d no rates yet\n", 
+		    __func__, ether_sprintf(an->an_node.ni_macaddr),
+		    bin_to_size(size_to_bin(frame_size)),
+		    ts->ts_status ? "FAIL" : "OK",
+		    short_tries, long_tries);
 		return;
 	}
-
 	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
+	if (!mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
+		int ndx = rate_to_ndx(sn, final_rate);
 
-	if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
-		/* this packet failed */
-		DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n", 
-			__func__,
-			ether_sprintf(an->an_node.ni_macaddr),
-			bin_to_size(size_to_bin(frame_size)),
-			sc->sc_hwmap[ads->xmit_rate0].ieeerate,
-				ads->xmit_tries0,
-			sc->sc_hwmap[ads->xmit_rate1].ieeerate,
-				ads->xmit_tries1,
-			sc->sc_hwmap[ads->xmit_rate2].ieeerate,
-				ads->xmit_tries2,
-			sc->sc_hwmap[ads->xmit_rate3].ieeerate,
-				ads->xmit_tries3,
-			ds->ds_txstat.ts_status ? "FAIL" : "OK",
-			short_tries, 
-			long_tries);
-	}
-
-	if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
-		/* only one rate was used */
-		ndx = rate_to_ndx(sn, final_rate);
-		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n", 
-			__func__, ether_sprintf(an->an_node.ni_macaddr),
-			bin_to_size(size_to_bin(frame_size)),
-			ds->ds_txstat.ts_status,
-			ndx, short_tries, long_tries);
-		if (ndx >= 0 && ndx < sn->num_rates) {
-			update_stats(sc, an, frame_size, 
-				     ndx, long_tries,
-				     0, 0,
-				     0, 0,
-				     0, 0,
-				     short_tries, long_tries, ds->ds_txstat.ts_status);
-		}
+		/*
+		 * Only one rate was used; optimize work.
+		 */
+		DPRINTF(sc, ATH_DEBUG_RATE,
+		    "%s: %s size %d %s rate/try %d/%d/%d\n", 
+		     __func__, ether_sprintf(an->an_node.ni_macaddr),
+		     bin_to_size(size_to_bin(frame_size)),
+		     ts->ts_status ? "FAIL" : "OK",
+		     final_rate, short_tries, long_tries);
+		update_stats(sc, an, frame_size, 
+			     ndx, long_tries,
+			     0, 0,
+			     0, 0,
+			     0, 0,
+			     short_tries, long_tries, ts->ts_status);
 	} else {
-		int rate0, tries0, ndx0;
-		int rate1, tries1, ndx1;
-		int rate2, tries2, ndx2;
-		int rate3, tries3, ndx3;
-		int finalTSIdx = ads->final_ts_index;
+		int hwrate0, rate0, tries0, ndx0;
+		int hwrate1, rate1, tries1, ndx1;
+		int hwrate2, rate2, tries2, ndx2;
+		int hwrate3, rate3, tries3, ndx3;
+		int finalTSIdx = ts->ts_finaltsi;
 
 		/*
 		 * Process intermediate rates that failed.
 		 */
+		if (sc->sc_ah->ah_magic != 0x20065416) {
+			hwrate0 = MS(ds0->ds_ctl3, AR_XmitRate0);
+			hwrate1 = MS(ds0->ds_ctl3, AR_XmitRate1);
+			hwrate2 = MS(ds0->ds_ctl3, AR_XmitRate2);
+			hwrate3 = MS(ds0->ds_ctl3, AR_XmitRate3);
+		} else {
+			hwrate0 = MS(ds0->ds_ctl3, AR5416_XmitRate0);
+			hwrate1 = MS(ds0->ds_ctl3, AR5416_XmitRate1);
+			hwrate2 = MS(ds0->ds_ctl3, AR5416_XmitRate2);
+			hwrate3 = MS(ds0->ds_ctl3, AR5416_XmitRate3);
+		}
 
-		rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
-		tries0 = ads->xmit_tries0;
+		rate0 = sc->sc_hwmap[hwrate0].ieeerate;
+		tries0 = MS(ds0->ds_ctl2, AR_XmitDataTries0);
 		ndx0 = rate_to_ndx(sn, rate0);
-		
-		rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
-		tries1 = ads->xmit_tries1;
+
+		rate1 = sc->sc_hwmap[hwrate1].ieeerate;
+		tries1 = MS(ds0->ds_ctl2, AR_XmitDataTries1);
 		ndx1 = rate_to_ndx(sn, rate1);
-		
-		rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
-		tries2 = ads->xmit_tries2;
+
+		rate2 = sc->sc_hwmap[hwrate2].ieeerate;
+		tries2 = MS(ds0->ds_ctl2, AR_XmitDataTries2);
 		ndx2 = rate_to_ndx(sn, rate2);
-		
-		rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
-		tries3 = ads->xmit_tries3;
+
+		rate3 = sc->sc_hwmap[hwrate3].ieeerate;
+		tries3 = MS(ds0->ds_ctl2, AR_XmitDataTries3);
 		ndx3 = rate_to_ndx(sn, rate3);
-		
-#if 1
-		DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n", 
-			__func__, ether_sprintf(an->an_node.ni_macaddr),
-			bin_to_size(size_to_bin(frame_size)),
-			finalTSIdx,
-			long_tries, 
-			ds->ds_txstat.ts_status,
-			rate0, tries0,
-			rate1, tries1,
-			rate2, tries2,
-			rate3, tries3);
-#endif
 
+		DPRINTF(sc, ATH_DEBUG_RATE,
+"%s: %s size %d finaltsidx %d tries %d %s rate/try [%d/%d %d/%d %d/%d %d/%d]\n", 
+		     __func__, ether_sprintf(an->an_node.ni_macaddr),
+		     bin_to_size(size_to_bin(frame_size)),
+		     finalTSIdx,
+		     long_tries, 
+		     ts->ts_status ? "FAIL" : "OK",
+		     rate0, tries0,
+		     rate1, tries1,
+		     rate2, tries2,
+		     rate3, tries3);
+
+		/*
+		 * NB: series > 0 are not penalized for failure
+		 * based on the try counts under the assumption
+		 * that losses are often bursty and since we
+		 * sample higher rates 1 try at a time doing so
+		 * may unfairly penalize them.
+		 */
 		if (tries0) {
 			update_stats(sc, an, frame_size, 
 				     ndx0, tries0, 
 				     ndx1, tries1, 
 				     ndx2, tries2, 
 				     ndx3, tries3, 
-				     short_tries, ds->ds_txstat.ts_longretry + 1, 
+				     short_tries, long_tries, 
 				     long_tries > tries0);
+			long_tries -= tries0;
 		}
 		
 		if (tries1 && finalTSIdx > 0) {
@@ -599,8 +627,9 @@
 				     ndx2, tries2, 
 				     ndx3, tries3, 
 				     0, 0, 
-				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0, 
-				     ds->ds_txstat.ts_status);
+				     short_tries, long_tries, 
+				     ts->ts_status);
+			long_tries -= tries1;
 		}
 
 		if (tries2 && finalTSIdx > 1) {
@@ -609,8 +638,9 @@
 				     ndx3, tries3, 
 				     0, 0,
 				     0, 0,
-				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1, 
-				     ds->ds_txstat.ts_status);
+				     short_tries, long_tries, 
+				     ts->ts_status);
+			long_tries -= tries2;
 		}
 
 		if (tries3 && finalTSIdx > 2) {
@@ -619,8 +649,8 @@
 				     0, 0,
 				     0, 0,
 				     0, 0,
-				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2, 
-				     ds->ds_txstat.ts_status);
+				     short_tries, long_tries, 
+				     ts->ts_status);
 		}
 	}
 }
@@ -628,8 +658,8 @@
 void
 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
 {
-	DPRINTF(sc, "%s: %s isnew %d\n", __func__,
-		ether_sprintf(an->an_node.ni_macaddr), isnew);
+	DPRINTF(sc, ATH_DEBUG_NODE, "%s: %s isnew %d\n", __func__,
+	     ether_sprintf(an->an_node.ni_macaddr), isnew);
 	if (isnew)
 		ath_rate_ctl_reset(sc, &an->an_node);
 }
@@ -651,32 +681,35 @@
         sn->static_rate_ndx = -1;
 	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
 		/*
-		 * A fixed rate is to be used; ic_fixed_rate is an
-		 * index into the supported rate set.  Convert this
+		 * A fixed rate is to be used; ic_fixed_rate is the
+		 * IEEE code for this rate (sans basic bit).  Convert this
 		 * to the index into the negotiated rate set for
 		 * the node.
 		 */
-		const struct ieee80211_rateset *rs =
-			&ic->ic_sup_rates[ic->ic_curmode];
-		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
 		/* NB: the rate set is assumed sorted */
 		srate = ni->ni_rates.rs_nrates - 1;
-		for (; srate >= 0 && RATE(srate) != r; srate--)
+		for (; srate >= 0 && RATE(srate) != ic->ic_fixed_rate; srate--)
 			;
-		KASSERT(srate >= 0,
-			("fixed rate %d not in rate set", ic->ic_fixed_rate));
-		sn->static_rate_ndx = srate;
+		/*
+		 * The fixed rate may not be available due to races
+		 * and mode settings.  Also orphaned nodes created in
+		 * adhoc mode may not have any rate set so this lookup
+		 * can fail.
+		 */
+		if (srate >= 0)
+			sn->static_rate_ndx = srate;
 	}
 
-        DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));
+        DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s size 1600 rate/tt",
+	    __func__, ether_sprintf(ni->ni_macaddr));
 
 	sn->num_rates = ni->ni_rates.rs_nrates;
         for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
 		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
 		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
 		if (sn->rates[x].rix == 0xff) {
-			DPRINTF(sc, "%s: ignore bogus rix at %d\n",
-				__func__, x);
+			DPRINTF(sc, ATH_DEBUG_RATE,
+			    "%s: ignore bogus rix at %d\n", __func__, x);
 			continue;
 		}
 		sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
@@ -684,11 +717,10 @@
 			rt->info[sn->rates[x].rix].rateCode | 
 			rt->info[sn->rates[x].rix].shortPreamble;
 
-		DPRINTF(sc, " %d/%d", sn->rates[x].rate,
-			calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 
-						  0,0));
+		DPRINTF(sc, ATH_DEBUG_RATE, " %d/%d", sn->rates[x].rate,
+		    calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 0,0));
 	}
-	DPRINTF(sc, "%s\n", "");
+	DPRINTF(sc, ATH_DEBUG_RATE, "%s\n", "");
 	
 	/* set the visible bit-rate to the lowest one available */
 	ni->ni_txrate = 0;
@@ -724,14 +756,15 @@
 		sn->current_rate[y] = ndx;
 	}
 
-	DPRINTF(sc, "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
-		__func__, ether_sprintf(ni->ni_macaddr), 
-		sn->num_rates,
-		sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
-		sn->stats[1][0].perfect_tx_time,
-		sn->rates[sn->num_rates-1].rate/2,
-			sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
-		sn->stats[1][sn->num_rates-1].perfect_tx_time
+	DPRINTF(sc, ATH_DEBUG_RATE,
+	    "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
+	    __func__, ether_sprintf(ni->ni_macaddr), 
+	    sn->num_rates,
+	    sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
+	    sn->stats[1][0].perfect_tx_time,
+	    sn->rates[sn->num_rates-1].rate/2,
+		sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
+	    sn->stats[1][sn->num_rates-1].perfect_tx_time
 	);
 
         if (sn->static_rate_ndx != -1)
@@ -789,7 +822,7 @@
 {
 	struct sample_softc *osc;
 	
-	DPRINTF(sc, "%s:\n", __func__);
+	DPRINTF(sc, ATH_DEBUG_ANY, "%s:\n", __func__);
 	osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
 	if (osc == NULL)
 		return NULL;
Index: sample.h
===================================================================
RCS file: /home/cvs/src/sys/dev/ath/ath_rate/sample/sample.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/dev/ath/ath_rate/sample/sample.h -L sys/dev/ath/ath_rate/sample/sample.h -u -r1.1.1.2 -r1.2
--- sys/dev/ath/ath_rate/sample/sample.h
+++ sys/dev/ath/ath_rate/sample/sample.h
@@ -33,7 +33,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGES.
  *
- * $FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.h,v 1.3.2.1 2006/02/24 19:51:11 sam Exp $
+ * $FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.h,v 1.7 2007/01/15 01:17:44 sam Exp $
  */
 
 /*
@@ -107,77 +107,46 @@
 #define WIFI_CW_MIN 31
 #define WIFI_CW_MAX 1023
 
-struct ar5212_desc {
-	/*
-	 * tx_control_0
-	 */
-	u_int32_t	frame_len:12;
-	u_int32_t	reserved_12_15:4;
-	u_int32_t	xmit_power:6;
-	u_int32_t	rts_cts_enable:1;
-	u_int32_t	veol:1;
-	u_int32_t	clear_dest_mask:1;
-	u_int32_t	ant_mode_xmit:4;
-	u_int32_t	inter_req:1;
-	u_int32_t	encrypt_key_valid:1;
-	u_int32_t	cts_enable:1;
-
-	/*
-	 * tx_control_1
-	 */
-	u_int32_t	buf_len:12;
-	u_int32_t	more:1;
-	u_int32_t	encrypt_key_index:7;
-	u_int32_t	frame_type:4;
-	u_int32_t	no_ack:1;
-	u_int32_t	comp_proc:2;
-	u_int32_t	comp_iv_len:2;
-	u_int32_t	comp_icv_len:2;
-	u_int32_t	reserved_31:1;
-
-	/*
-	 * tx_control_2
-	 */
-	u_int32_t	rts_duration:15;
-	u_int32_t	duration_update_enable:1;
-	u_int32_t	xmit_tries0:4;
-	u_int32_t	xmit_tries1:4;
-	u_int32_t	xmit_tries2:4;
-	u_int32_t	xmit_tries3:4;
-
-	/*
-	 * tx_control_3
-	 */
-	u_int32_t	xmit_rate0:5;
-	u_int32_t	xmit_rate1:5;
-	u_int32_t	xmit_rate2:5;
-	u_int32_t	xmit_rate3:5;
-	u_int32_t	rts_cts_rate:5;
-	u_int32_t	reserved_25_31:7;
+/*
+ * Definitions for pulling the rate and trie counts from
+ * a 5212 h/w descriptor.  These Don't belong here; the
+ * driver should record this information so the rate control
+ * code doesn't go groveling around in the descriptor bits.
+ */
+#define	ds_ctl2		ds_hw[0]
+#define	ds_ctl3		ds_hw[1]
 
-	/*
-	 * tx_status_0
-	 */
-	u_int32_t	frame_xmit_ok:1;
-	u_int32_t	excessive_retries:1;
-	u_int32_t	fifo_underrun:1;
-	u_int32_t	filtered:1;
-	u_int32_t	rts_fail_count:4;
-	u_int32_t	data_fail_count:4;
-	u_int32_t	virt_coll_count:4;
-	u_int32_t	send_timestamp:16;
+/* TX ds_ctl2 */
+#define	AR_XmitDataTries0	0x000f0000	/* series 0 max attempts */
+#define	AR_XmitDataTries0_S	16
+#define	AR_XmitDataTries1	0x00f00000	/* series 1 max attempts */
+#define	AR_XmitDataTries1_S	20
+#define	AR_XmitDataTries2	0x0f000000	/* series 2 max attempts */
+#define	AR_XmitDataTries2_S	24
+#define	AR_XmitDataTries3	0xf0000000	/* series 3 max attempts */
+#define	AR_XmitDataTries3_S	28
+
+/* TX ds_ctl3 */
+#define	AR_XmitRate0		0x0000001f	/* series 0 tx rate */
+#define	AR_XmitRate0_S		0
+#define	AR_XmitRate1		0x000003e0	/* series 1 tx rate */
+#define	AR_XmitRate1_S		5
+#define	AR_XmitRate2		0x00007c00	/* series 2 tx rate */
+#define	AR_XmitRate2_S		10
+#define	AR_XmitRate3		0x000f8000	/* series 3 tx rate */
+#define	AR_XmitRate3_S		15
+
+/* TX ds_ctl3 for 5416 */
+#define	AR5416_XmitRate0	0x000000ff	/* series 0 tx rate */
+#define	AR5416_XmitRate0_S	0
+#define	AR5416_XmitRate1	0x0000ff00	/* series 1 tx rate */
+#define	AR5416_XmitRate1_S	8
+#define	AR5416_XmitRate2	0x00ff0000	/* series 2 tx rate */
+#define	AR5416_XmitRate2_S	16
+#define	AR5416_XmitRate3	0xff000000	/* series 3 tx rate */
+#define	AR5416_XmitRate3_S	24
 
-	/*
-	 * tx_status_1
-	 */
-	u_int32_t	done:1;
-	u_int32_t	seq_num:12;
-	u_int32_t	ack_sig_strength:8;
-	u_int32_t	final_ts_index:2;
-	u_int32_t	comp_success:1;
-	u_int32_t	xmit_antenna:1;
-	u_int32_t	reserved_25_31_x:7;
-} __packed;
+#define MS(_v, _f)	(((_v) & (_f)) >> _f##_S)
 
 /*
  * Calculate the transmit duration of a frame.
@@ -195,18 +164,16 @@
 	int tt = 0;
 	int x = 0;
 	int cw = WIFI_CW_MIN;
-	int cix = rt->info[rix].controlRate;
+	int cix;
 	
 	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
 
-	if (!rt->info[rix].rateKbps) {
-		printf("rix %d (%d) bad ratekbps %d mode %u",
-		       rix, rt->info[rix].dot11Rate,
-		       rt->info[rix].rateKbps,
-		       sc->sc_curmode);
-
+	if (rix >= rt->rateCount) {
+		printf("bogus rix %d, max %u, mode %u\n",
+		       rix, rt->rateCount, sc->sc_curmode);
 		return 0;
 	}
+	cix = rt->info[rix].controlRate;
 	/* 
 	 * XXX getting mac/phy level timings should be fixed for turbo
 	 * rates, and there is probably a way to get this from the
@@ -250,18 +217,15 @@
 	}
 
 	if (rts || cts) {
-		int ctsrate = rt->info[cix].rateCode;
+		int ctsrate;
 		int ctsduration = 0;
 
-		if (!rt->info[cix].rateKbps) {
-			printf("cix %d (%d) bad ratekbps %d mode %u",
-			       cix, rt->info[cix].dot11Rate,
-			       rt->info[cix].rateKbps,
-			       sc->sc_curmode);
-			return 0;
-		}
+		/* NB: this is intentionally not a runtime check */
+		KASSERT(cix < rt->rateCount,
+		    ("bogus cix %d, max %u, mode %u\n", cix, rt->rateCount,
+		     sc->sc_curmode));
 
-		ctsrate |= rt->info[cix].shortPreamble;
+		ctsrate = rt->info[cix].rateCode | rt->info[cix].shortPreamble;
 		if (rts)		/* SIFS + CTS */
 			ctsduration += rt->info[cix].spAckDuration;
 


More information about the Midnightbsd-cvs mailing list