--- a/sys/dev/netif/ath/ath_hal/ah_osdep.c +++ b/sys/dev/netif/ath/ath_hal/ah_osdep.c @@ -185,184 +185,20 @@ #undef HAL_DEBUG_UNMASKABLE #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. +/* DF-4893: the AH_DEBUG_ALQ block (ALQ register tracing) was removed. * - * NB: doesn't handle multiple devices properly; only one DEVICE record - * is emitted and the different devices are not identified. - */ -/*#include FreeBSD */ -/*#include FreeBSD */ -#include - -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 char ath_hal_logfile[MAXPATHLEN] = "/tmp/ath_hal.log"; - -SYSCTL_STRING(_hw_ath_hal, OID_AUTO, alq_logfile, CTLFLAG_RW, - &ath_hal_logfile, sizeof(kernelname), "Name of ALQ logfile"); - -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; - kprintf("ath_hal: logging to %s enabled\n", - ath_hal_logfile); - } else { - if (ath_hal_alq) - alq_close(ath_hal_alq); - ath_hal_alq = NULL; - kprintf("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 = ah->ah_sh; - -#ifdef AH_DEBUG - /* Debug - complain if we haven't fully waken things up */ - if (! ath_hal_reg_whilst_asleep(ah, reg) && - ah->ah_powerMode != HAL_PM_AWAKE) { - ath_hal_printf(ah, "%s: reg=0x%08x, val=0x%08x, pm=%d\n", - __func__, reg, val, ah->ah_powerMode); - } -#endif - - if (ath_hal_alq) { - struct ale *ale = ath_hal_alq_get(ah); - if (ale) { - struct athregrec *r = (struct athregrec *) ale->ae_data; - r->threadid = curthread->td_tid; - r->op = OP_WRITE; - r->reg = reg; - r->val = val; - alq_post(ath_hal_alq, ale); - } - } - if (ah->ah_config.ah_serialise_reg_war) - lockmgr(&ah_regser_mtx, LK_EXCLUSIVE); - bus_space_write_4(tag, h, reg, val); - OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE); - if (ah->ah_config.ah_serialise_reg_war) - lockmgr(&ah_regser_mtx, LK_RELEASE); -} - -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 = ah->ah_sh; - u_int32_t val; - - /* Debug - complain if we haven't fully waken things up */ - if (! ath_hal_reg_whilst_asleep(ah, reg) && - ah->ah_powerMode != HAL_PM_AWAKE) { - ath_hal_printf(ah, "%s: reg=0x%08x, pm=%d\n", - __func__, reg, ah->ah_powerMode); - } - - if (ah->ah_config.ah_serialise_reg_war) - lockmgr(&ah_regser_mtx, LK_EXCLUSIVE); - OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ); - val = bus_space_read_4(tag, h, reg); - if (ah->ah_config.ah_serialise_reg_war) - lockmgr(&ah_regser_mtx, LK_RELEASE); - if (ath_hal_alq) { - struct ale *ale = ath_hal_alq_get(ah); - if (ale) { - struct athregrec *r = (struct athregrec *) ale->ae_data; - r->threadid = curthread->td_tid; - 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->threadid = curthread->td_tid; - r->op = OP_MARK; - r->reg = id; - r->val = v; - alq_post(ath_hal_alq, ale); - } - } -} -#else /* AH_DEBUG_ALQ */ + * It was inherited FreeBSD glue that can never compile on DragonFly: + * - the AH_DEBUG_ALQ option mapping is commented out (sys/conf/options); + * - no alq(9) implementation or exists in this tree + * (the include was commented out here); + * - its ath_hal_reg_read() called ath_hal_reg_whilst_asleep(), which is + * only defined under AH_DEBUG. + * The block also carried a TOCTOU: consumers checked the unlocked global + * `ath_hal_alq` (NULL test) and then passed it to alq_get()/alq_post() + * while the sysctl disable path ran alq_close() + NULL-store on it -- a + * use-after-free if the block is ever revived without locking. If alq(9) + * is imported later, re-add the block with the global protected by a mutex + * on BOTH the consumer and the sysctl closer paths. */ /* * Memory-mapped device register read/write. These are here @@ -422,7 +258,6 @@ lockmgr(&ah_regser_mtx, LK_RELEASE); return val; } -#endif /* AH_DEBUG_ALQ */ #ifdef AH_ASSERT void