diff options
author | Zhu Yi <yi.zhu@intel.com> | 2007-12-20 11:27:32 +0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 15:07:53 -0800 |
commit | 12342c475f5de17071eaf24ea2938ba8dfe285f2 (patch) | |
tree | a2cdfd191069397e093f2410009092e7e96c9325 /drivers/net/wireless/iwlwifi/iwl3945-base.c | |
parent | 7e94041ca17685cf12c658b8edc008dd0bdb00c7 (diff) | |
download | talos-obmc-linux-12342c475f5de17071eaf24ea2938ba8dfe285f2.tar.gz talos-obmc-linux-12342c475f5de17071eaf24ea2938ba8dfe285f2.zip |
iwlwifi: proper monitor support
This patch changes the iwlwifi driver to properly support
monitor interfaces after the filter flags change.
The patch is originally created by Johannes Berg for iwl4965. I fixed some
of the comments and created a similar patch for iwl3945.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 109 |
1 files changed, 11 insertions, 98 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c366ad55f70e..40b69182e4dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1497,16 +1497,6 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, return priv->ibss_beacon->len; } -static int iwl3945_rate_index_from_plcp(int plcp) -{ - int i = 0; - - for (i = 0; i < IWL_RATE_COUNT; i++) - if (iwl3945_rates[i].plcp == plcp) - return i; - return -1; -} - static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) { u8 i; @@ -3121,94 +3111,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, } } -void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb, - void *data, short len, - struct ieee80211_rx_status *stats, - u16 phy_flags) -{ - struct iwl3945_rt_rx_hdr *iwl3945_rt; - - /* First cache any information we need before we overwrite - * the information provided in the skb from the hardware */ - s8 signal = stats->ssi; - s8 noise = 0; - int rate = stats->rate; - u64 tsf = stats->mactime; - __le16 phy_flags_hw = cpu_to_le16(phy_flags); - - /* We received data from the HW, so stop the watchdog */ - if (len > IWL_RX_BUF_SIZE - sizeof(*iwl3945_rt)) { - IWL_DEBUG_DROP("Dropping too large packet in monitor\n"); - return; - } - - /* copy the frame data to write after where the radiotap header goes */ - iwl3945_rt = (void *)rxb->skb->data; - memmove(iwl3945_rt->payload, data, len); - - iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - iwl3945_rt->rt_hdr.it_pad = 0; /* always good to zero */ - - /* total header + data */ - iwl3945_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl3945_rt)); - - /* Set the size of the skb to the size of the frame */ - skb_put(rxb->skb, sizeof(*iwl3945_rt) + len); - - /* Big bitfield of all the fields we provide in radiotap */ - iwl3945_rt->rt_hdr.it_present = - cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA)); - - /* Zero the flags, we'll add to them as we go */ - iwl3945_rt->rt_flags = 0; - - iwl3945_rt->rt_tsf = cpu_to_le64(tsf); - - /* Convert to dBm */ - iwl3945_rt->rt_dbmsignal = signal; - iwl3945_rt->rt_dbmnoise = noise; - - /* Convert the channel frequency and set the flags */ - iwl3945_rt->rt_channelMHz = cpu_to_le16(stats->freq); - if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) - iwl3945_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); - else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) - iwl3945_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); - else /* 802.11g */ - iwl3945_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ)); - - rate = iwl3945_rate_index_from_plcp(rate); - if (rate == -1) - iwl3945_rt->rt_rate = 0; - else - iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee; - - /* antenna number */ - iwl3945_rt->rt_antenna = - le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; - - /* set the preamble flag if we have it */ - if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) - iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); - - stats->flag |= RX_FLAG_RADIOTAP; - ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); - rxb->skb = NULL; -} - - #define IWL_PACKET_RETRY_TIME HZ int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) @@ -4147,6 +4049,15 @@ static void iwl3945_rx_allocate(struct iwl3945_priv *priv) * more buffers it will schedule replenish */ break; } + + /* If radiotap head is required, reserve some headroom here. + * The physical head count is a variable rx_stats->phy_count. + * We reserve 4 bytes here. Plus these extra bytes, the + * headroom of the physical head should be enough for the + * radiotap head that iwl3945 supported. See iwl3945_rt. + */ + skb_reserve(rxb->skb, 4); + priv->alloc_rxb_skb++; list_del(element); @@ -7114,6 +7025,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); + priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); + if (!iwl3945_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); ret = -EIO; |