Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9a07d49 authored by Nishant Sarmukadam's avatar Nishant Sarmukadam Committed by John W. Linville
Browse files

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: default avatarNishant Sarmukadam <nishants@marvell.com>
Signed-off-by: default avataryogesh powar <yogeshp@marvell.com>
Signed-off-by: default avatarThomas Pedersen <thomas@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e53d9b96
Loading
Loading
Loading
Loading
+98 −3
Original line number Diff line number Diff line
@@ -251,6 +251,12 @@ struct mwl8k_vif {
		u8 enabled;
		u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN];
	} wep_key_conf[NUM_WEP_KEYS];

	/* BSSID */
	u8 bssid[ETH_ALEN];

	/* A flag to indicate is HW crypto is enabled for this bssid */
	bool is_hw_crypto_enabled;
};
#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))

@@ -834,6 +840,13 @@ struct mwl8k_rxd_8366_ap {

#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST	0x80

/* 8366 AP rx_status bits */
#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK		0x80
#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR	0xFF
#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR	0x02
#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR	0x04
#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR	0x08

static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
{
	struct mwl8k_rxd_8366_ap *rxd = _rxd;
@@ -894,6 +907,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,

	*qos = rxd->qos_control;

	if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
	    (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) &&
	    (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
		status->flag |= RX_FLAG_MMIC_ERROR;

	return le16_to_cpu(rxd->pkt_len);
}

@@ -932,6 +950,11 @@ struct mwl8k_rxd_sta {
#define MWL8K_STA_RATE_INFO_MCS_FORMAT		0x0001

#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST		0x02
#define MWL8K_STA_RX_CTRL_DECRYPT_ERROR		0x04
/* ICV=0 or MIC=1 */
#define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE		0x08
/* Key is uploaded only in failure case */
#define MWL8K_STA_RX_CTRL_KEY_INDEX			0x30

static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
{
@@ -990,6 +1013,9 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
	status->freq = ieee80211_channel_to_frequency(rxd->channel);

	*qos = rxd->qos_control;
	if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
	    (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE))
		status->flag |= RX_FLAG_MMIC_ERROR;

	return le16_to_cpu(rxd->pkt_len);
}
@@ -1148,9 +1174,25 @@ static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
		ieee80211_queue_work(hw, &priv->finalize_join_worker);
}

static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list,
						   u8 *bssid)
{
	struct mwl8k_vif *mwl8k_vif;

	list_for_each_entry(mwl8k_vif,
			    vif_list, list) {
		if (memcmp(bssid, mwl8k_vif->bssid,
			   ETH_ALEN) == 0)
			return mwl8k_vif;
	}

	return NULL;
}

static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
{
	struct mwl8k_priv *priv = hw->priv;
	struct mwl8k_vif *mwl8k_vif = NULL;
	struct mwl8k_rx_queue *rxq = priv->rxq + index;
	int processed;

@@ -1160,6 +1202,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
		void *rxd;
		int pkt_len;
		struct ieee80211_rx_status status;
		struct ieee80211_hdr *wh;
		__le16 qos;

		skb = rxq->buf[rxq->head].skb;
@@ -1186,8 +1229,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)

		rxq->rxd_count--;

		skb_put(skb, pkt_len);
		mwl8k_remove_dma_header(skb, qos);
		wh = &((struct mwl8k_dma_data *)skb->data)->wh;

		/*
		 * Check for a pending join operation.  Save a
@@ -1197,6 +1239,46 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
		if (mwl8k_capture_bssid(priv, (void *)skb->data))
			mwl8k_save_beacon(hw, skb);

		if (ieee80211_has_protected(wh->frame_control)) {

			/* Check if hw crypto has been enabled for
			 * this bss. If yes, set the status flags
			 * accordingly
			 */
			mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list,
								wh->addr1);

			if (mwl8k_vif != NULL &&
			    mwl8k_vif->is_hw_crypto_enabled == true) {
				/*
				 * When MMIC ERROR is encountered
				 * by the firmware, payload is
				 * dropped and only 32 bytes of
				 * mwl8k Firmware header is sent
				 * to the host.
				 *
				 * We need to add four bytes of
				 * key information.  In it
				 * MAC80211 expects keyidx set to
				 * 0 for triggering Counter
				 * Measure of MMIC failure.
				 */
				if (status.flag & RX_FLAG_MMIC_ERROR) {
					struct mwl8k_dma_data *tr;
					tr = (struct mwl8k_dma_data *)skb->data;
					memset((void *)&(tr->data), 0, 4);
					pkt_len += 4;
				}

				if (!ieee80211_is_auth(wh->frame_control))
					status.flag |= RX_FLAG_IV_STRIPPED |
						       RX_FLAG_DECRYPTED |
						       RX_FLAG_MMIC_STRIPPED;
			}
		}

		skb_put(skb, pkt_len);
		mwl8k_remove_dma_header(skb, qos);
		memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
		ieee80211_rx_irqsafe(hw, skb);

@@ -1499,7 +1581,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
	else
		qos = 0;

	if (priv->ap_fw)
		mwl8k_encapsulate_tx_frame(skb);
	else
		mwl8k_add_dma_header(skb, 0);

	wh = &((struct mwl8k_dma_data *)skb->data)->wh;

	tx_info = IEEE80211_SKB_CB(skb);
@@ -3525,6 +3611,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
	mwl8k_vif->vif = vif;
	mwl8k_vif->macid = macid;
	mwl8k_vif->seqno = 0;
	memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN);
	mwl8k_vif->is_hw_crypto_enabled = false;

	/* Set the mac address.  */
	mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
@@ -3930,9 +4018,16 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw,
			return 0;
		}

	} else {
		ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
		return ret;
	}

	for (i = 0; i < NUM_WEP_KEYS; i++) {
		key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
		if (mwl8k_vif->wep_key_conf[i].enabled)
			mwl8k_set_key(hw, SET_KEY, vif, sta, key);
	}
	return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
}