The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_wlan.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/lock.h>
   34 #include <sys/mutex.h>
   35 #include <sys/mbuf.h>
   36 #include <sys/kernel.h>
   37 #include <sys/socket.h>
   38 #include <sys/systm.h>
   39 #include <sys/malloc.h>
   40 #include <sys/queue.h>
   41 #include <sys/taskqueue.h>
   42 #include <sys/bus.h>
   43 #include <sys/endian.h>
   44 #include <sys/linker.h>
   45 
   46 #include <net/if.h>
   47 #include <net/ethernet.h>
   48 #include <net/if_media.h>
   49 
   50 #include <net80211/ieee80211_var.h>
   51 #include <net80211/ieee80211_radiotap.h>
   52 
   53 #include <dev/rtwn/if_rtwnvar.h>
   54 #include <dev/rtwn/if_rtwn_debug.h>
   55 
   56 #include <dev/rtwn/usb/rtwn_usb_var.h>
   57 
   58 #include <dev/rtwn/rtl8812a/r12a_var.h>
   59 
   60 #include <dev/rtwn/rtl8821a/usb/r21au.h>
   61 #include <dev/rtwn/rtl8821a/usb/r21au_reg.h>
   62 
   63 #define R21AU_RADAR_CHECK_PERIOD        (2 * hz)
   64 
   65 static void
   66 r21au_dfs_radar_disable(struct rtwn_softc *sc)
   67 {
   68         rtwn_bb_setbits(sc, 0x924, 0x00008000, 0);
   69 }
   70 
   71 static int
   72 r21au_dfs_radar_is_enabled(struct rtwn_softc *sc)
   73 {
   74         return !!(rtwn_bb_read(sc, 0x924) & 0x00008000);
   75 }
   76 
   77 static int
   78 r21au_dfs_radar_reset(struct rtwn_softc *sc)
   79 {
   80         int error;
   81 
   82         error = rtwn_bb_setbits(sc, 0x924, 0x00008000, 0);
   83         if (error != 0)
   84                 return (error);
   85 
   86         return (rtwn_bb_setbits(sc, 0x924, 0, 0x00008000));
   87 }
   88 
   89 static int
   90 r21au_dfs_radar_enable(struct rtwn_softc *sc)
   91 {
   92 #define RTWN_CHK(res) do {      \
   93         if (res != 0)           \
   94                 return (EIO);   \
   95 } while(0)
   96 
   97         RTWN_ASSERT_LOCKED(sc);
   98 
   99         RTWN_CHK(rtwn_bb_setbits(sc, 0x814, 0x3fffffff, 0x04cc4d10));
  100         RTWN_CHK(rtwn_bb_setbits(sc, R12A_BW_INDICATION, 0xff, 0x06));
  101         RTWN_CHK(rtwn_bb_write(sc, 0x918, 0x1c16ecdf));
  102         RTWN_CHK(rtwn_bb_write(sc, 0x924, 0x0152a400));
  103         RTWN_CHK(rtwn_bb_write(sc, 0x91c, 0x0fa21a20));
  104         RTWN_CHK(rtwn_bb_write(sc, 0x920, 0xe0f57204));
  105 
  106         return (r21au_dfs_radar_reset(sc));
  107 
  108 #undef RTWN_CHK
  109 }
  110 
  111 static int
  112 r21au_dfs_radar_is_detected(struct rtwn_softc *sc)
  113 {
  114         return !!(rtwn_bb_read(sc, 0xf98) & 0x00020000);
  115 }
  116 
  117 void
  118 r21au_chan_check(void *arg, int npending __unused)
  119 {
  120         struct rtwn_softc *sc = arg;
  121         struct r12a_softc *rs = sc->sc_priv;
  122         struct ieee80211com *ic = &sc->sc_ic;
  123 
  124         RTWN_LOCK(sc);
  125 #ifdef DIAGNOSTIC
  126         RTWN_DPRINTF(sc, RTWN_DEBUG_STATE,
  127             "%s: periodical radar detection task\n", __func__);
  128 #endif
  129 
  130         if (!r21au_dfs_radar_is_enabled(sc)) {
  131                 if (rs->rs_flags & R12A_RADAR_ENABLED) {
  132                         /* should not happen */
  133                         device_printf(sc->sc_dev,
  134                             "%s: radar detection was turned off "
  135                             "unexpectedly, resetting...\n", __func__);
  136 
  137                         /* XXX something more appropriate? */
  138                         ieee80211_restart_all(ic);
  139                 }
  140                 RTWN_UNLOCK(sc);
  141                 return;
  142         }
  143 
  144         if (r21au_dfs_radar_is_detected(sc)) {
  145                 r21au_dfs_radar_reset(sc);
  146 
  147                 RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, "%s: got radar event\n",
  148                     __func__);
  149 
  150                 RTWN_UNLOCK(sc);
  151                 IEEE80211_LOCK(ic);
  152 
  153                 ieee80211_dfs_notify_radar(ic, ic->ic_curchan);
  154 
  155                 IEEE80211_UNLOCK(ic);
  156                 RTWN_LOCK(sc);
  157         }
  158 
  159         if (rs->rs_flags & R12A_RADAR_ENABLED) {
  160                 taskqueue_enqueue_timeout(taskqueue_thread,
  161                     &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD);
  162         }
  163         RTWN_UNLOCK(sc);
  164 }
  165 
  166 int
  167 r21au_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
  168 {
  169         struct ieee80211com *ic = vap->iv_ic;
  170         struct rtwn_softc *sc = ic->ic_softc;
  171         struct rtwn_vap *rvp = RTWN_VAP(vap);
  172         struct r12a_softc *rs = sc->sc_priv;
  173         int error;
  174 
  175         KASSERT(rvp->id == 0 || rvp->id == 1,
  176             ("%s: unexpected vap id %d\n", __func__, rvp->id));
  177 
  178         IEEE80211_UNLOCK(ic);
  179         RTWN_LOCK(sc);
  180 
  181         error = 0;
  182         if (nstate == IEEE80211_S_CAC &&
  183             !(rs->rs_flags & R12A_RADAR_ENABLED)) {
  184                 error = r21au_dfs_radar_enable(sc);
  185                 if (error != 0) {
  186                         device_printf(sc->sc_dev,
  187                             "%s: cannot enable radar detection\n", __func__);
  188                         goto fail;
  189                 }
  190                 rs->rs_flags |= R12A_RADAR_ENABLED;
  191 
  192                 RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
  193                     "%s: radar detection was enabled\n", __func__);
  194 
  195                 taskqueue_enqueue_timeout(taskqueue_thread,
  196                     &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD);
  197         }
  198 
  199         if ((nstate < IEEE80211_S_CAC || nstate == IEEE80211_S_CSA) &&
  200             (rs->rs_flags & R12A_RADAR_ENABLED) &&
  201             (sc->vaps[!rvp->id] == NULL ||
  202             sc->vaps[!rvp->id]->vap.iv_state < IEEE80211_S_CAC ||
  203             sc->vaps[!rvp->id]->vap.iv_state == IEEE80211_S_CSA)) {
  204                 taskqueue_cancel_timeout(taskqueue_thread, &rs->rs_chan_check,
  205                     NULL);
  206 
  207                 rs->rs_flags &= ~R12A_RADAR_ENABLED;
  208                 r21au_dfs_radar_disable(sc);
  209 
  210                 RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
  211                     "%s: radar detection was disabled\n", __func__);
  212         }
  213 
  214 fail:
  215         RTWN_UNLOCK(sc);
  216         IEEE80211_LOCK(ic);
  217 
  218         if (error != 0)
  219                 return (error);
  220 
  221         return (rs->rs_newstate[rvp->id](vap, nstate, arg));
  222 }
  223 
  224 void
  225 r21au_scan_start(struct ieee80211com *ic)
  226 {
  227         struct rtwn_softc *sc = ic->ic_softc;
  228         struct r12a_softc *rs = sc->sc_priv;
  229 
  230         RTWN_LOCK(sc);
  231         if (rs->rs_flags & R12A_RADAR_ENABLED) {
  232                 RTWN_UNLOCK(sc);
  233                 while (taskqueue_cancel_timeout(taskqueue_thread,
  234                     &rs->rs_chan_check, NULL) != 0) {
  235                         taskqueue_drain_timeout(taskqueue_thread,
  236                             &rs->rs_chan_check);
  237                 }
  238                 RTWN_LOCK(sc);
  239 
  240                 r21au_dfs_radar_disable(sc);
  241                 RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
  242                     "%s: radar detection was (temporarily) disabled\n",
  243                     __func__);
  244         }
  245         RTWN_UNLOCK(sc);
  246 
  247         rs->rs_scan_start(ic);
  248 }
  249 
  250 void
  251 r21au_scan_end(struct ieee80211com *ic)
  252 {
  253         struct rtwn_softc *sc = ic->ic_softc;
  254         struct r12a_softc *rs = sc->sc_priv;
  255         int error;
  256 
  257         RTWN_LOCK(sc);
  258         if (rs->rs_flags & R12A_RADAR_ENABLED) {
  259                 error = r21au_dfs_radar_enable(sc);
  260                 if (error != 0) {
  261                         device_printf(sc->sc_dev,
  262                             "%s: cannot re-enable radar detection\n",
  263                             __func__);
  264 
  265                         /* XXX */
  266                         ieee80211_restart_all(ic);
  267                         RTWN_UNLOCK(sc);
  268                         return;
  269                 }
  270                 RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR,
  271                     "%s: radar detection was re-enabled\n", __func__);
  272 
  273                 taskqueue_enqueue_timeout(taskqueue_thread,
  274                     &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD);
  275         }
  276         RTWN_UNLOCK(sc);
  277 
  278         rs->rs_scan_end(ic);
  279 }

Cache object: fea188301b3ebca4db9cdde483704b8f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.