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/contrib/dev/iwlwifi/fw/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 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
    2 /*
    3  * Copyright (C) 2005-2014, 2021 Intel Corporation
    4  * Copyright (C) 2015-2017 Intel Deutschland GmbH
    5  */
    6 #include <linux/sched.h>
    7 #include <linux/export.h>
    8 
    9 #include "iwl-drv.h"
   10 #include "notif-wait.h"
   11 
   12 
   13 void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
   14 {
   15         spin_lock_init(&notif_wait->notif_wait_lock);
   16         INIT_LIST_HEAD(&notif_wait->notif_waits);
   17         init_waitqueue_head(&notif_wait->notif_waitq);
   18 }
   19 IWL_EXPORT_SYMBOL(iwl_notification_wait_init);
   20 
   21 bool iwl_notification_wait(struct iwl_notif_wait_data *notif_wait,
   22                            struct iwl_rx_packet *pkt)
   23 {
   24         bool triggered = false;
   25 
   26         if (!list_empty(&notif_wait->notif_waits)) {
   27                 struct iwl_notification_wait *w;
   28 
   29                 spin_lock_bh(&notif_wait->notif_wait_lock);
   30                 list_for_each_entry(w, &notif_wait->notif_waits, list) {
   31                         int i;
   32                         bool found = false;
   33 
   34                         /*
   35                          * If it already finished (triggered) or has been
   36                          * aborted then don't evaluate it again to avoid races,
   37                          * Otherwise the function could be called again even
   38                          * though it returned true before
   39                          */
   40                         if (w->triggered || w->aborted)
   41                                 continue;
   42 
   43                         for (i = 0; i < w->n_cmds; i++) {
   44                                 u16 rec_id = WIDE_ID(pkt->hdr.group_id,
   45                                                      pkt->hdr.cmd);
   46 
   47                                 if (w->cmds[i] == rec_id ||
   48                                     (!iwl_cmd_groupid(w->cmds[i]) &&
   49                                      DEF_ID(w->cmds[i]) == rec_id)) {
   50                                         found = true;
   51                                         break;
   52                                 }
   53                         }
   54                         if (!found)
   55                                 continue;
   56 
   57                         if (!w->fn || w->fn(notif_wait, pkt, w->fn_data)) {
   58                                 w->triggered = true;
   59                                 triggered = true;
   60                         }
   61                 }
   62                 spin_unlock_bh(&notif_wait->notif_wait_lock);
   63         }
   64 
   65         return triggered;
   66 }
   67 IWL_EXPORT_SYMBOL(iwl_notification_wait);
   68 
   69 void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
   70 {
   71         struct iwl_notification_wait *wait_entry;
   72 
   73         spin_lock_bh(&notif_wait->notif_wait_lock);
   74         list_for_each_entry(wait_entry, &notif_wait->notif_waits, list)
   75                 wait_entry->aborted = true;
   76         spin_unlock_bh(&notif_wait->notif_wait_lock);
   77 
   78         wake_up_all(&notif_wait->notif_waitq);
   79 }
   80 IWL_EXPORT_SYMBOL(iwl_abort_notification_waits);
   81 
   82 void
   83 iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
   84                            struct iwl_notification_wait *wait_entry,
   85                            const u16 *cmds, int n_cmds,
   86                            bool (*fn)(struct iwl_notif_wait_data *notif_wait,
   87                                       struct iwl_rx_packet *pkt, void *data),
   88                            void *fn_data)
   89 {
   90         if (WARN_ON(n_cmds > MAX_NOTIF_CMDS))
   91                 n_cmds = MAX_NOTIF_CMDS;
   92 
   93         wait_entry->fn = fn;
   94         wait_entry->fn_data = fn_data;
   95         wait_entry->n_cmds = n_cmds;
   96         memcpy(wait_entry->cmds, cmds, n_cmds * sizeof(u16));
   97         wait_entry->triggered = false;
   98         wait_entry->aborted = false;
   99 
  100         spin_lock_bh(&notif_wait->notif_wait_lock);
  101         list_add(&wait_entry->list, &notif_wait->notif_waits);
  102         spin_unlock_bh(&notif_wait->notif_wait_lock);
  103 }
  104 IWL_EXPORT_SYMBOL(iwl_init_notification_wait);
  105 
  106 void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
  107                              struct iwl_notification_wait *wait_entry)
  108 {
  109         spin_lock_bh(&notif_wait->notif_wait_lock);
  110         list_del(&wait_entry->list);
  111         spin_unlock_bh(&notif_wait->notif_wait_lock);
  112 }
  113 IWL_EXPORT_SYMBOL(iwl_remove_notification);
  114 
  115 int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
  116                           struct iwl_notification_wait *wait_entry,
  117                           unsigned long timeout)
  118 {
  119         int ret;
  120 
  121         ret = wait_event_timeout(notif_wait->notif_waitq,
  122                                  wait_entry->triggered || wait_entry->aborted,
  123                                  timeout);
  124 
  125         iwl_remove_notification(notif_wait, wait_entry);
  126 
  127         if (wait_entry->aborted)
  128                 return -EIO;
  129 
  130         /* return value is always >= 0 */
  131         if (ret <= 0)
  132                 return -ETIMEDOUT;
  133         return 0;
  134 }
  135 IWL_EXPORT_SYMBOL(iwl_wait_notification);

Cache object: 2d55194029851e88accd3f363e266bee


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