1*2a2441c9SAdrian Chadd /*- 2*2a2441c9SAdrian Chadd * Copyright (c) 2012 Adrian Chadd 3*2a2441c9SAdrian Chadd * All rights reserved. 4*2a2441c9SAdrian Chadd * 5*2a2441c9SAdrian Chadd * Redistribution and use in source and binary forms, with or without 6*2a2441c9SAdrian Chadd * modification, are permitted provided that the following conditions 7*2a2441c9SAdrian Chadd * are met: 8*2a2441c9SAdrian Chadd * 1. Redistributions of source code must retain the above copyright 9*2a2441c9SAdrian Chadd * notice, this list of conditions and the following disclaimer, 10*2a2441c9SAdrian Chadd * without modification. 11*2a2441c9SAdrian Chadd * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12*2a2441c9SAdrian Chadd * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13*2a2441c9SAdrian Chadd * redistribution must be conditioned upon including a substantially 14*2a2441c9SAdrian Chadd * similar Disclaimer requirement for further binary redistribution. 15*2a2441c9SAdrian Chadd * 16*2a2441c9SAdrian Chadd * NO WARRANTY 17*2a2441c9SAdrian Chadd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*2a2441c9SAdrian Chadd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*2a2441c9SAdrian Chadd * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20*2a2441c9SAdrian Chadd * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21*2a2441c9SAdrian Chadd * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22*2a2441c9SAdrian Chadd * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23*2a2441c9SAdrian Chadd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*2a2441c9SAdrian Chadd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*2a2441c9SAdrian Chadd * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26*2a2441c9SAdrian Chadd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27*2a2441c9SAdrian Chadd * THE POSSIBILITY OF SUCH DAMAGES. 28*2a2441c9SAdrian Chadd * 29*2a2441c9SAdrian Chadd * $FreeBSD$ 30*2a2441c9SAdrian Chadd */ 31*2a2441c9SAdrian Chadd #include "opt_ah.h" 32*2a2441c9SAdrian Chadd #include "opt_ath.h" 33*2a2441c9SAdrian Chadd 34*2a2441c9SAdrian Chadd #include <sys/param.h> 35*2a2441c9SAdrian Chadd #include <sys/systm.h> 36*2a2441c9SAdrian Chadd #include <sys/kernel.h> 37*2a2441c9SAdrian Chadd #include <sys/module.h> 38*2a2441c9SAdrian Chadd #include <sys/sysctl.h> 39*2a2441c9SAdrian Chadd #include <sys/bus.h> 40*2a2441c9SAdrian Chadd #include <sys/malloc.h> 41*2a2441c9SAdrian Chadd #include <sys/proc.h> 42*2a2441c9SAdrian Chadd #include <sys/pcpu.h> 43*2a2441c9SAdrian Chadd #include <sys/lock.h> 44*2a2441c9SAdrian Chadd #include <sys/mutex.h> 45*2a2441c9SAdrian Chadd #include <sys/alq.h> 46*2a2441c9SAdrian Chadd 47*2a2441c9SAdrian Chadd #include <dev/ath/if_ath_alq.h> 48*2a2441c9SAdrian Chadd 49*2a2441c9SAdrian Chadd #ifdef ATH_DEBUG_ALQ 50*2a2441c9SAdrian Chadd static struct ale * 51*2a2441c9SAdrian Chadd if_ath_alq_get(struct if_ath_alq *alq, int len) 52*2a2441c9SAdrian Chadd { 53*2a2441c9SAdrian Chadd struct ale *ale; 54*2a2441c9SAdrian Chadd 55*2a2441c9SAdrian Chadd if (alq->sc_alq_isactive == 0) 56*2a2441c9SAdrian Chadd return (NULL); 57*2a2441c9SAdrian Chadd 58*2a2441c9SAdrian Chadd ale = alq_getn(alq->sc_alq_alq, len, ALQ_NOWAIT); 59*2a2441c9SAdrian Chadd if (! ale) 60*2a2441c9SAdrian Chadd alq->sc_alq_numlost++; 61*2a2441c9SAdrian Chadd return (ale); 62*2a2441c9SAdrian Chadd } 63*2a2441c9SAdrian Chadd 64*2a2441c9SAdrian Chadd void 65*2a2441c9SAdrian Chadd if_ath_alq_init(struct if_ath_alq *alq, const char *devname) 66*2a2441c9SAdrian Chadd { 67*2a2441c9SAdrian Chadd 68*2a2441c9SAdrian Chadd bzero(alq, sizeof(*alq)); 69*2a2441c9SAdrian Chadd 70*2a2441c9SAdrian Chadd strncpy(alq->sc_alq_devname, devname, ATH_ALQ_DEVNAME_LEN); 71*2a2441c9SAdrian Chadd printf("%s (%s): detached\n", __func__, alq->sc_alq_devname); 72*2a2441c9SAdrian Chadd snprintf(alq->sc_alq_filename, ATH_ALQ_FILENAME_LEN, 73*2a2441c9SAdrian Chadd "/tmp/ath_%s_alq.log", alq->sc_alq_devname); 74*2a2441c9SAdrian Chadd 75*2a2441c9SAdrian Chadd /* XXX too conservative, right? */ 76*2a2441c9SAdrian Chadd alq->sc_alq_qsize = (64*1024); 77*2a2441c9SAdrian Chadd } 78*2a2441c9SAdrian Chadd 79*2a2441c9SAdrian Chadd void 80*2a2441c9SAdrian Chadd if_ath_alq_tidyup(struct if_ath_alq *alq) 81*2a2441c9SAdrian Chadd { 82*2a2441c9SAdrian Chadd 83*2a2441c9SAdrian Chadd if_ath_alq_stop(alq); 84*2a2441c9SAdrian Chadd printf("%s (%s): detached\n", __func__, alq->sc_alq_devname); 85*2a2441c9SAdrian Chadd bzero(alq, sizeof(*alq)); 86*2a2441c9SAdrian Chadd } 87*2a2441c9SAdrian Chadd 88*2a2441c9SAdrian Chadd int 89*2a2441c9SAdrian Chadd if_ath_alq_start(struct if_ath_alq *alq) 90*2a2441c9SAdrian Chadd { 91*2a2441c9SAdrian Chadd int error; 92*2a2441c9SAdrian Chadd 93*2a2441c9SAdrian Chadd if (alq->sc_alq_isactive) 94*2a2441c9SAdrian Chadd return (0); 95*2a2441c9SAdrian Chadd 96*2a2441c9SAdrian Chadd /* 97*2a2441c9SAdrian Chadd * Create a variable-length ALQ. 98*2a2441c9SAdrian Chadd */ 99*2a2441c9SAdrian Chadd error = alq_open(&alq->sc_alq_alq, alq->sc_alq_filename, 100*2a2441c9SAdrian Chadd curthread->td_ucred, ALQ_DEFAULT_CMODE, 101*2a2441c9SAdrian Chadd alq->sc_alq_qsize, 0); 102*2a2441c9SAdrian Chadd 103*2a2441c9SAdrian Chadd if (error != 0) { 104*2a2441c9SAdrian Chadd printf("%s (%s): failed, err=%d\n", __func__, 105*2a2441c9SAdrian Chadd alq->sc_alq_devname, error); 106*2a2441c9SAdrian Chadd } else { 107*2a2441c9SAdrian Chadd printf("%s (%s): opened\n", __func__, alq->sc_alq_devname); 108*2a2441c9SAdrian Chadd alq->sc_alq_isactive = 1; 109*2a2441c9SAdrian Chadd } 110*2a2441c9SAdrian Chadd return (error); 111*2a2441c9SAdrian Chadd } 112*2a2441c9SAdrian Chadd 113*2a2441c9SAdrian Chadd int 114*2a2441c9SAdrian Chadd if_ath_alq_stop(struct if_ath_alq *alq) 115*2a2441c9SAdrian Chadd { 116*2a2441c9SAdrian Chadd 117*2a2441c9SAdrian Chadd if (alq->sc_alq_isactive == 0) 118*2a2441c9SAdrian Chadd return (0); 119*2a2441c9SAdrian Chadd 120*2a2441c9SAdrian Chadd printf("%s (%s): closed\n", __func__, alq->sc_alq_devname); 121*2a2441c9SAdrian Chadd 122*2a2441c9SAdrian Chadd alq->sc_alq_isactive = 0; 123*2a2441c9SAdrian Chadd alq_close(alq->sc_alq_alq); 124*2a2441c9SAdrian Chadd alq->sc_alq_alq = NULL; 125*2a2441c9SAdrian Chadd 126*2a2441c9SAdrian Chadd return (0); 127*2a2441c9SAdrian Chadd } 128*2a2441c9SAdrian Chadd 129*2a2441c9SAdrian Chadd /* 130*2a2441c9SAdrian Chadd * Post a debug message to the ALQ. 131*2a2441c9SAdrian Chadd * 132*2a2441c9SAdrian Chadd * "len" is the size of the buf payload in bytes. 133*2a2441c9SAdrian Chadd */ 134*2a2441c9SAdrian Chadd void 135*2a2441c9SAdrian Chadd if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len, 136*2a2441c9SAdrian Chadd const char *buf) 137*2a2441c9SAdrian Chadd { 138*2a2441c9SAdrian Chadd struct if_ath_alq_hdr *ap; 139*2a2441c9SAdrian Chadd struct ale *ale; 140*2a2441c9SAdrian Chadd 141*2a2441c9SAdrian Chadd if (! if_ath_alq_checkdebug(alq, op)) 142*2a2441c9SAdrian Chadd return; 143*2a2441c9SAdrian Chadd 144*2a2441c9SAdrian Chadd /* 145*2a2441c9SAdrian Chadd * Enforce some semblence of sanity on 'len'. 146*2a2441c9SAdrian Chadd * Although strictly speaking, any length is possible - 147*2a2441c9SAdrian Chadd * just be conservative so things don't get out of hand. 148*2a2441c9SAdrian Chadd */ 149*2a2441c9SAdrian Chadd if (len > ATH_ALQ_PAYLOAD_LEN) 150*2a2441c9SAdrian Chadd len = ATH_ALQ_PAYLOAD_LEN; 151*2a2441c9SAdrian Chadd 152*2a2441c9SAdrian Chadd ale = if_ath_alq_get(alq, len + sizeof(struct if_ath_alq_hdr)); 153*2a2441c9SAdrian Chadd 154*2a2441c9SAdrian Chadd if (ale == NULL) 155*2a2441c9SAdrian Chadd return; 156*2a2441c9SAdrian Chadd 157*2a2441c9SAdrian Chadd ap = (struct if_ath_alq_hdr *) ale->ae_data; 158*2a2441c9SAdrian Chadd ap->threadid = (uint64_t) curthread->td_tid; 159*2a2441c9SAdrian Chadd ap->tstamp = (uint32_t) ticks; 160*2a2441c9SAdrian Chadd ap->op = op; 161*2a2441c9SAdrian Chadd ap->len = len; 162*2a2441c9SAdrian Chadd 163*2a2441c9SAdrian Chadd /* 164*2a2441c9SAdrian Chadd * Copy the payload _after_ the header field. 165*2a2441c9SAdrian Chadd */ 166*2a2441c9SAdrian Chadd memcpy(((char *) ap) + sizeof(struct if_ath_alq_hdr), 167*2a2441c9SAdrian Chadd buf, 168*2a2441c9SAdrian Chadd ap->len); 169*2a2441c9SAdrian Chadd 170*2a2441c9SAdrian Chadd alq_post(alq->sc_alq_alq, ale); 171*2a2441c9SAdrian Chadd } 172*2a2441c9SAdrian Chadd #endif /* ATH_DEBUG */ 173