cfg80211 API for channels/bitrates, mac80211 and driver conversion
[linux-2.6-block.git] / net / mac80211 / rx.c
index 1ccd32933eb73e58985e13374ececdb064d0c43e..c9ff98a9321136d5592ae08415100b8f6570cb2b 100644 (file)
@@ -82,10 +82,10 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
  */
 static struct sk_buff *
 ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
-                    struct ieee80211_rx_status *status)
+                    struct ieee80211_rx_status *status,
+                    struct ieee80211_rate *rate)
 {
        struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_rate *rate;
        int needed_headroom = 0;
        struct ieee80211_radiotap_header *rthdr;
        __le64 *rttsft = NULL;
@@ -194,14 +194,11 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                        rtfixed->rx_flags |=
                                cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
 
-               rate = ieee80211_get_rate(local, status->phymode,
-                                         status->rate);
-               if (rate)
-                       rtfixed->rate = rate->rate / 5;
+               rtfixed->rate = rate->bitrate / 5;
 
                rtfixed->chan_freq = cpu_to_le16(status->freq);
 
-               if (status->phymode == MODE_IEEE80211A)
+               if (status->band == IEEE80211_BAND_5GHZ)
                        rtfixed->chan_flags =
                                cpu_to_le16(IEEE80211_CHAN_OFDM |
                                            IEEE80211_CHAN_5GHZ);
@@ -249,15 +246,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
 }
 
 
-/* pre-rx handlers
- *
- * these don't have dev/sdata fields in the rx data
- * The sta value should also not be used because it may
- * be NULL even though a STA (in IBSS mode) will be added.
- */
-
-static ieee80211_txrx_result
-ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
+static void ieee80211_parse_qos(struct ieee80211_txrx_data *rx)
 {
        u8 *data = rx->skb->data;
        int tid;
@@ -290,61 +279,16 @@ ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
        /* Set skb->priority to 1d tag if highest order bit of TID is not set.
         * For now, set skb->priority to 0 for other cases. */
        rx->skb->priority = (tid > 7) ? 0 : tid;
-
-       return TXRX_CONTINUE;
-}
-
-
-static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
-                             struct sk_buff *skb,
-                             struct ieee80211_rx_status *status)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       u32 load = 0, hdrtime;
-       struct ieee80211_rate *rate;
-       struct ieee80211_hw_mode *mode = local->hw.conf.mode;
-       int i;
-
-       /* Estimate total channel use caused by this frame */
-
-       if (unlikely(mode->num_rates < 0))
-               return TXRX_CONTINUE;
-
-       rate = &mode->rates[0];
-       for (i = 0; i < mode->num_rates; i++) {
-               if (mode->rates[i].val == status->rate) {
-                       rate = &mode->rates[i];
-                       break;
-               }
-       }
-
-       /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
-        * 1 usec = 1/8 * (1080 / 10) = 13.5 */
-
-       if (mode->mode == MODE_IEEE80211A ||
-           (mode->mode == MODE_IEEE80211G &&
-            rate->flags & IEEE80211_RATE_ERP))
-               hdrtime = CHAN_UTIL_HDR_SHORT;
-       else
-               hdrtime = CHAN_UTIL_HDR_LONG;
-
-       load = hdrtime;
-       if (!is_multicast_ether_addr(hdr->addr1))
-               load += hdrtime;
-
-       load += skb->len * rate->rate_inv;
-
-       /* Divide channel_use by 8 to avoid wrapping around the counter */
-       load >>= CHAN_UTIL_SHIFT;
-
-       return load;
 }
 
-static ieee80211_txrx_result
-ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
+static void ieee80211_verify_ip_alignment(struct ieee80211_txrx_data *rx)
 {
+#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
        int hdrlen;
 
+       if (!WLAN_FC_DATA_PRESENT(rx->fc))
+               return;
+
        /*
         * Drivers are required to align the payload data in a way that
         * guarantees that the contained IP header is aligned to a four-
@@ -368,16 +312,42 @@ ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
        if (rx->flags & IEEE80211_TXRXD_RX_AMSDU)
                hdrlen += ETH_HLEN;
        WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
-
-       return TXRX_CONTINUE;
+#endif
 }
 
-ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
+
+static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
+                                  struct sk_buff *skb,
+                                  struct ieee80211_rx_status *status,
+                                  struct ieee80211_rate *rate)
 {
-       ieee80211_rx_h_parse_qos,
-       ieee80211_rx_h_verify_ip_alignment,
-       NULL
-};
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u32 load = 0, hdrtime;
+
+       /* Estimate total channel use caused by this frame */
+
+       /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
+        * 1 usec = 1/8 * (1080 / 10) = 13.5 */
+
+       if (status->band == IEEE80211_BAND_5GHZ ||
+           (status->band == IEEE80211_BAND_5GHZ &&
+            rate->flags & IEEE80211_RATE_ERP_G))
+               hdrtime = CHAN_UTIL_HDR_SHORT;
+       else
+               hdrtime = CHAN_UTIL_HDR_LONG;
+
+       load = hdrtime;
+       if (!is_multicast_ether_addr(hdr->addr1))
+               load += hdrtime;
+
+       /* TODO: optimise again */
+       load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
+
+       /* Divide channel_use by 8 to avoid wrapping around the counter */
+       load >>= CHAN_UTIL_SHIFT;
+
+       return load;
+}
 
 /* rx handlers */
 
