if_ath_alq.c revision 242781
1242781Sadrian/*- 2242781Sadrian * Copyright (c) 2012 Adrian Chadd 3242781Sadrian * All rights reserved. 4242781Sadrian * 5242781Sadrian * Redistribution and use in source and binary forms, with or without 6242781Sadrian * modification, are permitted provided that the following conditions 7242781Sadrian * are met: 8242781Sadrian * 1. Redistributions of source code must retain the above copyright 9242781Sadrian * notice, this list of conditions and the following disclaimer, 10242781Sadrian * without modification. 11242781Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12242781Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13242781Sadrian * redistribution must be conditioned upon including a substantially 14242781Sadrian * similar Disclaimer requirement for further binary redistribution. 15242781Sadrian * 16242781Sadrian * NO WARRANTY 17242781Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18242781Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19242781Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20242781Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21242781Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22242781Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23242781Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24242781Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25242781Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26242781Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27242781Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28242781Sadrian * 29242781Sadrian * $FreeBSD: head/sys/dev/ath/if_ath_alq.c 242781 2012-11-08 18:07:29Z adrian $ 30242781Sadrian */ 31242781Sadrian#include "opt_ah.h" 32242781Sadrian#include "opt_ath.h" 33242781Sadrian 34242781Sadrian#include <sys/param.h> 35242781Sadrian#include <sys/systm.h> 36242781Sadrian#include <sys/kernel.h> 37242781Sadrian#include <sys/module.h> 38242781Sadrian#include <sys/sysctl.h> 39242781Sadrian#include <sys/bus.h> 40242781Sadrian#include <sys/malloc.h> 41242781Sadrian#include <sys/proc.h> 42242781Sadrian#include <sys/pcpu.h> 43242781Sadrian#include <sys/lock.h> 44242781Sadrian#include <sys/mutex.h> 45242781Sadrian#include <sys/alq.h> 46242781Sadrian 47242781Sadrian#include <dev/ath/if_ath_alq.h> 48242781Sadrian 49242781Sadrian#ifdef ATH_DEBUG_ALQ 50242781Sadrianstatic struct ale * 51242781Sadrianif_ath_alq_get(struct if_ath_alq *alq, int len) 52242781Sadrian{ 53242781Sadrian struct ale *ale; 54242781Sadrian 55242781Sadrian if (alq->sc_alq_isactive == 0) 56242781Sadrian return (NULL); 57242781Sadrian 58242781Sadrian ale = alq_getn(alq->sc_alq_alq, len, ALQ_NOWAIT); 59242781Sadrian if (! ale) 60242781Sadrian alq->sc_alq_numlost++; 61242781Sadrian return (ale); 62242781Sadrian} 63242781Sadrian 64242781Sadrianvoid 65242781Sadrianif_ath_alq_init(struct if_ath_alq *alq, const char *devname) 66242781Sadrian{ 67242781Sadrian 68242781Sadrian bzero(alq, sizeof(*alq)); 69242781Sadrian 70242781Sadrian strncpy(alq->sc_alq_devname, devname, ATH_ALQ_DEVNAME_LEN); 71242781Sadrian printf("%s (%s): detached\n", __func__, alq->sc_alq_devname); 72242781Sadrian snprintf(alq->sc_alq_filename, ATH_ALQ_FILENAME_LEN, 73242781Sadrian "/tmp/ath_%s_alq.log", alq->sc_alq_devname); 74242781Sadrian 75242781Sadrian /* XXX too conservative, right? */ 76242781Sadrian alq->sc_alq_qsize = (64*1024); 77242781Sadrian} 78242781Sadrian 79242781Sadrianvoid 80242781Sadrianif_ath_alq_tidyup(struct if_ath_alq *alq) 81242781Sadrian{ 82242781Sadrian 83242781Sadrian if_ath_alq_stop(alq); 84242781Sadrian printf("%s (%s): detached\n", __func__, alq->sc_alq_devname); 85242781Sadrian bzero(alq, sizeof(*alq)); 86242781Sadrian} 87242781Sadrian 88242781Sadrianint 89242781Sadrianif_ath_alq_start(struct if_ath_alq *alq) 90242781Sadrian{ 91242781Sadrian int error; 92242781Sadrian 93242781Sadrian if (alq->sc_alq_isactive) 94242781Sadrian return (0); 95242781Sadrian 96242781Sadrian /* 97242781Sadrian * Create a variable-length ALQ. 98242781Sadrian */ 99242781Sadrian error = alq_open(&alq->sc_alq_alq, alq->sc_alq_filename, 100242781Sadrian curthread->td_ucred, ALQ_DEFAULT_CMODE, 101242781Sadrian alq->sc_alq_qsize, 0); 102242781Sadrian 103242781Sadrian if (error != 0) { 104242781Sadrian printf("%s (%s): failed, err=%d\n", __func__, 105242781Sadrian alq->sc_alq_devname, error); 106242781Sadrian } else { 107242781Sadrian printf("%s (%s): opened\n", __func__, alq->sc_alq_devname); 108242781Sadrian alq->sc_alq_isactive = 1; 109242781Sadrian } 110242781Sadrian return (error); 111242781Sadrian} 112242781Sadrian 113242781Sadrianint 114242781Sadrianif_ath_alq_stop(struct if_ath_alq *alq) 115242781Sadrian{ 116242781Sadrian 117242781Sadrian if (alq->sc_alq_isactive == 0) 118242781Sadrian return (0); 119242781Sadrian 120242781Sadrian printf("%s (%s): closed\n", __func__, alq->sc_alq_devname); 121242781Sadrian 122242781Sadrian alq->sc_alq_isactive = 0; 123242781Sadrian alq_close(alq->sc_alq_alq); 124242781Sadrian alq->sc_alq_alq = NULL; 125242781Sadrian 126242781Sadrian return (0); 127242781Sadrian} 128242781Sadrian 129242781Sadrian/* 130242781Sadrian * Post a debug message to the ALQ. 131242781Sadrian * 132242781Sadrian * "len" is the size of the buf payload in bytes. 133242781Sadrian */ 134242781Sadrianvoid 135242781Sadrianif_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len, 136242781Sadrian const char *buf) 137242781Sadrian{ 138242781Sadrian struct if_ath_alq_hdr *ap; 139242781Sadrian struct ale *ale; 140242781Sadrian 141242781Sadrian if (! if_ath_alq_checkdebug(alq, op)) 142242781Sadrian return; 143242781Sadrian 144242781Sadrian /* 145242781Sadrian * Enforce some semblence of sanity on 'len'. 146242781Sadrian * Although strictly speaking, any length is possible - 147242781Sadrian * just be conservative so things don't get out of hand. 148242781Sadrian */ 149242781Sadrian if (len > ATH_ALQ_PAYLOAD_LEN) 150242781Sadrian len = ATH_ALQ_PAYLOAD_LEN; 151242781Sadrian 152242781Sadrian ale = if_ath_alq_get(alq, len + sizeof(struct if_ath_alq_hdr)); 153242781Sadrian 154242781Sadrian if (ale == NULL) 155242781Sadrian return; 156242781Sadrian 157242781Sadrian ap = (struct if_ath_alq_hdr *) ale->ae_data; 158242781Sadrian ap->threadid = (uint64_t) curthread->td_tid; 159242781Sadrian ap->tstamp = (uint32_t) ticks; 160242781Sadrian ap->op = op; 161242781Sadrian ap->len = len; 162242781Sadrian 163242781Sadrian /* 164242781Sadrian * Copy the payload _after_ the header field. 165242781Sadrian */ 166242781Sadrian memcpy(((char *) ap) + sizeof(struct if_ath_alq_hdr), 167242781Sadrian buf, 168242781Sadrian ap->len); 169242781Sadrian 170242781Sadrian alq_post(alq->sc_alq_alq, ale); 171242781Sadrian} 172242781Sadrian#endif /* ATH_DEBUG */ 173