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/iwm/if_iwm_notif_wait.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  * Based on BSD-licensed source modules in the Linux iwlwifi driver,
    3  * which were used as the reference documentation for this implementation.
    4  *
    5  ******************************************************************************
    6  *
    7  * This file is provided under a dual BSD/GPLv2 license.  When using or
    8  * redistributing this file, you may do so under either license.
    9  *
   10  * GPL LICENSE SUMMARY
   11  *
   12  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
   13  * Copyright(c) 2015 Intel Deutschland GmbH
   14  *
   15  * This program is free software; you can redistribute it and/or modify
   16  * it under the terms of version 2 of the GNU General Public License as
   17  * published by the Free Software Foundation.
   18  *
   19  * This program is distributed in the hope that it will be useful, but
   20  * WITHOUT ANY WARRANTY; without even the implied warranty of
   21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   22  * General Public License for more details.
   23  *
   24  * You should have received a copy of the GNU General Public License
   25  * along with this program; if not, write to the Free Software
   26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
   27  * USA
   28  *
   29  * The full GNU General Public License is included in this distribution
   30  * in the file called COPYING.
   31  *
   32  * Contact Information:
   33  *  Intel Linux Wireless <linuxwifi@intel.com>
   34  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
   35  *
   36  * BSD LICENSE
   37  *
   38  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
   39  * All rights reserved.
   40  *
   41  * Redistribution and use in source and binary forms, with or without
   42  * modification, are permitted provided that the following conditions
   43  * are met:
   44  *
   45  *  * Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  *  * Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in
   49  *    the documentation and/or other materials provided with the
   50  *    distribution.
   51  *  * Neither the name Intel Corporation nor the names of its
   52  *    contributors may be used to endorse or promote products derived
   53  *    from this software without specific prior written permission.
   54  *
   55  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   56  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   57  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   58  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   59  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   60  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   61  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   62  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   63  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   64  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   65  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   66  *
   67  *****************************************************************************/
   68 
   69 #include <sys/cdefs.h>
   70 __FBSDID("$FreeBSD$");
   71 
   72 #include "opt_wlan.h"
   73 #include "opt_iwm.h"
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/bus.h>
   78 #include <sys/kernel.h>
   79 #include <sys/malloc.h>
   80 #include <sys/lock.h>
   81 #include <sys/queue.h>
   82 
   83 #include <dev/iwm/if_iwm_notif_wait.h>
   84 
   85 #define IWM_WAIT_LOCK_INIT(_n, _s) \
   86         mtx_init(&(_n)->lk_mtx, (_s), "iwm wait_notif", MTX_DEF);
   87 #define IWM_WAIT_LOCK(_n)               mtx_lock(&(_n)->lk_mtx)
   88 #define IWM_WAIT_UNLOCK(_n)             mtx_unlock(&(_n)->lk_mtx)
   89 #define IWM_WAIT_LOCK_DESTROY(_n)       mtx_destroy(&(_n)->lk_mtx)
   90 
   91 struct iwm_notif_wait_data {
   92         struct mtx lk_mtx;
   93         char lk_buf[32];
   94         STAILQ_HEAD(, iwm_notification_wait) list;
   95         struct iwm_softc *sc;
   96 };
   97 
   98 struct iwm_notif_wait_data *
   99 iwm_notification_wait_init(struct iwm_softc *sc)
  100 {
  101         struct iwm_notif_wait_data *data;
  102 
  103         data = malloc(sizeof(*data), M_DEVBUF, M_NOWAIT | M_ZERO);
  104         if (data != NULL) {
  105                 snprintf(data->lk_buf, 32, "iwm wait_notif");
  106                 IWM_WAIT_LOCK_INIT(data, data->lk_buf);
  107                 STAILQ_INIT(&data->list);
  108                 data->sc = sc;
  109         }
  110 
  111         return data;
  112 }
  113 
  114 void
  115 iwm_notification_wait_free(struct iwm_notif_wait_data *notif_data)
  116 {
  117         KASSERT(STAILQ_EMPTY(&notif_data->list), ("notif list isn't empty"));
  118         IWM_WAIT_LOCK_DESTROY(notif_data);
  119         free(notif_data, M_DEVBUF);
  120 }
  121 
  122 /* XXX Get rid of separate cmd argument, like in iwlwifi's code */
  123 void
  124 iwm_notification_wait_notify(struct iwm_notif_wait_data *notif_data,
  125     uint16_t cmd, struct iwm_rx_packet *pkt)
  126 {
  127         struct iwm_notification_wait *wait_entry;
  128 
  129         IWM_WAIT_LOCK(notif_data);
  130         STAILQ_FOREACH(wait_entry, &notif_data->list, entry) {
  131                 int found = FALSE;
  132                 int i;
  133 
  134                 /*
  135                  * If it already finished (triggered) or has been
  136                  * aborted then don't evaluate it again to avoid races,
  137                  * Otherwise the function could be called again even
  138                  * though it returned true before
  139                  */
  140                 if (wait_entry->triggered || wait_entry->aborted)
  141                         continue;
  142 
  143                 for (i = 0; i < wait_entry->n_cmds; i++) {
  144                         if (cmd == wait_entry->cmds[i]) {
  145                                 found = TRUE;
  146                                 break;
  147                         }
  148                 }
  149                 if (!found)
  150                         continue;
  151 
  152                 if (!wait_entry->fn ||
  153                     wait_entry->fn(notif_data->sc, pkt, wait_entry->fn_data)) {
  154                         wait_entry->triggered = 1;
  155                         wakeup(wait_entry);
  156                 }
  157         }
  158         IWM_WAIT_UNLOCK(notif_data);
  159 }
  160 
  161 void
  162 iwm_abort_notification_waits(struct iwm_notif_wait_data *notif_data)
  163 {
  164         struct iwm_notification_wait *wait_entry;
  165 
  166         IWM_WAIT_LOCK(notif_data);
  167         STAILQ_FOREACH(wait_entry, &notif_data->list, entry) {
  168                 wait_entry->aborted = 1;
  169                 wakeup(wait_entry);
  170         }
  171         IWM_WAIT_UNLOCK(notif_data);
  172 }
  173 
  174 void
  175 iwm_init_notification_wait(struct iwm_notif_wait_data *notif_data,
  176     struct iwm_notification_wait *wait_entry, const uint16_t *cmds, int n_cmds,
  177     int (*fn)(struct iwm_softc *sc, struct iwm_rx_packet *pkt, void *data),
  178     void *fn_data)
  179 {
  180         KASSERT(n_cmds <= IWM_MAX_NOTIF_CMDS,
  181             ("n_cmds %d is too large", n_cmds));
  182         wait_entry->fn = fn;
  183         wait_entry->fn_data = fn_data;
  184         wait_entry->n_cmds = n_cmds;
  185         memcpy(wait_entry->cmds, cmds, n_cmds * sizeof(uint16_t));
  186         wait_entry->triggered = 0;
  187         wait_entry->aborted = 0;
  188 
  189         IWM_WAIT_LOCK(notif_data);
  190         STAILQ_INSERT_TAIL(&notif_data->list, wait_entry, entry);
  191         IWM_WAIT_UNLOCK(notif_data);
  192 }
  193 
  194 int
  195 iwm_wait_notification(struct iwm_notif_wait_data *notif_data,
  196     struct iwm_notification_wait *wait_entry, int timeout)
  197 {
  198         int ret = 0;
  199 
  200         IWM_WAIT_LOCK(notif_data);
  201         if (!wait_entry->triggered && !wait_entry->aborted) {
  202                 ret = msleep(wait_entry, &notif_data->lk_mtx, 0, "iwm_notif",
  203                     timeout);
  204         }
  205         STAILQ_REMOVE(&notif_data->list, wait_entry, iwm_notification_wait,
  206             entry);
  207         IWM_WAIT_UNLOCK(notif_data);
  208 
  209         return ret;
  210 }
  211 
  212 void
  213 iwm_remove_notification(struct iwm_notif_wait_data *notif_data,
  214     struct iwm_notification_wait *wait_entry)
  215 {
  216         IWM_WAIT_LOCK(notif_data);
  217         STAILQ_REMOVE(&notif_data->list, wait_entry, iwm_notification_wait,
  218             entry);
  219         IWM_WAIT_UNLOCK(notif_data);
  220 }

Cache object: 85214931552aaa1c66cf117187931e2a


[ 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.