mac80211: don't store napi struct
authorJohannes Berg <johannes.berg@intel.com>
Thu, 11 Jun 2015 14:02:32 +0000 (16:02 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 17 Jul 2015 13:37:59 +0000 (15:37 +0200)
When introducing multiple RX queues, a single NAPI struct will not
be sufficient. Instead of trying to store multiple, simply change
the API to have the NAPI struct passed to the RX function. This of
course means that drivers using rx_irqsafe() cannot use NAPI, but
that seems a reasonable trade-off, particularly since only two of
all drivers are currently using it at all.

While at it, we can now remove the IEEE80211_RX_REORDER_TIMER flag
again since this code path cannot have a napi struct anyway.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/dvm/dev.h
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/dvm/rx.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/rx.c
include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/rx.c

index 3811878ab9cd2057ad44785c7f3dad5cb5edcf07..074977ede34391380c8c2383435847ae5dddb8a7 100644 (file)
@@ -669,6 +669,8 @@ struct iwl_priv {
        /* ieee device used by generic ieee processing code */
        struct ieee80211_hw *hw;
 
+       struct napi_struct *napi;
+
        struct list_head calib_results;
 
        struct workqueue_struct *workqueue;
index 234e30f498b2dde18f3f355d5cfdcf13db6dc185..644819563cf0e85272b3780243d160a26ced3e82 100644 (file)
@@ -2037,7 +2037,8 @@ static void iwl_napi_add(struct iwl_op_mode *op_mode,
 {
        struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
 
-       ieee80211_napi_add(priv->hw, napi, napi_dev, poll, weight);
+       netif_napi_add(napi_dev, napi, poll, weight);
+       priv->napi = napi;
 }
 
 static const struct iwl_op_mode_ops iwl_dvm_ops = {
index debec963c610d4693fb40ca22a27b9cd3b6310ac..5a91f5d6b1dcc5de325bb9465c995cebb096c710 100644 (file)
@@ -786,7 +786,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
 
        memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
-       ieee80211_rx(priv->hw, skb);
+       ieee80211_rx_napi(priv->hw, skb, priv->napi);
 }
 
 static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
index 2d4bad5fe825fb4802fc1439167323dcf4b23e7b..605f57a2c6be4c76f07a36cd99ccbc91d81f44c4 100644 (file)
@@ -559,6 +559,7 @@ struct iwl_mvm {
        const struct iwl_cfg *cfg;
        struct iwl_phy_db *phy_db;
        struct ieee80211_hw *hw;
+       struct napi_struct *napi;
 
        /* for protecting access to iwl_mvm */
        struct mutex mutex;
index e4fa50075ffdc3b51c66f4b6587595134da9ade3..3967df63e0f3822a53b0d120cfc811773e5f44c0 100644 (file)
@@ -1316,7 +1316,8 @@ static void iwl_mvm_napi_add(struct iwl_op_mode *op_mode,
 {
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 
-       ieee80211_napi_add(mvm->hw, napi, napi_dev, poll, weight);
+       netif_napi_add(napi_dev, napi, poll, weight);
+       mvm->napi = napi;
 }
 
 static const struct iwl_op_mode_ops iwl_mvm_ops = {
index 8f1d93b7a13aa1059a4844c64f825822ee07605a..9ff0b4321df3b051d5e1ec3576e73036b578f53e 100644 (file)
@@ -129,7 +129,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
                                fraglen, rxb->truesize);
        }
 
-       ieee80211_rx(mvm->hw, skb);
+       ieee80211_rx_napi(mvm->hw, skb, mvm->napi);
 }
 
 /*
index 43dbddfa06c00de84e1d626eb8451a2c2757f2c9..ff68b8c4ab35164ff235bb89101fbb042c8dd954 100644 (file)
@@ -3694,20 +3694,28 @@ void ieee80211_free_hw(struct ieee80211_hw *hw);
 void ieee80211_restart_hw(struct ieee80211_hw *hw);
 
 /**
- * ieee80211_napi_add - initialize mac80211 NAPI context
- * @hw: the hardware to initialize the NAPI context on
- * @napi: the NAPI context to initialize
- * @napi_dev: dummy NAPI netdevice, here to not waste the space if the
- *     driver doesn't use NAPI
- * @poll: poll function
- * @weight: default weight
+ * ieee80211_rx_napi - receive frame from NAPI context
  *
- * See also netif_napi_add().
+ * Use this function to hand received frames to mac80211. The receive
+ * buffer in @skb must start with an IEEE 802.11 header. In case of a
+ * paged @skb is used, the driver is recommended to put the ieee80211
+ * header of the frame on the linear part of the @skb to avoid memory
+ * allocation and/or memcpy by the stack.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other. Calls to
+ * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
+ * mixed for a single hardware. Must not run concurrently with
+ * ieee80211_tx_status() or ieee80211_tx_status_ni().
+ *
+ * This function must be called with BHs disabled.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac80211 after this call
+ * @napi: the NAPI context
  */
-void ieee80211_napi_add(struct ieee80211_hw *hw, struct napi_struct *napi,
-                       struct net_device *napi_dev,
-                       int (*poll)(struct napi_struct *, int),
-                       int weight);
+void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb,
+                      struct napi_struct *napi);
 
 /**
  * ieee80211_rx - receive frame
@@ -3729,7 +3737,10 @@ void ieee80211_napi_add(struct ieee80211_hw *hw, struct napi_struct *napi,
  * @hw: the hardware this frame came in on
  * @skb: the buffer to receive, owned by mac80211 after this call
  */
-void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
+static inline void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+       ieee80211_rx_napi(hw, skb, NULL);
+}
 
 /**
  * ieee80211_rx_irqsafe - receive frame
index 361bb3ca335c6b9be26d971f78fcbcb36fe2a4ee..7d75f93bac7d57bd47dc9a90aee96b4e4d8fc0a5 100644 (file)
@@ -202,8 +202,6 @@ enum ieee80211_packet_rx_flags {
  * @IEEE80211_RX_CMNTR: received on cooked monitor already
  * @IEEE80211_RX_BEACON_REPORTED: This frame was already reported
  *     to cfg80211_report_obss_beacon().
- * @IEEE80211_RX_REORDER_TIMER: this frame is released by the
- *     reorder buffer timeout timer, not the normal RX path
  *
  * These flags are used across handling multiple interfaces
  * for a single frame.
@@ -211,10 +209,10 @@ enum ieee80211_packet_rx_flags {
 enum ieee80211_rx_flags {
        IEEE80211_RX_CMNTR              = BIT(0),
        IEEE80211_RX_BEACON_REPORTED    = BIT(1),
-       IEEE80211_RX_REORDER_TIMER      = BIT(2),
 };
 
 struct ieee80211_rx_data {
+       struct napi_struct *napi;
        struct sk_buff *skb;
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
@@ -1347,8 +1345,6 @@ struct ieee80211_local {
 
        struct ieee80211_sub_if_data __rcu *p2p_sdata;
 
-       struct napi_struct *napi;
-
        /* virtual monitor interface */
        struct ieee80211_sub_if_data __rcu *monitor_sdata;
        struct cfg80211_chan_def monitor_chandef;
index 3c63468b4dfb530d0e28a5f97dddf5065543ba6f..dba0a86dee18ecb0d6eadd34f4967369ff2e82e8 100644 (file)
@@ -1132,18 +1132,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL(ieee80211_register_hw);
 
-void ieee80211_napi_add(struct ieee80211_hw *hw, struct napi_struct *napi,
-                       struct net_device *napi_dev,
-                       int (*poll)(struct napi_struct *, int),
-                       int weight)
-{
-       struct ieee80211_local *local = hw_to_local(hw);
-
-       netif_napi_add(napi_dev, napi, poll, weight);
-       local->napi = napi;
-}
-EXPORT_SYMBOL_GPL(ieee80211_napi_add);
-
 void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 {
        struct ieee80211_local *local = hw_to_local(hw);
index dd6bb2a54d45f8b791d10a2ccf83092998ba7efe..817bf22dad5a1b4e56974dfb21720bb3a1ffafb1 100644 (file)
@@ -2148,9 +2148,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                /* deliver to local stack */
                skb->protocol = eth_type_trans(skb, dev);
                memset(skb->cb, 0, sizeof(skb->cb));
-               if (!(rx->flags & IEEE80211_RX_REORDER_TIMER) &&
-                   rx->local->napi)
-                       napi_gro_receive(rx->local->napi, skb);
+               if (rx->napi)
+                       napi_gro_receive(rx->napi, skb);
                else
                        netif_receive_skb(skb);
        }
@@ -3256,7 +3255,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                /* This is OK -- must be QoS data frame */
                .security_idx = tid,
                .seqno_idx = tid,
-               .flags = IEEE80211_RX_REORDER_TIMER,
+               .napi = NULL, /* must be NULL to not have races */
        };
        struct tid_ampdu_rx *tid_agg_rx;
 
