aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-17 07:13:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 14:57:54 -0400
commitf1d58c2521eb160178b2151d6326d8dc5d7c8560 (patch)
treeaf373bb1a5fbb6bc9436d29095133992d33d6598 /net/mac80211/rx.c
parent18ad01c43918751cc22f8ee28f6b38b8954a55b2 (diff)
mac80211: push rx status into skb->cb
Within mac80211, we often need to copy the rx status into skb->cb. This is wasteful, as drivers could be building it in there to start with. This patch changes the API so that drivers are expected to pass the RX status in skb->cb, now accessible as IEEE80211_SKB_RXCB(skb). It also updates all drivers to pass the rx status in there, but only by making them memcpy() it into place before the call to the receive function (ieee80211_rx(_irqsafe)). Each driver can now be optimised on its own schedule. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c71
1 files changed, 31 insertions, 40 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index de5bba7f910a..0563b6969a21 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -30,7 +30,6 @@
30static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, 30static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
31 struct tid_ampdu_rx *tid_agg_rx, 31 struct tid_ampdu_rx *tid_agg_rx,
32 struct sk_buff *skb, 32 struct sk_buff *skb,
33 struct ieee80211_rx_status *status,
34 u16 mpdu_seq_num, 33 u16 mpdu_seq_num,
35 int bar_req); 34 int bar_req);
36/* 35/*
@@ -59,11 +58,11 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
59 return skb; 58 return skb;
60} 59}
61 60
62static inline int should_drop_frame(struct ieee80211_rx_status *status, 61static inline int should_drop_frame(struct sk_buff *skb,
63 struct sk_buff *skb,
64 int present_fcs_len, 62 int present_fcs_len,
65 int radiotap_len) 63 int radiotap_len)
66{ 64{
65 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
67 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 66 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
68 67
69 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) 68 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
@@ -111,10 +110,10 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
111static void 110static void
112ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, 111ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
113 struct sk_buff *skb, 112 struct sk_buff *skb,
114 struct ieee80211_rx_status *status,
115 struct ieee80211_rate *rate, 113 struct ieee80211_rate *rate,
116 int rtap_len) 114 int rtap_len)
117{ 115{
116 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
118 struct ieee80211_radiotap_header *rthdr; 117 struct ieee80211_radiotap_header *rthdr;
119 unsigned char *pos; 118 unsigned char *pos;
120 119
@@ -220,9 +219,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
220 */ 219 */
221static struct sk_buff * 220static struct sk_buff *
222ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, 221ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
223 struct ieee80211_rx_status *status,
224 struct ieee80211_rate *rate) 222 struct ieee80211_rate *rate)
225{ 223{
224 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
226 struct ieee80211_sub_if_data *sdata; 225 struct ieee80211_sub_if_data *sdata;
227 int needed_headroom = 0; 226 int needed_headroom = 0;
228 struct sk_buff *skb, *skb2; 227 struct sk_buff *skb, *skb2;
@@ -248,8 +247,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
248 present_fcs_len = FCS_LEN; 247 present_fcs_len = FCS_LEN;
249 248
250 if (!local->monitors) { 249 if (!local->monitors) {
251 if (should_drop_frame(status, origskb, present_fcs_len, 250 if (should_drop_frame(origskb, present_fcs_len, rtap_len)) {
252 rtap_len)) {
253 dev_kfree_skb(origskb); 251 dev_kfree_skb(origskb);
254 return NULL; 252 return NULL;
255 } 253 }
@@ -257,7 +255,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
257 return remove_monitor_info(local, origskb, rtap_len); 255 return remove_monitor_info(local, origskb, rtap_len);
258 } 256 }
259 257
260 if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) { 258 if (should_drop_frame(origskb, present_fcs_len, rtap_len)) {
261 /* only need to expand headroom if necessary */ 259 /* only need to expand headroom if necessary */
262 skb = origskb; 260 skb = origskb;
263 origskb = NULL; 261 origskb = NULL;
@@ -289,7 +287,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
289 287
290 /* if necessary, prepend radiotap information */ 288 /* if necessary, prepend radiotap information */
291 if (!(status->flag & RX_FLAG_RADIOTAP)) 289 if (!(status->flag & RX_FLAG_RADIOTAP))
292 ieee80211_add_rx_radiotap_header(local, skb, status, rate, 290 ieee80211_add_rx_radiotap_header(local, skb, rate,
293 needed_headroom); 291 needed_headroom);
294 292
295 skb_reset_mac_header(skb); 293 skb_reset_mac_header(skb);
@@ -421,12 +419,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
421 struct sk_buff *skb = rx->skb; 419 struct sk_buff *skb = rx->skb;
422 420
423 if (unlikely(local->hw_scanning)) 421 if (unlikely(local->hw_scanning))
424 return ieee80211_scan_rx(rx->sdata, skb, rx->status); 422 return ieee80211_scan_rx(rx->sdata, skb);
425 423
426 if (unlikely(local->sw_scanning)) { 424 if (unlikely(local->sw_scanning)) {
427 /* drop all the other packets during a software scan anyway */ 425 /* drop all the other packets during a software scan anyway */
428 if (ieee80211_scan_rx(rx->sdata, skb, rx->status) 426 if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
429 != RX_QUEUED)
430 dev_kfree_skb(skb); 427 dev_kfree_skb(skb);
431 return RX_QUEUED; 428 return RX_QUEUED;
432 } 429 }
@@ -1620,7 +1617,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
1620 /* manage reordering buffer according to requested */ 1617 /* manage reordering buffer according to requested */
1621 /* sequence number */ 1618 /* sequence number */
1622 rcu_read_lock(); 1619 rcu_read_lock();
1623 ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, NULL, 1620 ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
1624 start_seq_num, 1); 1621 start_seq_num, 1);
1625 rcu_read_unlock(); 1622 rcu_read_unlock();
1626 return RX_DROP_UNUSABLE; 1623 return RX_DROP_UNUSABLE;
@@ -1817,13 +1814,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
1817 return RX_DROP_MONITOR; 1814 return RX_DROP_MONITOR;
1818 1815
1819 if (ieee80211_vif_is_mesh(&sdata->vif)) 1816 if (ieee80211_vif_is_mesh(&sdata->vif))
1820 return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); 1817 return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
1821 1818
1822 if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 1819 if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
1823 return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status); 1820 return ieee80211_ibss_rx_mgmt(sdata, rx->skb);
1824 1821
1825 if (sdata->vif.type == NL80211_IFTYPE_STATION) 1822 if (sdata->vif.type == NL80211_IFTYPE_STATION)
1826 return ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); 1823 return ieee80211_sta_rx_mgmt(sdata, rx->skb);
1827 1824
1828 return RX_DROP_MONITOR; 1825 return RX_DROP_MONITOR;
1829} 1826}
@@ -2114,9 +2111,9 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
2114 */ 2111 */
2115static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, 2112static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2116 struct sk_buff *skb, 2113 struct sk_buff *skb,
2117 struct ieee80211_rx_status *status,
2118 struct ieee80211_rate *rate) 2114 struct ieee80211_rate *rate)
2119{ 2115{
2116 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
2120 struct ieee80211_local *local = hw_to_local(hw); 2117 struct ieee80211_local *local = hw_to_local(hw);
2121 struct ieee80211_sub_if_data *sdata; 2118 struct ieee80211_sub_if_data *sdata;
2122 struct ieee80211_hdr *hdr; 2119 struct ieee80211_hdr *hdr;
@@ -2227,20 +2224,21 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
2227{ 2224{
2228 struct ieee80211_supported_band *sband; 2225 struct ieee80211_supported_band *sband;
2229 struct ieee80211_rate *rate; 2226 struct ieee80211_rate *rate;
2230 struct ieee80211_rx_status status; 2227 struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
2228 struct ieee80211_rx_status *status;
2231 2229
2232 if (!tid_agg_rx->reorder_buf[index]) 2230 if (!skb)
2233 goto no_frame; 2231 goto no_frame;
2234 2232
2233 status = IEEE80211_SKB_RXCB(skb);
2234
2235 /* release the reordered frames to stack */ 2235 /* release the reordered frames to stack */
2236 memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); 2236 sband = hw->wiphy->bands[status->band];
2237 sband = hw->wiphy->bands[status.band]; 2237 if (status->flag & RX_FLAG_HT)
2238 if (status.flag & RX_FLAG_HT)
2239 rate = sband->bitrates; /* TODO: HT rates */ 2238 rate = sband->bitrates; /* TODO: HT rates */
2240 else 2239 else
2241 rate = &sband->bitrates[status.rate_idx]; 2240 rate = &sband->bitrates[status->rate_idx];
2242 __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], 2241 __ieee80211_rx_handle_packet(hw, skb, rate);
2243 &status, rate);
2244 tid_agg_rx->stored_mpdu_num--; 2242 tid_agg_rx->stored_mpdu_num--;
2245 tid_agg_rx->reorder_buf[index] = NULL; 2243 tid_agg_rx->reorder_buf[index] = NULL;
2246 2244
@@ -2265,7 +2263,6 @@ no_frame:
2265static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, 2263static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2266 struct tid_ampdu_rx *tid_agg_rx, 2264 struct tid_ampdu_rx *tid_agg_rx,
2267 struct sk_buff *skb, 2265 struct sk_buff *skb,
2268 struct ieee80211_rx_status *rxstatus,
2269 u16 mpdu_seq_num, 2266 u16 mpdu_seq_num,
2270 int bar_req) 2267 int bar_req)
2271{ 2268{
@@ -2324,8 +2321,6 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2324 /* put the frame in the reordering buffer */ 2321 /* put the frame in the reordering buffer */
2325 tid_agg_rx->reorder_buf[index] = skb; 2322 tid_agg_rx->reorder_buf[index] = skb;
2326 tid_agg_rx->reorder_time[index] = jiffies; 2323 tid_agg_rx->reorder_time[index] = jiffies;
2327 memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus,
2328 sizeof(*rxstatus));
2329 tid_agg_rx->stored_mpdu_num++; 2324 tid_agg_rx->stored_mpdu_num++;
2330 /* release the buffer until next missing frame */ 2325 /* release the buffer until next missing frame */
2331 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) 2326 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn)
@@ -2374,8 +2369,7 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2374} 2369}
2375 2370
2376static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, 2371static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2377 struct sk_buff *skb, 2372 struct sk_buff *skb)
2378 struct ieee80211_rx_status *status)
2379{ 2373{
2380 struct ieee80211_hw *hw = &local->hw; 2374 struct ieee80211_hw *hw = &local->hw;
2381 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 2375 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -2424,7 +2418,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2424 2418
2425 /* according to mpdu sequence number deal with reordering buffer */ 2419 /* according to mpdu sequence number deal with reordering buffer */
2426 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; 2420 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2427 ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, status, 2421 ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
2428 mpdu_seq_num, 0); 2422 mpdu_seq_num, 0);
2429 end_reorder: 2423 end_reorder:
2430 return ret; 2424 return ret;
@@ -2434,12 +2428,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2434 * This is the receive path handler. It is called by a low level driver when an 2428 * This is the receive path handler. It is called by a low level driver when an
2435 * 802.11 MPDU is received from the hardware. 2429 * 802.11 MPDU is received from the hardware.
2436 */ 2430 */
2437void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, 2431void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
2438 struct ieee80211_rx_status *status)
2439{ 2432{
2440 struct ieee80211_local *local = hw_to_local(hw); 2433 struct ieee80211_local *local = hw_to_local(hw);
2441 struct ieee80211_rate *rate = NULL; 2434 struct ieee80211_rate *rate = NULL;
2442 struct ieee80211_supported_band *sband; 2435 struct ieee80211_supported_band *sband;
2436 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
2443 2437
2444 if (status->band < 0 || 2438 if (status->band < 0 ||
2445 status->band >= IEEE80211_NUM_BANDS) { 2439 status->band >= IEEE80211_NUM_BANDS) {
@@ -2482,7 +2476,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
2482 * if it was previously present. 2476 * if it was previously present.
2483 * Also, frames with less than 16 bytes are dropped. 2477 * Also, frames with less than 16 bytes are dropped.
2484 */ 2478 */
2485 skb = ieee80211_rx_monitor(local, skb, status, rate); 2479 skb = ieee80211_rx_monitor(local, skb, rate);
2486 if (!skb) { 2480 if (!skb) {
2487 rcu_read_unlock(); 2481 rcu_read_unlock();
2488 return; 2482 return;
@@ -2500,8 +2494,8 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
2500 * frames from other than operational channel), but that should not 2494 * frames from other than operational channel), but that should not
2501 * happen in normal networks. 2495 * happen in normal networks.
2502 */ 2496 */
2503 if (!ieee80211_rx_reorder_ampdu(local, skb, status)) 2497 if (!ieee80211_rx_reorder_ampdu(local, skb))
2504 __ieee80211_rx_handle_packet(hw, skb, status, rate); 2498 __ieee80211_rx_handle_packet(hw, skb, rate);
2505 2499
2506 rcu_read_unlock(); 2500 rcu_read_unlock();
2507} 2501}
@@ -2509,16 +2503,13 @@ EXPORT_SYMBOL(__ieee80211_rx);
2509 2503
2510/* This is a version of the rx handler that can be called from hard irq 2504/* This is a version of the rx handler that can be called from hard irq
2511 * context. Post the skb on the queue and schedule the tasklet */ 2505 * context. Post the skb on the queue and schedule the tasklet */
2512void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb, 2506void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb)
2513 struct ieee80211_rx_status *status)
2514{ 2507{
2515 struct ieee80211_local *local = hw_to_local(hw); 2508 struct ieee80211_local *local = hw_to_local(hw);
2516 2509
2517 BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); 2510 BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb));
2518 2511
2519 skb->dev = local->mdev; 2512 skb->dev = local->mdev;
2520 /* copy status into skb->cb for use by tasklet */
2521 memcpy(skb->cb, status, sizeof(*status));
2522 skb->pkt_type = IEEE80211_RX_MSG; 2513 skb->pkt_type = IEEE80211_RX_MSG;
2523 skb_queue_tail(&local->skb_queue, skb); 2514 skb_queue_tail(&local->skb_queue, skb);
2524 tasklet_schedule(&local->tasklet); 2515 tasklet_schedule(&local->tasklet);