*/
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;
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);
}
-/* 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;
/* 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-
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 */
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;
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;
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)) &&
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;
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;
}
/* 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);
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 */
{
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
* 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();
}