alq
static struct alq *ath_hal_alq;
SYSCTL_PROC(_hw_ath_hal, OID_AUTO, alq,
MODULE_DEPEND(ath_hal, alq, 1, 1, 1);
MODULE_DEPEND(ath_main, alq, 1, 1, 1);
if_ath_alq_start(struct if_ath_alq *alq)
if (alq->sc_alq_isactive)
error = alq_open(&alq->sc_alq_alq, alq->sc_alq_filename,
alq->sc_alq_qsize, 0);
alq->sc_alq_devname, error);
printf("%s (%s): opened\n", __func__, alq->sc_alq_devname);
alq->sc_alq_isactive = 1;
if_ath_alq_post(alq, ATH_ALQ_INIT_STATE,
(char *) &alq->sc_alq_cfg);
if_ath_alq_stop(struct if_ath_alq *alq)
if (alq->sc_alq_isactive == 0)
printf("%s (%s): closed\n", __func__, alq->sc_alq_devname);
alq->sc_alq_isactive = 0;
alq_close(alq->sc_alq_alq);
alq->sc_alq_alq = NULL;
if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len,
if (! if_ath_alq_checkdebug(alq, op))
ale = if_ath_alq_get(alq, len + sizeof(struct if_ath_alq_hdr));
alq_post(alq->sc_alq_alq, ale);
if_ath_alq_get(struct if_ath_alq *alq, int len)
if (alq->sc_alq_isactive == 0)
ale = alq_getn(alq->sc_alq_alq, len, ALQ_NOWAIT);
alq->sc_alq_numlost++;
if_ath_alq_init(struct if_ath_alq *alq, const char *devname)
bzero(alq, sizeof(*alq));
strncpy(alq->sc_alq_devname, devname, ATH_ALQ_DEVNAME_LEN);
printf("%s (%s): attached\n", __func__, alq->sc_alq_devname);
snprintf(alq->sc_alq_filename, ATH_ALQ_FILENAME_LEN,
"/tmp/ath_%s_alq.log", alq->sc_alq_devname);
alq->sc_alq_qsize = (64*1024);
if_ath_alq_setcfg(struct if_ath_alq *alq, uint32_t macVer,
alq->sc_alq_cfg.sc_mac_version = htobe32(macVer);
alq->sc_alq_cfg.sc_mac_revision = htobe32(macRev);
alq->sc_alq_cfg.sc_phy_rev = htobe32(phyRev);
alq->sc_alq_cfg.sc_hal_magic = htobe32(halMagic);
if_ath_alq_tidyup(struct if_ath_alq *alq)
if_ath_alq_stop(alq);
printf("%s (%s): detached\n", __func__, alq->sc_alq_devname);
bzero(alq, sizeof(*alq));
struct alq * sc_alq_alq; /* alq state */
if_ath_alq_checkdebug(struct if_ath_alq *alq, uint16_t op)
return ((alq->sc_alq_debug | ATH_ALQ_LOG_ALWAYS_MASK)
extern void if_ath_alq_init(struct if_ath_alq *alq, const char *devname);
extern void if_ath_alq_setcfg(struct if_ath_alq *alq, uint32_t macVer,
extern void if_ath_alq_tidyup(struct if_ath_alq *alq);
extern int if_ath_alq_start(struct if_ath_alq *alq);
extern int if_ath_alq_stop(struct if_ath_alq *alq);
extern void if_ath_alq_post(struct if_ath_alq *alq, uint16_t op,
if_ath_alq_post_intr(struct if_ath_alq *alq, uint32_t status,
if (! if_ath_alq_checkdebug(alq, ATH_ALQ_INTR_STATUS))
if_ath_alq_post(alq, ATH_ALQ_INTR_STATUS, sizeof(intr),
static int ald_add(struct alq *);
static int ald_rem(struct alq *);
static void ald_activate(struct alq *);
static void ald_deactivate(struct alq *);
static void alq_shutdown(struct alq *);
static void alq_destroy(struct alq *);
static int alq_doio(struct alq *);
ald_add(struct alq *alq)
LIST_INSERT_HEAD(&ald_queues, alq, aq_link);
ald_rem(struct alq *alq)
LIST_REMOVE(alq, aq_link);
ald_activate(struct alq *alq)
LIST_INSERT_HEAD(&ald_active, alq, aq_act);
ald_deactivate(struct alq *alq)
LIST_REMOVE(alq, aq_act);
alq->aq_flags &= ~AQ_ACTIVE;
struct alq *alq;
while ((alq = LIST_FIRST(&ald_active)) == NULL &&
if (ald_shutingdown && alq == NULL) {
ALQ_LOCK(alq);
ald_deactivate(alq);
needwakeup = alq_doio(alq);
ALQ_UNLOCK(alq);
wakeup_one(alq);
struct alq *alq;
while ((alq = LIST_FIRST(&ald_queues)) != NULL) {
LIST_REMOVE(alq, aq_link);
alq_shutdown(alq);
alq_shutdown(struct alq *alq)
ALQ_LOCK(alq);
alq->aq_flags |= AQ_SHUTDOWN;
if (!(alq->aq_flags & AQ_ACTIVE) && HAS_PENDING_DATA(alq)) {
alq->aq_flags |= AQ_ACTIVE;
ALQ_UNLOCK(alq);
ald_activate(alq);
ALQ_LOCK(alq);
while (alq->aq_flags & AQ_ACTIVE) {
alq->aq_flags |= AQ_WANTED;
msleep_spin(alq, &alq->aq_mtx, "aldclose", 0);
ALQ_UNLOCK(alq);
vn_close(alq->aq_vp, FWRITE, alq->aq_cred,
crfree(alq->aq_cred);
alq_destroy(struct alq *alq)
alq_shutdown(alq);
mtx_destroy(&alq->aq_mtx);
free(alq->aq_entbuf, M_ALD);
free(alq, M_ALD);
alq_doio(struct alq *alq)
KASSERT((HAS_PENDING_DATA(alq)), ("%s: queue empty!", __func__));
vp = alq->aq_vp;
wrapearly = alq->aq_wrapearly;
aiov[0].iov_base = alq->aq_entbuf + alq->aq_writetail;
if (alq->aq_writetail < alq->aq_writehead) {
totlen = aiov[0].iov_len = alq->aq_writehead - alq->aq_writetail;
} else if (alq->aq_writehead == 0) {
totlen = aiov[0].iov_len = alq->aq_buflen - alq->aq_writetail -
aiov[0].iov_len = alq->aq_buflen - alq->aq_writetail -
aiov[1].iov_base = alq->aq_entbuf;
aiov[1].iov_len = alq->aq_writehead;
alq->aq_flags |= AQ_FLUSHING;
ALQ_UNLOCK(alq);
if (mac_vnode_check_write(alq->aq_cred, NOCRED, vp) == 0)
VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, alq->aq_cred);
ALQ_LOCK(alq);
alq->aq_flags &= ~AQ_FLUSHING;
alq->aq_writetail = (alq->aq_writetail + totlen + wrapearly) %
alq->aq_buflen;
alq->aq_freebytes += totlen + wrapearly;
alq->aq_wrapearly = 0;
if (!HAS_PENDING_DATA(alq))
alq->aq_writehead = alq->aq_writetail = 0;
KASSERT((alq->aq_writetail >= 0 && alq->aq_writetail < alq->aq_buflen),
if (alq->aq_flags & AQ_WANTED) {
alq->aq_flags &= ~AQ_WANTED;
alq_open_flags(struct alq **alqp, const char *file, struct ucred *cred, int cmode,
struct alq *alq;
alq = malloc(sizeof(*alq), M_ALD, M_WAITOK|M_ZERO);
alq->aq_vp = nd.ni_vp;
alq->aq_cred = crhold(cred);
mtx_init(&alq->aq_mtx, "ALD Queue", NULL, MTX_SPIN|MTX_QUIET);
alq->aq_buflen = size;
alq->aq_entmax = 0;
alq->aq_entlen = 0;
alq->aq_freebytes = alq->aq_buflen;
alq->aq_entbuf = malloc(alq->aq_buflen, M_ALD, M_WAITOK|M_ZERO);
alq->aq_writehead = alq->aq_writetail = 0;
alq->aq_flags |= AQ_ORDERED;
if ((error = ald_add(alq)) != 0) {
alq_destroy(alq);
*alqp = alq;
alq_open(struct alq **alqp, const char *file, struct ucred *cred, int cmode,
alq_writen(struct alq *alq, void *data, int len, int flags)
KASSERT((len > 0 && len <= alq->aq_buflen),
ALQ_LOCK(alq);
if (len > alq->aq_buflen ||
alq->aq_flags & AQ_SHUTDOWN ||
(((flags & ALQ_NOWAIT) || (!(alq->aq_flags & AQ_ACTIVE) &&
HAS_PENDING_DATA(alq))) && alq->aq_freebytes < len)) {
ALQ_UNLOCK(alq);
if (alq->aq_flags & AQ_ORDERED && alq->aq_waiters > 0) {
alq->aq_waiters++;
msleep_spin(&alq->aq_waiters, &alq->aq_mtx, "alqwnord", 0);
alq->aq_waiters--;
while (alq->aq_freebytes < len && !(alq->aq_flags & AQ_SHUTDOWN)) {
alq->aq_flags |= AQ_WANTED;
alq->aq_waiters++;
msleep_spin(alq, &alq->aq_mtx, "alqwnres", 0);
alq->aq_waiters--;
if (alq->aq_waiters > 0 && !(alq->aq_flags & AQ_ORDERED) &&
alq->aq_freebytes < len && !(alq->aq_flags & AQ_WANTED))
waitchan = alq;
if (alq->aq_waiters > 0) {
if (alq->aq_flags & AQ_ORDERED)
waitchan = &alq->aq_waiters;
waitchan = alq;
if (alq->aq_flags & AQ_SHUTDOWN) {
if ((alq->aq_buflen - alq->aq_writehead) < len)
copy = alq->aq_buflen - alq->aq_writehead;
bcopy(data, alq->aq_entbuf + alq->aq_writehead, copy);
alq->aq_writehead += copy;
if (alq->aq_writehead >= alq->aq_buflen) {
KASSERT((alq->aq_writehead == alq->aq_buflen),
alq->aq_writehead,
alq->aq_buflen));
alq->aq_writehead = 0;
bcopy(((uint8_t *)data)+copy, alq->aq_entbuf, len - copy);
alq->aq_writehead = len - copy;
KASSERT((alq->aq_writehead >= 0 && alq->aq_writehead < alq->aq_buflen),
alq->aq_freebytes -= len;
if (!(alq->aq_flags & AQ_ACTIVE) && !(flags & ALQ_NOACTIVATE)) {
alq->aq_flags |= AQ_ACTIVE;
KASSERT((HAS_PENDING_DATA(alq)), ("%s: queue empty!", __func__));
ALQ_UNLOCK(alq);
ald_activate(alq);
alq_write(struct alq *alq, void *data, int flags)
KASSERT((alq->aq_flags & AQ_LEGACY),
return (alq_writen(alq, data, alq->aq_entlen, flags));
alq_getn(struct alq *alq, int len, int flags)
KASSERT((len > 0 && len <= alq->aq_buflen),
ALQ_LOCK(alq);
if (alq->aq_writehead <= alq->aq_writetail)
contigbytes = alq->aq_freebytes;
contigbytes = alq->aq_buflen - alq->aq_writehead;
if (alq->aq_writetail >= len || flags & ALQ_WAITOK) {
alq->aq_wrapearly = contigbytes;
contigbytes = alq->aq_freebytes =
alq->aq_writetail;
alq->aq_writehead = 0;
if (len > alq->aq_buflen ||
alq->aq_flags & AQ_SHUTDOWN ||
(((flags & ALQ_NOWAIT) || (!(alq->aq_flags & AQ_ACTIVE) &&
HAS_PENDING_DATA(alq))) && contigbytes < len)) {
ALQ_UNLOCK(alq);
if (alq->aq_flags & AQ_ORDERED && alq->aq_waiters > 0) {
alq->aq_waiters++;
msleep_spin(&alq->aq_waiters, &alq->aq_mtx, "alqgnord", 0);
alq->aq_waiters--;
while (contigbytes < len && !(alq->aq_flags & AQ_SHUTDOWN)) {
alq->aq_flags |= AQ_WANTED;
alq->aq_waiters++;
LIST_ENTRY(alq) aq_act; /* List of active queues */
msleep_spin(alq, &alq->aq_mtx, "alqgnres", 0);
alq->aq_waiters--;
if (alq->aq_writehead <= alq->aq_writetail)
contigbytes = alq->aq_freebytes;
contigbytes = alq->aq_buflen - alq->aq_writehead;
LIST_ENTRY(alq) aq_link; /* List of all queues */
if (alq->aq_waiters > 0 && !(alq->aq_flags & AQ_ORDERED) &&
contigbytes < len && !(alq->aq_flags & AQ_WANTED))
waitchan = alq;
if (alq->aq_waiters > 0) {
if (alq->aq_flags & AQ_ORDERED)
waitchan = &alq->aq_waiters;
waitchan = alq;
if (alq->aq_flags & AQ_SHUTDOWN) {
ALQ_UNLOCK(alq);
alq->aq_getpost.ae_data = alq->aq_entbuf + alq->aq_writehead;
alq->aq_getpost.ae_bytesused = len;
return (&alq->aq_getpost);
alq_get(struct alq *alq, int flags)
KASSERT((alq->aq_flags & AQ_LEGACY),
return (alq_getn(alq, alq->aq_entlen, flags));
alq_post_flags(struct alq *alq, struct ale *ale, int flags)
if (!(alq->aq_flags & AQ_ACTIVE) &&
alq->aq_flags |= AQ_ACTIVE;
alq->aq_writehead += ale->ae_bytesused;
alq->aq_freebytes -= ale->ae_bytesused;
if (alq->aq_writehead == alq->aq_buflen)
alq->aq_writehead = 0;
KASSERT((alq->aq_writehead >= 0 &&
alq->aq_writehead < alq->aq_buflen),
KASSERT((HAS_PENDING_DATA(alq)), ("%s: queue empty!", __func__));
if (alq->aq_waiters > 0) {
if (alq->aq_flags & AQ_ORDERED)
waitchan = &alq->aq_waiters;
waitchan = alq;
#define ALQ_LOCK(alq) mtx_lock_spin(&(alq)->aq_mtx)
ALQ_UNLOCK(alq);
ald_activate(alq);
#define ALQ_UNLOCK(alq) mtx_unlock_spin(&(alq)->aq_mtx)
alq_flush(struct alq *alq)
ALQ_LOCK(alq);
if (HAS_PENDING_DATA(alq) && !(alq->aq_flags & AQ_FLUSHING)) {
if (alq->aq_flags & AQ_ACTIVE)
ald_deactivate(alq);
#define HAS_PENDING_DATA(alq) ((alq)->aq_freebytes != (alq)->aq_buflen)
needwakeup = alq_doio(alq);
ALQ_UNLOCK(alq);
wakeup_one(alq);
alq_close(struct alq *alq)
if (ald_rem(alq) == 0)
alq_destroy(alq);
DECLARE_MODULE(alq, alq_mod, SI_SUB_LAST, SI_ORDER_ANY);
MODULE_VERSION(alq, 1);
static LIST_HEAD(, alq) ald_queues;
static LIST_HEAD(, alq) ald_active;
struct alq *ktr_alq;
SYSCTL_PROC(_net_wlan, OID_AUTO, alq,
static struct alq *ieee80211_alq;
MODULE_DEPEND(wlan, alq, 1, 1, 1);
struct alq *new_alq;
MODULE_DEPEND(siftr, alq, 1, 1, 1);
static struct alq *siftr_alq = NULL;
int alq_write(struct alq *alq, void *data, int flags);
void alq_flush(struct alq *alq);
void alq_close(struct alq *alq);
struct ale *alq_getn(struct alq *alq, int len, int flags);
struct ale *alq_get(struct alq *alq, int flags);
void alq_post_flags(struct alq *alq, struct ale *ale, int flags);
alq_post(struct alq *alq, struct ale *ale)
alq_post_flags(alq, ale, 0);
struct alq;
int alq_open_flags(struct alq **alqp, const char *file, struct ucred *cred, int cmode,
int alq_open(struct alq **alqp, const char *file, struct ucred *cred, int cmode,
int alq_writen(struct alq *alq, void *data, int len, int flags);