OSDN Git Service

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 3811878..074977e 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 234e30f..6448195 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 debec96..5a91f5d 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 2d4bad5..605f57a 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 e4fa500..3967df6 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 8f1d93b..9ff0b43 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 43dbddf..ff68b8c 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 361bb3c..7d75f93 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 3c63468..dba0a86 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 dd6bb2a..817bf22 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 */