xref: /freebsd/sys/dev/ath/if_ath_alq.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
12a2441c9SAdrian Chadd /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
42a2441c9SAdrian Chadd  * Copyright (c) 2012 Adrian Chadd
52a2441c9SAdrian Chadd  * All rights reserved.
62a2441c9SAdrian Chadd  *
72a2441c9SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
82a2441c9SAdrian Chadd  * modification, are permitted provided that the following conditions
92a2441c9SAdrian Chadd  * are met:
102a2441c9SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
112a2441c9SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
122a2441c9SAdrian Chadd  *    without modification.
132a2441c9SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
142a2441c9SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
152a2441c9SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
162a2441c9SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
172a2441c9SAdrian Chadd  *
182a2441c9SAdrian Chadd  * NO WARRANTY
192a2441c9SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
202a2441c9SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
212a2441c9SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
222a2441c9SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
232a2441c9SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
242a2441c9SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
252a2441c9SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
262a2441c9SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
272a2441c9SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
282a2441c9SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
292a2441c9SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
302a2441c9SAdrian Chadd  */
312a2441c9SAdrian Chadd #include "opt_ah.h"
322a2441c9SAdrian Chadd #include "opt_ath.h"
332a2441c9SAdrian Chadd 
342a2441c9SAdrian Chadd #include <sys/param.h>
352a2441c9SAdrian Chadd #include <sys/systm.h>
362a2441c9SAdrian Chadd #include <sys/kernel.h>
372a2441c9SAdrian Chadd #include <sys/module.h>
382a2441c9SAdrian Chadd #include <sys/sysctl.h>
392a2441c9SAdrian Chadd #include <sys/bus.h>
402a2441c9SAdrian Chadd #include <sys/malloc.h>
412a2441c9SAdrian Chadd #include <sys/proc.h>
422a2441c9SAdrian Chadd #include <sys/pcpu.h>
432a2441c9SAdrian Chadd #include <sys/lock.h>
442a2441c9SAdrian Chadd #include <sys/mutex.h>
452a2441c9SAdrian Chadd #include <sys/alq.h>
46956d4fb9SAdrian Chadd #include <sys/endian.h>
4781561d04SAdrian Chadd #include <sys/time.h>
482a2441c9SAdrian Chadd 
492a2441c9SAdrian Chadd #include <dev/ath/if_ath_alq.h>
502a2441c9SAdrian Chadd 
512a2441c9SAdrian Chadd #ifdef	ATH_DEBUG_ALQ
522a2441c9SAdrian Chadd static struct ale *
if_ath_alq_get(struct if_ath_alq * alq,int len)532a2441c9SAdrian Chadd if_ath_alq_get(struct if_ath_alq *alq, int len)
542a2441c9SAdrian Chadd {
552a2441c9SAdrian Chadd 	struct ale *ale;
562a2441c9SAdrian Chadd 
572a2441c9SAdrian Chadd 	if (alq->sc_alq_isactive == 0)
582a2441c9SAdrian Chadd 		return (NULL);
592a2441c9SAdrian Chadd 
602a2441c9SAdrian Chadd 	ale = alq_getn(alq->sc_alq_alq, len, ALQ_NOWAIT);
612a2441c9SAdrian Chadd 	if (! ale)
622a2441c9SAdrian Chadd 		alq->sc_alq_numlost++;
632a2441c9SAdrian Chadd 	return (ale);
642a2441c9SAdrian Chadd }
652a2441c9SAdrian Chadd 
662a2441c9SAdrian Chadd void
if_ath_alq_init(struct if_ath_alq * alq,const char * devname)672a2441c9SAdrian Chadd if_ath_alq_init(struct if_ath_alq *alq, const char *devname)
682a2441c9SAdrian Chadd {
692a2441c9SAdrian Chadd 
702a2441c9SAdrian Chadd 	bzero(alq, sizeof(*alq));
712a2441c9SAdrian Chadd 
722a2441c9SAdrian Chadd 	strncpy(alq->sc_alq_devname, devname, ATH_ALQ_DEVNAME_LEN);
73a64438faSAdrian Chadd 	printf("%s (%s): attached\n", __func__, alq->sc_alq_devname);
742a2441c9SAdrian Chadd 	snprintf(alq->sc_alq_filename, ATH_ALQ_FILENAME_LEN,
752a2441c9SAdrian Chadd 	    "/tmp/ath_%s_alq.log", alq->sc_alq_devname);
762a2441c9SAdrian Chadd 
772a2441c9SAdrian Chadd 	/* XXX too conservative, right? */
782a2441c9SAdrian Chadd 	alq->sc_alq_qsize = (64*1024);
792a2441c9SAdrian Chadd }
802a2441c9SAdrian Chadd 
812a2441c9SAdrian Chadd void
if_ath_alq_setcfg(struct if_ath_alq * alq,uint32_t macVer,uint32_t macRev,uint32_t phyRev,uint32_t halMagic)82956d4fb9SAdrian Chadd if_ath_alq_setcfg(struct if_ath_alq *alq, uint32_t macVer,
83956d4fb9SAdrian Chadd     uint32_t macRev, uint32_t phyRev, uint32_t halMagic)
84956d4fb9SAdrian Chadd {
85956d4fb9SAdrian Chadd 
86956d4fb9SAdrian Chadd 	/* Store these in network order */
87956d4fb9SAdrian Chadd 	alq->sc_alq_cfg.sc_mac_version = htobe32(macVer);
88956d4fb9SAdrian Chadd 	alq->sc_alq_cfg.sc_mac_revision = htobe32(macRev);
89956d4fb9SAdrian Chadd 	alq->sc_alq_cfg.sc_phy_rev = htobe32(phyRev);
90956d4fb9SAdrian Chadd 	alq->sc_alq_cfg.sc_hal_magic = htobe32(halMagic);
91956d4fb9SAdrian Chadd }
92956d4fb9SAdrian Chadd 
93956d4fb9SAdrian Chadd void
if_ath_alq_tidyup(struct if_ath_alq * alq)942a2441c9SAdrian Chadd if_ath_alq_tidyup(struct if_ath_alq *alq)
952a2441c9SAdrian Chadd {
962a2441c9SAdrian Chadd 
972a2441c9SAdrian Chadd 	if_ath_alq_stop(alq);
982a2441c9SAdrian Chadd 	printf("%s (%s): detached\n", __func__, alq->sc_alq_devname);
992a2441c9SAdrian Chadd 	bzero(alq, sizeof(*alq));
1002a2441c9SAdrian Chadd }
1012a2441c9SAdrian Chadd 
1022a2441c9SAdrian Chadd int
if_ath_alq_start(struct if_ath_alq * alq)1032a2441c9SAdrian Chadd if_ath_alq_start(struct if_ath_alq *alq)
1042a2441c9SAdrian Chadd {
1052a2441c9SAdrian Chadd 	int error;
1062a2441c9SAdrian Chadd 
1072a2441c9SAdrian Chadd 	if (alq->sc_alq_isactive)
1082a2441c9SAdrian Chadd 		return (0);
1092a2441c9SAdrian Chadd 
1102a2441c9SAdrian Chadd 	/*
1112a2441c9SAdrian Chadd 	 * Create a variable-length ALQ.
1122a2441c9SAdrian Chadd 	 */
1132a2441c9SAdrian Chadd 	error = alq_open(&alq->sc_alq_alq, alq->sc_alq_filename,
1142a2441c9SAdrian Chadd 	    curthread->td_ucred, ALQ_DEFAULT_CMODE,
1152a2441c9SAdrian Chadd 	    alq->sc_alq_qsize, 0);
1162a2441c9SAdrian Chadd 
1172a2441c9SAdrian Chadd 	if (error != 0) {
1182a2441c9SAdrian Chadd 		printf("%s (%s): failed, err=%d\n", __func__,
1192a2441c9SAdrian Chadd 		    alq->sc_alq_devname, error);
1202a2441c9SAdrian Chadd 	} else {
1212a2441c9SAdrian Chadd 		printf("%s (%s): opened\n", __func__, alq->sc_alq_devname);
1222a2441c9SAdrian Chadd 		alq->sc_alq_isactive = 1;
123956d4fb9SAdrian Chadd 		if_ath_alq_post(alq, ATH_ALQ_INIT_STATE,
124956d4fb9SAdrian Chadd 		    sizeof (struct if_ath_alq_init_state),
125956d4fb9SAdrian Chadd 		    (char *) &alq->sc_alq_cfg);
1262a2441c9SAdrian Chadd 	}
1272a2441c9SAdrian Chadd 	return (error);
1282a2441c9SAdrian Chadd }
1292a2441c9SAdrian Chadd 
1302a2441c9SAdrian Chadd int
if_ath_alq_stop(struct if_ath_alq * alq)1312a2441c9SAdrian Chadd if_ath_alq_stop(struct if_ath_alq *alq)
1322a2441c9SAdrian Chadd {
1332a2441c9SAdrian Chadd 
1342a2441c9SAdrian Chadd 	if (alq->sc_alq_isactive == 0)
1352a2441c9SAdrian Chadd 		return (0);
1362a2441c9SAdrian Chadd 
1372a2441c9SAdrian Chadd 	printf("%s (%s): closed\n", __func__, alq->sc_alq_devname);
1382a2441c9SAdrian Chadd 
1392a2441c9SAdrian Chadd 	alq->sc_alq_isactive = 0;
1402a2441c9SAdrian Chadd 	alq_close(alq->sc_alq_alq);
1412a2441c9SAdrian Chadd 	alq->sc_alq_alq = NULL;
1422a2441c9SAdrian Chadd 
1432a2441c9SAdrian Chadd 	return (0);
1442a2441c9SAdrian Chadd }
1452a2441c9SAdrian Chadd 
1462a2441c9SAdrian Chadd /*
1472a2441c9SAdrian Chadd  * Post a debug message to the ALQ.
1482a2441c9SAdrian Chadd  *
1492a2441c9SAdrian Chadd  * "len" is the size of the buf payload in bytes.
1502a2441c9SAdrian Chadd  */
1512a2441c9SAdrian Chadd void
if_ath_alq_post(struct if_ath_alq * alq,uint16_t op,uint16_t len,const char * buf)1522a2441c9SAdrian Chadd if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len,
1532a2441c9SAdrian Chadd     const char *buf)
1542a2441c9SAdrian Chadd {
1552a2441c9SAdrian Chadd 	struct if_ath_alq_hdr *ap;
1562a2441c9SAdrian Chadd 	struct ale *ale;
15781561d04SAdrian Chadd 	struct timeval tv;
1582a2441c9SAdrian Chadd 
1592a2441c9SAdrian Chadd 	if (! if_ath_alq_checkdebug(alq, op))
1602a2441c9SAdrian Chadd 		return;
1612a2441c9SAdrian Chadd 
16281561d04SAdrian Chadd 	microtime(&tv);
16381561d04SAdrian Chadd 
1642a2441c9SAdrian Chadd 	/*
1652a2441c9SAdrian Chadd 	 * Enforce some semblence of sanity on 'len'.
1662a2441c9SAdrian Chadd 	 * Although strictly speaking, any length is possible -
1672a2441c9SAdrian Chadd 	 * just be conservative so things don't get out of hand.
1682a2441c9SAdrian Chadd 	 */
1692a2441c9SAdrian Chadd 	if (len > ATH_ALQ_PAYLOAD_LEN)
1702a2441c9SAdrian Chadd 		len = ATH_ALQ_PAYLOAD_LEN;
1712a2441c9SAdrian Chadd 
1722a2441c9SAdrian Chadd 	ale = if_ath_alq_get(alq, len + sizeof(struct if_ath_alq_hdr));
1732a2441c9SAdrian Chadd 
1742a2441c9SAdrian Chadd 	if (ale == NULL)
1752a2441c9SAdrian Chadd 		return;
1762a2441c9SAdrian Chadd 
1772a2441c9SAdrian Chadd 	ap = (struct if_ath_alq_hdr *) ale->ae_data;
178956d4fb9SAdrian Chadd 	ap->threadid = htobe64((uint64_t) curthread->td_tid);
17981561d04SAdrian Chadd 	ap->tstamp_sec = htobe32((uint32_t) tv.tv_sec);
18081561d04SAdrian Chadd 	ap->tstamp_usec = htobe32((uint32_t) tv.tv_usec);
181956d4fb9SAdrian Chadd 	ap->op = htobe16(op);
182956d4fb9SAdrian Chadd 	ap->len = htobe16(len);
1832a2441c9SAdrian Chadd 
1842a2441c9SAdrian Chadd 	/*
1852a2441c9SAdrian Chadd 	 * Copy the payload _after_ the header field.
1862a2441c9SAdrian Chadd 	 */
1875086df9fSAdrian Chadd 	if (buf != NULL) {
1882a2441c9SAdrian Chadd 		memcpy(((char *) ap) + sizeof(struct if_ath_alq_hdr),
1892a2441c9SAdrian Chadd 		    buf,
190956d4fb9SAdrian Chadd 		    len);
1915086df9fSAdrian Chadd 	}
1922a2441c9SAdrian Chadd 
1932a2441c9SAdrian Chadd 	alq_post(alq->sc_alq_alq, ale);
1942a2441c9SAdrian Chadd }
1952a2441c9SAdrian Chadd #endif	/* ATH_DEBUG */
196