mac80211: Add HT rates into RX status reporting
Jouni Malinen [Fri, 12 Dec 2008 12:38:33 +0000 (14:38 +0200)]
This patch adds option for HT-enabled drivers to report HT rates
(HT20/HT40, short GI, MCS index) to mac80211. These rates are
currently not in the rate table, so the rate_idx is used to indicate
MCS index.

Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

include/net/mac80211.h
net/mac80211/mlme.c
net/mac80211/rx.c

index 22ae72c..9428d3e 100644 (file)
@@ -436,6 +436,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  *     is valid. This is useful in monitor mode and necessary for beacon frames
  *     to enable IBSS merging.
  * @RX_FLAG_SHORTPRE: Short preamble was used for this frame
+ * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
+ * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
+ * @RX_FLAG_SHORT_GI: Short guard interval was used
  */
 enum mac80211_rx_flags {
        RX_FLAG_MMIC_ERROR      = 1<<0,
@@ -446,7 +449,10 @@ enum mac80211_rx_flags {
        RX_FLAG_FAILED_FCS_CRC  = 1<<5,
        RX_FLAG_FAILED_PLCP_CRC = 1<<6,
        RX_FLAG_TSFT            = 1<<7,
-       RX_FLAG_SHORTPRE        = 1<<8
+       RX_FLAG_SHORTPRE        = 1<<8,
+       RX_FLAG_HT              = 1<<9,
+       RX_FLAG_40MHZ           = 1<<10,
+       RX_FLAG_SHORT_GI        = 1<<11,
 };
 
 /**
@@ -466,7 +472,8 @@ enum mac80211_rx_flags {
  * @noise: noise when receiving this frame, in dBm.
  * @qual: overall signal quality indication, in percent (0-100).
  * @antenna: antenna used
- * @rate_idx: index of data rate into band's supported rates
+ * @rate_idx: index of data rate into band's supported rates or MCS index if
+ *     HT rates are use (RX_FLAG_HT)
  * @flag: %RX_FLAG_*
  */
 struct ieee80211_rx_status {
index e4d1fca..a444b38 100644 (file)
@@ -1613,8 +1613,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                         * e.g: at 1 MBit that means mactime is 192 usec earlier
                         * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
                         */
-                       int rate = local->hw.wiphy->bands[band]->
+                       int rate;
+                       if (rx_status->flag & RX_FLAG_HT) {
+                               rate = 65; /* TODO: HT rates */
+                       } else {
+                               rate = local->hw.wiphy->bands[band]->
                                        bitrates[rx_status->rate_idx].bitrate;
+                       }
                        rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
                } else if (local && local->ops && local->ops->get_tsf)
                        /* second best option: get current TSF */
index 73cf126..b729c00 100644 (file)
@@ -149,7 +149,17 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        pos++;
 
        /* IEEE80211_RADIOTAP_RATE */
-       *pos = rate->bitrate / 5;
+       if (status->flag & RX_FLAG_HT) {
+               /*
+                * TODO: add following information into radiotap header once
+                * suitable fields are defined for it:
+                * - MCS index (status->rate_idx)
+                * - HT40 (status->flag & RX_FLAG_40MHZ)
+                * - short-GI (status->flag & RX_FLAG_SHORT_GI)
+                */
+               *pos = 0;
+       } else
+               *pos = rate->bitrate / 5;
        pos++;
 
        /* IEEE80211_RADIOTAP_CHANNEL */
@@ -1849,9 +1859,15 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                        if (!(sdata->dev->flags & IFF_PROMISC))
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
-               } else if (!rx->sta)
+               } else if (!rx->sta) {
+                       int rate_idx;
+                       if (rx->status->flag & RX_FLAG_HT)
+                               rate_idx = 0; /* TODO: HT rates */
+                       else
+                               rate_idx = rx->status->rate_idx;
                        rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2,
-                               BIT(rx->status->rate_idx));
+                               BIT(rate_idx));
+               }
                break;
        case NL80211_IFTYPE_MESH_POINT:
                if (!multicast &&
@@ -2057,7 +2073,13 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
                                        tid_agg_rx->reorder_buf[index]->cb,
                                        sizeof(status));
                                sband = local->hw.wiphy->bands[status.band];
-                               rate = &sband->bitrates[status.rate_idx];
+                               if (status.flag & RX_FLAG_HT) {
+                                       /* TODO: HT rates */
+                                       rate = sband->bitrates;
+                               } else {
+                                       rate = &sband->bitrates
+                                               [status.rate_idx];
+                               }
                                __ieee80211_rx_handle_packet(hw,
                                        tid_agg_rx->reorder_buf[index],
                                        &status, rate);
@@ -2101,7 +2123,10 @@ static 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];
+               if (status.flag & RX_FLAG_HT)
+                       rate = sband->bitrates; /* TODO: HT rates */
+               else
+                       rate = &sband->bitrates[status.rate_idx];
                __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
                                             &status, rate);
                tid_agg_rx->stored_mpdu_num--;
@@ -2189,15 +2214,26 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
        }
 
        sband = local->hw.wiphy->bands[status->band];
-
-       if (!sband ||
-           status->rate_idx < 0 ||
-           status->rate_idx >= sband->n_bitrates) {
+       if (!sband) {
                WARN_ON(1);
                return;
        }
 
-       rate = &sband->bitrates[status->rate_idx];
+       if (status->flag & RX_FLAG_HT) {
+               /* rate_idx is MCS index */
+               if (WARN_ON(status->rate_idx < 0 ||
+                           status->rate_idx >= 76))
+                       return;
+               /* HT rates are not in the table - use the highest legacy rate
+                * for now since other parts of mac80211 may not yet be fully
+                * MCS aware. */
+               rate = &sband->bitrates[sband->n_bitrates - 1];
+       } else {
+               if (WARN_ON(status->rate_idx < 0 ||
+                           status->rate_idx >= sband->n_bitrates))
+                       return;
+               rate = &sband->bitrates[status->rate_idx];
+       }
 
        /*
         * key references and virtual interfaces are protected using RCU