linux/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
   2/*
   3 * Copyright (C) 2005-2014, 2018-2019 Intel Corporation
   4 * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
   5 * Copyright (C) 2015 Intel Deutschland GmbH
   6 */
   7#ifndef __iwl_op_mode_h__
   8#define __iwl_op_mode_h__
   9
  10#include <linux/netdevice.h>
  11#include <linux/debugfs.h>
  12
  13struct iwl_op_mode;
  14struct iwl_trans;
  15struct sk_buff;
  16struct iwl_device_cmd;
  17struct iwl_rx_cmd_buffer;
  18struct iwl_fw;
  19struct iwl_cfg;
  20
  21/**
  22 * DOC: Operational mode - what is it ?
  23 *
  24 * The operational mode (a.k.a. op_mode) is the layer that implements
  25 * mac80211's handlers. It knows two APIs: mac80211's and the fw's. It uses
  26 * the transport API to access the HW. The op_mode doesn't need to know how the
  27 * underlying HW works, since the transport layer takes care of that.
  28 *
  29 * There can be several op_mode: i.e. different fw APIs will require two
  30 * different op_modes. This is why the op_mode is virtualized.
  31 */
  32
  33/**
  34 * DOC: Life cycle of the Operational mode
  35 *
  36 * The operational mode has a very simple life cycle.
  37 *
  38 *      1) The driver layer (iwl-drv.c) chooses the op_mode based on the
  39 *         capabilities advertised by the fw file (in TLV format).
  40 *      2) The driver layer starts the op_mode (ops->start)
  41 *      3) The op_mode registers mac80211
  42 *      4) The op_mode is governed by mac80211
  43 *      5) The driver layer stops the op_mode
  44 */
  45
  46/**
  47 * struct iwl_op_mode_ops - op_mode specific operations
  48 *
  49 * The op_mode exports its ops so that external components can start it and
  50 * interact with it. The driver layer typically calls the start and stop
  51 * handlers, the transport layer calls the others.
  52 *
  53 * All the handlers MUST be implemented, except @rx_rss which can be left
  54 * out *iff* the opmode will never run on hardware with multi-queue capability.
  55 *
  56 * @start: start the op_mode. The transport layer is already allocated.
  57 *      May sleep
  58 * @stop: stop the op_mode. Must free all the memory allocated.
  59 *      May sleep
  60 * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
  61 *      HCMD this Rx responds to. Can't sleep.
  62 * @rx_rss: data queue RX notification to the op_mode, for (data) notifications
  63 *      received on the RSS queue(s). The queue parameter indicates which of the
  64 *      RSS queues received this frame; it will always be non-zero.
  65 *      This method must not sleep.
  66 * @async_cb: called when an ASYNC command with CMD_WANT_ASYNC_CALLBACK set
  67 *      completes. Must be atomic.
  68 * @queue_full: notifies that a HW queue is full.
  69 *      Must be atomic and called with BH disabled.
  70 * @queue_not_full: notifies that a HW queue is not full any more.
  71 *      Must be atomic and called with BH disabled.
  72 * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
  73 *      the radio is killed. Return %true if the device should be stopped by
  74 *      the transport immediately after the call. May sleep.
  75 * @free_skb: allows the transport layer to free skbs that haven't been
  76 *      reclaimed by the op_mode. This can happen when the driver is freed and
  77 *      there are Tx packets pending in the transport layer.
  78 *      Must be atomic
  79 * @nic_error: error notification. Must be atomic and must be called with BH
  80 *      disabled.
  81 * @cmd_queue_full: Called when the command queue gets full. Must be atomic and
  82 *      called with BH disabled.
  83 * @nic_config: configure NIC, called before firmware is started.
  84 *      May sleep
  85 * @wimax_active: invoked when WiMax becomes active. May sleep
  86 */
  87struct iwl_op_mode_ops {
  88        struct iwl_op_mode *(*start)(struct iwl_trans *trans,
  89                                     const struct iwl_cfg *cfg,
  90                                     const struct iwl_fw *fw,
  91                                     struct dentry *dbgfs_dir);
  92        void (*stop)(struct iwl_op_mode *op_mode);
  93        void (*rx)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
  94                   struct iwl_rx_cmd_buffer *rxb);
  95        void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
  96                       struct iwl_rx_cmd_buffer *rxb, unsigned int queue);
  97        void (*async_cb)(struct iwl_op_mode *op_mode,
  98                         const struct iwl_device_cmd *cmd);
  99        void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
 100        void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
 101        bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
 102        void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
 103        void (*nic_error)(struct iwl_op_mode *op_mode);
 104        void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
 105        void (*nic_config)(struct iwl_op_mode *op_mode);
 106        void (*wimax_active)(struct iwl_op_mode *op_mode);
 107};
 108
 109int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops);
 110void iwl_opmode_deregister(const char *name);
 111
 112/**
 113 * struct iwl_op_mode - operational mode
 114 * @ops: pointer to its own ops
 115 *
 116 * This holds an implementation of the mac80211 / fw API.
 117 */
 118struct iwl_op_mode {
 119        const struct iwl_op_mode_ops *ops;
 120
 121        char op_mode_specific[] __aligned(sizeof(void *));
 122};
 123
 124static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode)
 125{
 126        might_sleep();
 127        op_mode->ops->stop(op_mode);
 128}
 129
 130static inline void iwl_op_mode_rx(struct iwl_op_mode *op_mode,
 131                                  struct napi_struct *napi,
 132                                  struct iwl_rx_cmd_buffer *rxb)
 133{
 134        return op_mode->ops->rx(op_mode, napi, rxb);
 135}
 136
 137static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode,
 138                                      struct napi_struct *napi,
 139                                      struct iwl_rx_cmd_buffer *rxb,
 140                                      unsigned int queue)
 141{
 142        op_mode->ops->rx_rss(op_mode, napi, rxb, queue);
 143}
 144
 145static inline void iwl_op_mode_async_cb(struct iwl_op_mode *op_mode,
 146                                        const struct iwl_device_cmd *cmd)
 147{
 148        if (op_mode->ops->async_cb)
 149                op_mode->ops->async_cb(op_mode, cmd);
 150}
 151
 152static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode,
 153                                          int queue)
 154{
 155        op_mode->ops->queue_full(op_mode, queue);
 156}
 157
 158static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
 159                                              int queue)
 160{
 161        op_mode->ops->queue_not_full(op_mode, queue);
 162}
 163
 164static inline bool __must_check
 165iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, bool state)
 166{
 167        might_sleep();
 168        return op_mode->ops->hw_rf_kill(op_mode, state);
 169}
 170
 171static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
 172                                        struct sk_buff *skb)
 173{
 174        op_mode->ops->free_skb(op_mode, skb);
 175}
 176
 177static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode)
 178{
 179        op_mode->ops->nic_error(op_mode);
 180}
 181
 182static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
 183{
 184        op_mode->ops->cmd_queue_full(op_mode);
 185}
 186
 187static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
 188{
 189        might_sleep();
 190        op_mode->ops->nic_config(op_mode);
 191}
 192
 193static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode)
 194{
 195        might_sleep();
 196        op_mode->ops->wimax_active(op_mode);
 197}
 198
 199#endif /* __iwl_op_mode_h__ */
 200