diff options
author | Zhu Yi <yi.zhu@intel.com> | 2007-12-19 22:27:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:07:53 -0500 |
commit | 12342c475f5de17071eaf24ea2938ba8dfe285f2 (patch) | |
tree | a2cdfd191069397e093f2410009092e7e96c9325 /drivers/net/wireless/iwlwifi/iwl3945-base.c | |
parent | 7e94041ca17685cf12c658b8edc008dd0bdb00c7 (diff) |
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, | |||
1497 | return priv->ibss_beacon->len; | 1497 | return priv->ibss_beacon->len; |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | static int iwl3945_rate_index_from_plcp(int plcp) | ||
1501 | { | ||
1502 | int i = 0; | ||
1503 | |||
1504 | for (i = 0; i < IWL_RATE_COUNT; i++) | ||
1505 | if (iwl3945_rates[i].plcp == plcp) | ||
1506 | return i; | ||
1507 | return -1; | ||
1508 | } | ||
1509 | |||
1510 | static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) | 1500 | static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) |
1511 | { | 1501 | { |
1512 | u8 i; | 1502 | u8 i; |
@@ -3121,94 +3111,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, | |||
3121 | } | 3111 | } |
3122 | } | 3112 | } |
3123 | 3113 | ||
3124 | void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, | ||
3125 | struct iwl3945_rx_mem_buffer *rxb, | ||
3126 | void *data, short len, | ||
3127 | struct ieee80211_rx_status *stats, | ||
3128 | u16 phy_flags) | ||
3129 | { | ||
3130 | struct iwl3945_rt_rx_hdr *iwl3945_rt; | ||
3131 | |||
3132 | /* First cache any information we need before we overwrite | ||
3133 | * the information provided in the skb from the hardware */ | ||
3134 | s8 signal = stats->ssi; | ||
3135 | s8 noise = 0; | ||
3136 | int rate = stats->rate; | ||
3137 | u64 tsf = stats->mactime; | ||
3138 | __le16 phy_flags_hw = cpu_to_le16(phy_flags); | ||
3139 | |||
3140 | /* We received data from the HW, so stop the watchdog */ | ||
3141 | if (len > IWL_RX_BUF_SIZE - sizeof(*iwl3945_rt)) { | ||
3142 | IWL_DEBUG_DROP("Dropping too large packet in monitor\n"); | ||
3143 | return; | ||
3144 | } | ||
3145 | |||
3146 | /* copy the frame data to write after where the radiotap header goes */ | ||
3147 | iwl3945_rt = (void *)rxb->skb->data; | ||
3148 | memmove(iwl3945_rt->payload, data, len); | ||
3149 | |||
3150 | iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
3151 | iwl3945_rt->rt_hdr.it_pad = 0; /* always good to zero */ | ||
3152 | |||
3153 | /* total header + data */ | ||
3154 | iwl3945_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl3945_rt)); | ||
3155 | |||
3156 | /* Set the size of the skb to the size of the frame */ | ||
3157 | skb_put(rxb->skb, sizeof(*iwl3945_rt) + len); | ||
3158 | |||
3159 | /* Big bitfield of all the fields we provide in radiotap */ | ||
3160 | iwl3945_rt->rt_hdr.it_present = | ||
3161 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | | ||
3162 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
3163 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
3164 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
3165 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | ||
3166 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | ||
3167 | (1 << IEEE80211_RADIOTAP_ANTENNA)); | ||
3168 | |||
3169 | /* Zero the flags, we'll add to them as we go */ | ||
3170 | iwl3945_rt->rt_flags = 0; | ||
3171 | |||
3172 | iwl3945_rt->rt_tsf = cpu_to_le64(tsf); | ||
3173 | |||
3174 | /* Convert to dBm */ | ||
3175 | iwl3945_rt->rt_dbmsignal = signal; | ||
3176 | iwl3945_rt->rt_dbmnoise = noise; | ||
3177 | |||
3178 | /* Convert the channel frequency and set the flags */ | ||
3179 | iwl3945_rt->rt_channelMHz = cpu_to_le16(stats->freq); | ||
3180 | if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) | ||
3181 | iwl3945_rt->rt_chbitmask = | ||
3182 | cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); | ||
3183 | else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) | ||
3184 | iwl3945_rt->rt_chbitmask = | ||
3185 | cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); | ||
3186 | else /* 802.11g */ | ||
3187 | iwl3945_rt->rt_chbitmask = | ||
3188 | cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ)); | ||
3189 | |||
3190 | rate = iwl3945_rate_index_from_plcp(rate); | ||
3191 | if (rate == -1) | ||
3192 | iwl3945_rt->rt_rate = 0; | ||
3193 | else | ||
3194 | iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee; | ||
3195 | |||
3196 | /* antenna number */ | ||
3197 | iwl3945_rt->rt_antenna = | ||
3198 | le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; | ||
3199 | |||
3200 | /* set the preamble flag if we have it */ | ||
3201 | if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
3202 | iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
3203 | |||
3204 | IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); | ||
3205 | |||
3206 | stats->flag |= RX_FLAG_RADIOTAP; | ||
3207 | ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); | ||
3208 | rxb->skb = NULL; | ||
3209 | } | ||
3210 | |||
3211 | |||
3212 | #define IWL_PACKET_RETRY_TIME HZ | 3114 | #define IWL_PACKET_RETRY_TIME HZ |
3213 | 3115 | ||
3214 | int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) | 3116 | 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) | |||
4147 | * more buffers it will schedule replenish */ | 4049 | * more buffers it will schedule replenish */ |
4148 | break; | 4050 | break; |
4149 | } | 4051 | } |
4052 | |||
4053 | /* If radiotap head is required, reserve some headroom here. | ||
4054 | * The physical head count is a variable rx_stats->phy_count. | ||
4055 | * We reserve 4 bytes here. Plus these extra bytes, the | ||
4056 | * headroom of the physical head should be enough for the | ||
4057 | * radiotap head that iwl3945 supported. See iwl3945_rt. | ||
4058 | */ | ||
4059 | skb_reserve(rxb->skb, 4); | ||
4060 | |||
4150 | priv->alloc_rxb_skb++; | 4061 | priv->alloc_rxb_skb++; |
4151 | list_del(element); | 4062 | list_del(element); |
4152 | 4063 | ||
@@ -7114,6 +7025,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co | |||
7114 | mutex_lock(&priv->mutex); | 7025 | mutex_lock(&priv->mutex); |
7115 | IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); | 7026 | IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); |
7116 | 7027 | ||
7028 | priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); | ||
7029 | |||
7117 | if (!iwl3945_is_ready(priv)) { | 7030 | if (!iwl3945_is_ready(priv)) { |
7118 | IWL_DEBUG_MAC80211("leave - not ready\n"); | 7031 | IWL_DEBUG_MAC80211("leave - not ready\n"); |
7119 | ret = -EIO; | 7032 | ret = -EIO; |