linux/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
   2/*
   3 * Copyright (C) 2005-2014 Intel Corporation
   4 * Copyright (C) 2015-2017 Intel Deutschland GmbH
   5 */
   6#ifndef __iwl_notif_wait_h__
   7#define __iwl_notif_wait_h__
   8
   9#include <linux/wait.h>
  10
  11#include "iwl-trans.h"
  12
  13struct iwl_notif_wait_data {
  14        struct list_head notif_waits;
  15        spinlock_t notif_wait_lock;
  16        wait_queue_head_t notif_waitq;
  17};
  18
  19#define MAX_NOTIF_CMDS  5
  20
  21/**
  22 * struct iwl_notification_wait - notification wait entry
  23 * @list: list head for global list
  24 * @fn: Function called with the notification. If the function
  25 *      returns true, the wait is over, if it returns false then
  26 *      the waiter stays blocked. If no function is given, any
  27 *      of the listed commands will unblock the waiter.
  28 * @cmds: command IDs
  29 * @n_cmds: number of command IDs
  30 * @triggered: waiter should be woken up
  31 * @aborted: wait was aborted
  32 *
  33 * This structure is not used directly, to wait for a
  34 * notification declare it on the stack, and call
  35 * iwl_init_notification_wait() with appropriate
  36 * parameters. Then do whatever will cause the ucode
  37 * to notify the driver, and to wait for that then
  38 * call iwl_wait_notification().
  39 *
  40 * Each notification is one-shot. If at some point we
  41 * need to support multi-shot notifications (which
  42 * can't be allocated on the stack) we need to modify
  43 * the code for them.
  44 */
  45struct iwl_notification_wait {
  46        struct list_head list;
  47
  48        bool (*fn)(struct iwl_notif_wait_data *notif_data,
  49                   struct iwl_rx_packet *pkt, void *data);
  50        void *fn_data;
  51
  52        u16 cmds[MAX_NOTIF_CMDS];
  53        u8 n_cmds;
  54        bool triggered, aborted;
  55};
  56
  57
  58/* caller functions */
  59void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data);
  60bool iwl_notification_wait(struct iwl_notif_wait_data *notif_data,
  61                           struct iwl_rx_packet *pkt);
  62void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data);
  63
  64static inline void
  65iwl_notification_notify(struct iwl_notif_wait_data *notif_data)
  66{
  67        wake_up_all(&notif_data->notif_waitq);
  68}
  69
  70static inline void
  71iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data,
  72                             struct iwl_rx_packet *pkt)
  73{
  74        if (iwl_notification_wait(notif_data, pkt))
  75                iwl_notification_notify(notif_data);
  76}
  77
  78/* user functions */
  79void __acquires(wait_entry)
  80iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data,
  81                           struct iwl_notification_wait *wait_entry,
  82                           const u16 *cmds, int n_cmds,
  83                           bool (*fn)(struct iwl_notif_wait_data *notif_data,
  84                                      struct iwl_rx_packet *pkt, void *data),
  85                           void *fn_data);
  86
  87int __must_check __releases(wait_entry)
  88iwl_wait_notification(struct iwl_notif_wait_data *notif_data,
  89                      struct iwl_notification_wait *wait_entry,
  90                      unsigned long timeout);
  91
  92void __releases(wait_entry)
  93iwl_remove_notification(struct iwl_notif_wait_data *notif_data,
  94                        struct iwl_notification_wait *wait_entry);
  95
  96#endif /* __iwl_notif_wait_h__ */
  97