aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorNishant Sarmukadam <nishants@marvell.com>2010-12-30 14:23:33 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-19 11:36:06 -0500
commitd9a07d4980514e701555c4f03b865a54c4c48b4a (patch)
treefaefe4d3977cef4d6e6012cb409d50282c60b3f3 /drivers/net/wireless
parente53d9b964e2568172149d41b3157af9cde9accaf (diff)
mwl8k: Set mac80211 rx status flags appropriately when hw crypto is enabled
When hw crypto is enabled, set rx status flags appropriately depending on whether hw crypto is enabled for a particular bss. Also report MIC errors to mac80211, so that counter measures can be initiated Signed-off-by: Nishant Sarmukadam <nishants@marvell.com> Signed-off-by: yogesh powar <yogeshp@marvell.com> Signed-off-by: Thomas Pedersen <thomas@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mwl8k.c101
1 files changed, 98 insertions, 3 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 95bbdca0ba87..2b76bbc5e612 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -251,6 +251,12 @@ struct mwl8k_vif {
251 u8 enabled; 251 u8 enabled;
252 u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN]; 252 u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN];
253 } wep_key_conf[NUM_WEP_KEYS]; 253 } wep_key_conf[NUM_WEP_KEYS];
254
255 /* BSSID */
256 u8 bssid[ETH_ALEN];
257
258 /* A flag to indicate is HW crypto is enabled for this bssid */
259 bool is_hw_crypto_enabled;
254}; 260};
255#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) 261#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
256 262
@@ -834,6 +840,13 @@ struct mwl8k_rxd_8366_ap {
834 840
835#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 841#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80
836 842
843/* 8366 AP rx_status bits */
844#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80
845#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF
846#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02
847#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04
848#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08
849
837static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) 850static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
838{ 851{
839 struct mwl8k_rxd_8366_ap *rxd = _rxd; 852 struct mwl8k_rxd_8366_ap *rxd = _rxd;
@@ -894,6 +907,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
894 907
895 *qos = rxd->qos_control; 908 *qos = rxd->qos_control;
896 909
910 if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
911 (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) &&
912 (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
913 status->flag |= RX_FLAG_MMIC_ERROR;
914
897 return le16_to_cpu(rxd->pkt_len); 915 return le16_to_cpu(rxd->pkt_len);
898} 916}
899 917
@@ -932,6 +950,11 @@ struct mwl8k_rxd_sta {
932#define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 950#define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001
933 951
934#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 952#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02
953#define MWL8K_STA_RX_CTRL_DECRYPT_ERROR 0x04
954/* ICV=0 or MIC=1 */
955#define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE 0x08
956/* Key is uploaded only in failure case */
957#define MWL8K_STA_RX_CTRL_KEY_INDEX 0x30
935 958
936static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) 959static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
937{ 960{
@@ -990,6 +1013,9 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
990 status->freq = ieee80211_channel_to_frequency(rxd->channel); 1013 status->freq = ieee80211_channel_to_frequency(rxd->channel);
991 1014
992 *qos = rxd->qos_control; 1015 *qos = rxd->qos_control;
1016 if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
1017 (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE))
1018 status->flag |= RX_FLAG_MMIC_ERROR;
993 1019
994 return le16_to_cpu(rxd->pkt_len); 1020 return le16_to_cpu(rxd->pkt_len);
995} 1021}
@@ -1148,9 +1174,25 @@ static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
1148 ieee80211_queue_work(hw, &priv->finalize_join_worker); 1174 ieee80211_queue_work(hw, &priv->finalize_join_worker);
1149} 1175}
1150 1176
1177static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list,
1178 u8 *bssid)
1179{
1180 struct mwl8k_vif *mwl8k_vif;
1181
1182 list_for_each_entry(mwl8k_vif,
1183 vif_list, list) {
1184 if (memcmp(bssid, mwl8k_vif->bssid,
1185 ETH_ALEN) == 0)
1186 return mwl8k_vif;
1187 }
1188
1189 return NULL;
1190}
1191
1151static int rxq_process(struct ieee80211_hw *hw, int index, int limit) 1192static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1152{ 1193{
1153 struct mwl8k_priv *priv = hw->priv; 1194 struct mwl8k_priv *priv = hw->priv;
1195 struct mwl8k_vif *mwl8k_vif = NULL;
1154 struct mwl8k_rx_queue *rxq = priv->rxq + index; 1196 struct mwl8k_rx_queue *rxq = priv->rxq + index;
1155 int processed; 1197 int processed;
1156 1198
@@ -1160,6 +1202,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1160 void *rxd; 1202 void *rxd;
1161 int pkt_len; 1203 int pkt_len;
1162 struct ieee80211_rx_status status; 1204 struct ieee80211_rx_status status;
1205 struct ieee80211_hdr *wh;
1163 __le16 qos; 1206 __le16 qos;
1164 1207
1165 skb = rxq->buf[rxq->head].skb; 1208 skb = rxq->buf[rxq->head].skb;
@@ -1186,8 +1229,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1186 1229
1187 rxq->rxd_count--; 1230 rxq->rxd_count--;
1188 1231
1189 skb_put(skb, pkt_len); 1232 wh = &((struct mwl8k_dma_data *)skb->data)->wh;
1190 mwl8k_remove_dma_header(skb, qos);
1191 1233
1192 /* 1234 /*
1193 * Check for a pending join operation. Save a 1235 * Check for a pending join operation. Save a
@@ -1197,6 +1239,46 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1197 if (mwl8k_capture_bssid(priv, (void *)skb->data)) 1239 if (mwl8k_capture_bssid(priv, (void *)skb->data))
1198 mwl8k_save_beacon(hw, skb); 1240 mwl8k_save_beacon(hw, skb);
1199 1241
1242 if (ieee80211_has_protected(wh->frame_control)) {
1243
1244 /* Check if hw crypto has been enabled for
1245 * this bss. If yes, set the status flags
1246 * accordingly
1247 */
1248 mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list,
1249 wh->addr1);
1250
1251 if (mwl8k_vif != NULL &&
1252 mwl8k_vif->is_hw_crypto_enabled == true) {
1253 /*
1254 * When MMIC ERROR is encountered
1255 * by the firmware, payload is
1256 * dropped and only 32 bytes of
1257 * mwl8k Firmware header is sent
1258 * to the host.
1259 *
1260 * We need to add four bytes of
1261 * key information. In it
1262 * MAC80211 expects keyidx set to
1263 * 0 for triggering Counter
1264 * Measure of MMIC failure.
1265 */
1266 if (status.flag & RX_FLAG_MMIC_ERROR) {
1267 struct mwl8k_dma_data *tr;
1268 tr = (struct mwl8k_dma_data *)skb->data;
1269 memset((void *)&(tr->data), 0, 4);
1270 pkt_len += 4;
1271 }
1272
1273 if (!ieee80211_is_auth(wh->frame_control))
1274 status.flag |= RX_FLAG_IV_STRIPPED |
1275 RX_FLAG_DECRYPTED |
1276 RX_FLAG_MMIC_STRIPPED;
1277 }
1278 }
1279
1280 skb_put(skb, pkt_len);
1281 mwl8k_remove_dma_header(skb, qos);
1200 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); 1282 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
1201 ieee80211_rx_irqsafe(hw, skb); 1283 ieee80211_rx_irqsafe(hw, skb);
1202 1284
@@ -1499,7 +1581,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1499 else 1581 else
1500 qos = 0; 1582 qos = 0;
1501 1583
1502 mwl8k_encapsulate_tx_frame(skb); 1584 if (priv->ap_fw)
1585 mwl8k_encapsulate_tx_frame(skb);
1586 else
1587 mwl8k_add_dma_header(skb, 0);
1588
1503 wh = &((struct mwl8k_dma_data *)skb->data)->wh; 1589 wh = &((struct mwl8k_dma_data *)skb->data)->wh;
1504 1590
1505 tx_info = IEEE80211_SKB_CB(skb); 1591 tx_info = IEEE80211_SKB_CB(skb);
@@ -3525,6 +3611,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
3525 mwl8k_vif->vif = vif; 3611 mwl8k_vif->vif = vif;
3526 mwl8k_vif->macid = macid; 3612 mwl8k_vif->macid = macid;
3527 mwl8k_vif->seqno = 0; 3613 mwl8k_vif->seqno = 0;
3614 memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN);
3615 mwl8k_vif->is_hw_crypto_enabled = false;
3528 3616
3529 /* Set the mac address. */ 3617 /* Set the mac address. */
3530 mwl8k_cmd_set_mac_addr(hw, vif, vif->addr); 3618 mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
@@ -3930,9 +4018,16 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw,
3930 return 0; 4018 return 0;
3931 } 4019 }
3932 4020
4021 } else {
4022 ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
3933 return ret; 4023 return ret;
3934 } 4024 }
3935 4025
4026 for (i = 0; i < NUM_WEP_KEYS; i++) {
4027 key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
4028 if (mwl8k_vif->wep_key_conf[i].enabled)
4029 mwl8k_set_key(hw, SET_KEY, vif, sta, key);
4030 }
3936 return mwl8k_cmd_set_new_stn_add(hw, vif, sta); 4031 return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
3937} 4032}
3938 4033