aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl3945-base.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2007-12-19 22:27:32 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:07:53 -0500
commit12342c475f5de17071eaf24ea2938ba8dfe285f2 (patch)
treea2cdfd191069397e093f2410009092e7e96c9325 /drivers/net/wireless/iwlwifi/iwl3945-base.c
parent7e94041ca17685cf12c658b8edc008dd0bdb00c7 (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.c109
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
1500static 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
1510static u8 iwl3945_rate_get_lowest_plcp(int rate_mask) 1500static 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
3124void 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
3214int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) 3116int 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;