@@ -3433,7 +3432,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
  * be called with rcu_read_lock protection.
  */
 static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
-                                        struct sk_buff *skb)
+                                        struct sk_buff *skb,
+                                        struct napi_struct *napi)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_sub_if_data *sdata;
@@ -3449,6 +3449,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        memset(&rx, 0, sizeof(rx));
        rx.skb = skb;
        rx.local = local;
+       rx.napi = napi;
 
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
@@ -3550,7 +3551,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
  * This is the receive path handler. It is called by a low level driver when an
  * 802.11 MPDU is received from the hardware.
  */
-void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb,
+                      struct napi_struct *napi)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_rate *rate = NULL;
@@ -3649,7 +3651,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
        ieee80211_tpt_led_trig_rx(local,
                        ((struct ieee80211_hdr *)skb->data)->frame_control,
                        skb->len);
-       __ieee80211_rx_handle_packet(hw, skb);
+       __ieee80211_rx_handle_packet(hw, skb, napi);
 
        rcu_read_unlock();
 
@@ -3657,7 +3659,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
  drop:
        kfree_skb(skb);
 }
-EXPORT_SYMBOL(ieee80211_rx);
+EXPORT_SYMBOL(ieee80211_rx_napi);
 
 /* This is a version of the rx handler that can be called from hard irq
  * context. Post the skb on the queue and schedule the tasklet */