@@ -1700,7 +1670,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
 static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                         struct sk_buff *skb,
                                         struct ieee80211_rx_status *status,
-                                        u32 load)
+                                        u32 load,
+                                        struct ieee80211_rate *rate)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_sub_if_data *sdata;
@@ -1720,6 +1691,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
        rx.u.rx.status = status;
        rx.u.rx.load = load;
+       rx.u.rx.rate = rate;
        rx.fc = le16_to_cpu(hdr->frame_control);
        type = rx.fc & IEEE80211_FCTL_FTYPE;
 
@@ -1740,9 +1712,9 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
                rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
 
-       if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
-                                          sta) != TXRX_CONTINUE)
-               goto end;
+       ieee80211_parse_qos(&rx);
+       ieee80211_verify_ip_alignment(&rx);
+
        skb = rx.skb;
 
        if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) &&
@@ -1852,6 +1824,8 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
        u16 head_seq_num, buf_size;
        int index;
        u32 pkt_load;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_rate *rate;
 
        buf_size = tid_agg_rx->buf_size;
        head_seq_num = tid_agg_rx->head_seq_num;
@@ -1882,12 +1856,14 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
                                memcpy(&status,
                                        tid_agg_rx->reorder_buf[index]->cb,
                                        sizeof(status));
+                               sband = local->hw.wiphy->bands[status.band];
+                               rate = &sband->bitrates[status.rate_idx];
                                pkt_load = ieee80211_rx_load_stats(local,
                                                tid_agg_rx->reorder_buf[index],
-                                               &status);
+                                               &status, rate);
                                __ieee80211_rx_handle_packet(hw,
                                        tid_agg_rx->reorder_buf[index],
-                                       &status, pkt_load);
+                                       &status, pkt_load, rate);
                                tid_agg_rx->stored_mpdu_num--;
                                tid_agg_rx->reorder_buf[index] = NULL;
                        }
@@ -1927,11 +1903,13 @@ u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
                /* release the reordered frame back to stack */
                memcpy(&status, tid_agg_rx->reorder_buf[index]->cb,
                        sizeof(status));
+               sband = local->hw.wiphy->bands[status.band];
+               rate = &sband->bitrates[status.rate_idx];
                pkt_load = ieee80211_rx_load_stats(local,
                                        tid_agg_rx->reorder_buf[index],
-                                       &status);
+                                       &status, rate);
                __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
-                                               &status, pkt_load);
+                                            &status, pkt_load, rate);
                tid_agg_rx->stored_mpdu_num--;
                tid_agg_rx->reorder_buf[index] = NULL;
                tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
@@ -1972,7 +1950,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
                goto end_reorder;
 
        /* null data frames are excluded */
-       if (unlikely(fc & IEEE80211_STYPE_QOS_NULLFUNC))
+       if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
                goto end_reorder;
 
        /* new un-ordered ampdu frame - process it */
@@ -2012,6 +1990,25 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
 {
        struct ieee80211_local *local = hw_to_local(hw);
        u32 pkt_load;
+       struct ieee80211_rate *rate = NULL;
+       struct ieee80211_supported_band *sband;
+
+       if (status->band < 0 ||
+           status->band > IEEE80211_NUM_BANDS) {
+               WARN_ON(1);
+               return;
+       }
+
+       sband = local->hw.wiphy->bands[status->band];
+
+       if (!sband ||
+           status->rate_idx < 0 ||
+           status->rate_idx >= sband->n_bitrates) {
+               WARN_ON(1);
+               return;
+       }
+
+       rate = &sband->bitrates[status->rate_idx];
 
        /*
         * key references and virtual interfaces are protected using RCU
@@ -2026,17 +2023,17 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
         * if it was previously present.
         * Also, frames with less than 16 bytes are dropped.
         */
-       skb = ieee80211_rx_monitor(local, skb, status);
+       skb = ieee80211_rx_monitor(local, skb, status, rate);
        if (!skb) {
                rcu_read_unlock();
                return;
        }
 
-       pkt_load = ieee80211_rx_load_stats(local, skb, status);
+       pkt_load = ieee80211_rx_load_stats(local, skb, status, rate);
        local->channel_use_raw += pkt_load;
 
        if (!ieee80211_rx_reorder_ampdu(local, skb))
-               __ieee80211_rx_handle_packet(hw, skb, status, pkt_load);
+               __ieee80211_rx_handle_packet(hw, skb, status, pkt_load, rate);
 
        rcu_read_unlock();
 }