diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3af80e0..e215e9f 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -4394,31 +4394,6 @@ void ieee80211_free_hw(struct ieee80211_hw *hw); */ void ieee80211_restart_hw(struct ieee80211_hw *hw); -/** - * ieee80211_rx_list - receive frame and store processed skbs in a list - * - * 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 and RCU read lock - * - * @hw: the hardware this frame came in on - * @sta: the station the frame was received from, or %NULL - * @skb: the buffer to receive, owned by mac80211 after this call - * @list: the destination list - */ -void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - struct sk_buff *skb, struct list_head *list); - /** * ieee80211_rx_napi - receive frame from NAPI context * diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b460547..35b0fe0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -218,7 +218,7 @@ enum ieee80211_rx_flags { }; struct ieee80211_rx_data { - struct list_head *list; + struct napi_struct *napi; struct sk_buff *skb; struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fc93b5f..ecb5af6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2575,8 +2575,8 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb, memset(skb->cb, 0, sizeof(skb->cb)); /* deliver to local stack */ - if (rx->list) - list_add_tail(&skb->list, rx->list); + if (rx->napi) + napi_gro_receive(rx->napi, skb); else netif_receive_skb(skb); } @@ -3866,6 +3866,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, + .napi = NULL, /* must be NULL to not have races */ }; struct tid_ampdu_rx *tid_agg_rx; @@ -4469,8 +4470,8 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, /* deliver to local stack */ skb->protocol = eth_type_trans(skb, fast_rx->dev); memset(skb->cb, 0, sizeof(skb->cb)); - if (rx->list) - list_add_tail(&skb->list, rx->list); + if (rx->napi) + napi_gro_receive(rx->napi, skb); else netif_receive_skb(skb); @@ -4537,7 +4538,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, struct sk_buff *skb, - struct list_head *list) + struct napi_struct *napi) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; @@ -4552,7 +4553,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, memset(&rx, 0, sizeof(rx)); rx.skb = skb; rx.local = local; - rx.list = list; + rx.napi = napi; if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) I802_DEBUG_INC(local->dot11ReceivedFragmentCount); @@ -4660,8 +4661,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_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, - struct sk_buff *skb, struct list_head *list) +void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, + struct sk_buff *skb, struct napi_struct *napi) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate = NULL; @@ -4752,6 +4753,13 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, status->rx_flags = 0; + /* + * key references and virtual interfaces are protected using RCU + * and this requires that we are in a read-side RCU section during + * receive processing + */ + rcu_read_lock(); + /* * Frames with failed FCS/PLCP checksum are not returned, * all other frames are returned without radiotap header @@ -4759,47 +4767,23 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, * Also, frames with less than 16 bytes are dropped. */ skb = ieee80211_rx_monitor(local, skb, rate); - if (!skb) + if (!skb) { + rcu_read_unlock(); return; + } ieee80211_tpt_led_trig_rx(local, ((struct ieee80211_hdr *)skb->data)->frame_control, skb->len); - __ieee80211_rx_handle_packet(hw, pubsta, skb, list); + __ieee80211_rx_handle_packet(hw, pubsta, skb, napi); + + rcu_read_unlock(); return; drop: kfree_skb(skb); } -EXPORT_SYMBOL(ieee80211_rx_list); - -void ieee80211_rx_napi(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, - struct sk_buff *skb, struct napi_struct *napi) -{ - struct sk_buff *tmp; - LIST_HEAD(list); - - - /* - * key references and virtual interfaces are protected using RCU - * and this requires that we are in a read-side RCU section during - * receive processing - */ - rcu_read_lock(); - ieee80211_rx_list(hw, pubsta, skb, &list); - rcu_read_unlock(); - - if (!napi) { - netif_receive_skb_list(&list); - return; - } - - list_for_each_entry_safe(skb, tmp, &list, list) { - skb_list_del_init(skb); - napi_gro_receive(napi, skb); - } -} EXPORT_SYMBOL(ieee80211_rx_napi); /* This is a version of the rx handler that can be called from hard irq