Author: adrian
Date: Thu Nov  8 18:07:29 2012
New Revision: 242781
URL: http://svnweb.freebsd.org/changeset/base/242781

Log:
  Add my initial cut at driver-layer ALQ support.
  
  I'm using this to debug EDMA TX and RX descriptors and it's really helpful
  to have a non-printf() way to decode frames.
  
  I won't link this into the build until I've tidied it up a little more.
  
  This will eventually be behind ATH_DEBUG_ALQ.

Added:
  head/sys/dev/ath/if_ath_alq.c   (contents, props changed)
  head/sys/dev/ath/if_ath_alq.h   (contents, props changed)

Added: head/sys/dev/ath/if_ath_alq.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/ath/if_ath_alq.c       Thu Nov  8 18:07:29 2012        
(r242781)
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 2012 Adrian Chadd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#include "opt_ah.h"
+#include "opt_ath.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/pcpu.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/alq.h>
+
+#include <dev/ath/if_ath_alq.h>
+
+#ifdef ATH_DEBUG_ALQ
+static struct ale *
+if_ath_alq_get(struct if_ath_alq *alq, int len)
+{
+       struct ale *ale;
+
+       if (alq->sc_alq_isactive == 0)
+               return (NULL);
+
+       ale = alq_getn(alq->sc_alq_alq, len, ALQ_NOWAIT);
+       if (! ale)
+               alq->sc_alq_numlost++;
+       return (ale);
+}
+
+void
+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): detached\n", __func__, alq->sc_alq_devname);
+       snprintf(alq->sc_alq_filename, ATH_ALQ_FILENAME_LEN,
+           "/tmp/ath_%s_alq.log", alq->sc_alq_devname);
+
+       /* XXX too conservative, right? */
+       alq->sc_alq_qsize = (64*1024);
+}
+
+void
+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));
+}
+
+int
+if_ath_alq_start(struct if_ath_alq *alq)
+{
+       int error;
+
+       if (alq->sc_alq_isactive)
+               return (0);
+
+       /*
+        * Create a variable-length ALQ.
+        */
+       error = alq_open(&alq->sc_alq_alq, alq->sc_alq_filename,
+           curthread->td_ucred, ALQ_DEFAULT_CMODE,
+           alq->sc_alq_qsize, 0);
+
+       if (error != 0) {
+               printf("%s (%s): failed, err=%d\n", __func__,
+                   alq->sc_alq_devname, error);
+       } else {
+               printf("%s (%s): opened\n", __func__, alq->sc_alq_devname);
+               alq->sc_alq_isactive = 1;
+       }
+       return (error);
+}
+
+int
+if_ath_alq_stop(struct if_ath_alq *alq)
+{
+
+       if (alq->sc_alq_isactive == 0)
+               return (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;
+
+       return (0);
+}
+
+/*
+ * Post a debug message to the ALQ.
+ *
+ * "len" is the size of the buf payload in bytes.
+ */
+void
+if_ath_alq_post(struct if_ath_alq *alq, uint16_t op, uint16_t len,
+    const char *buf)
+{
+       struct if_ath_alq_hdr *ap;
+       struct ale *ale;
+
+       if (! if_ath_alq_checkdebug(alq, op))
+               return;
+
+       /*
+        * Enforce some semblence of sanity on 'len'.
+        * Although strictly speaking, any length is possible -
+        * just be conservative so things don't get out of hand.
+        */
+       if (len > ATH_ALQ_PAYLOAD_LEN)
+               len = ATH_ALQ_PAYLOAD_LEN;
+
+       ale = if_ath_alq_get(alq, len + sizeof(struct if_ath_alq_hdr));
+
+       if (ale == NULL)
+               return;
+
+       ap = (struct if_ath_alq_hdr *) ale->ae_data;
+       ap->threadid = (uint64_t) curthread->td_tid;
+       ap->tstamp = (uint32_t) ticks;
+       ap->op = op;
+       ap->len = len;
+
+       /*
+        * Copy the payload _after_ the header field.
+        */
+       memcpy(((char *) ap) + sizeof(struct if_ath_alq_hdr),
+           buf,
+           ap->len);
+
+       alq_post(alq->sc_alq_alq, ale);
+}
+#endif /* ATH_DEBUG */

Added: head/sys/dev/ath/if_ath_alq.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/dev/ath/if_ath_alq.h       Thu Nov  8 18:07:29 2012        
(r242781)
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2012 Adrian Chadd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#ifndef        __IF_ATH_ALQ_H__
+#define        __IF_ATH_ALQ_H__
+
+#define        ATH_ALQ_FILENAME_LEN    128
+#define        ATH_ALQ_DEVNAME_LEN     32
+
+struct if_ath_alq {
+       uint32_t        sc_alq_debug;           /* Debug flags to report */
+       struct alq *    sc_alq_alq;             /* alq state */
+       unsigned int    sc_alq_qsize;           /* queue size */
+       unsigned int    sc_alq_numlost;         /* number of "lost" entries */
+       int             sc_alq_isactive;
+       char            sc_alq_devname[ATH_ALQ_DEVNAME_LEN];
+       char            sc_alq_filename[ATH_ALQ_FILENAME_LEN];
+};
+
+#define        ATH_ALQ_EDMA_TXSTATUS           1
+#define        ATH_ALQ_EDMA_RXSTATUS           2
+#define        ATH_ALQ_EDMA_TXDESC             3
+
+/* 128 bytes in total */
+#define        ATH_ALQ_PAYLOAD_LEN             112
+
+struct if_ath_alq_hdr {
+       uint64_t        threadid;
+       uint32_t        tstamp;
+       uint16_t        op;
+       uint16_t        len;    /* Length of (optional) payload */
+};
+
+struct if_ath_alq_payload {
+       struct if_ath_alq_hdr hdr;
+       char            payload[];
+};
+
+#ifdef _KERNEL
+static inline int
+if_ath_alq_checkdebug(struct if_ath_alq *alq, uint16_t op)
+{
+
+       return (alq->sc_alq_debug & (1 << (op - 1)));
+}
+
+extern void if_ath_alq_init(struct if_ath_alq *alq, const char *devname);
+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,
+           uint16_t len, const char *buf);
+#endif /* _KERNEL */
+
+#endif
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to