qcacld-3.0: Handle MIC Error in Chatter Mode

qcacld-2.0 to qcacld-3.0 propagation

Add support to handle an error indicated by the fw in offload mode.
In this case - MIC error type.

Change-Id: I53363bdbaafad7fab0a6e067a43892a3066abbb6
CRs-Fixed: 791274
This commit is contained in:
Dhanashri Atre 2015-11-19 10:56:53 -08:00 committed by Akash Patel
parent d8455813df
commit 1f0cbe43e3
5 changed files with 188 additions and 25 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
* Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@ -35,7 +35,7 @@
* based on the HTT message type.
* 2. functions that provide the info elements from specific HTT messages.
*/
#include <wma.h>
#include <htc_api.h> /* HTC_PACKET */
#include <htt.h> /* HTT_T2H_MSG_TYPE, etc. */
#include <cdf_nbuf.h> /* cdf_nbuf_t */
@ -49,6 +49,8 @@
#include <wdi_event.h>
#include <ol_htt_tx_api.h>
#include <ol_txrx_types.h>
#include <ol_txrx_peer_find.h>
/*--- target->host HTT message dispatch function ----------------------------*/
#ifndef DEBUG_CREDIT
@ -418,6 +420,55 @@ void htt_t2h_lp_msg_handler(void *context, cdf_nbuf_t htt_t2h_msg)
break;
}
case HTT_T2H_MSG_TYPE_RX_OFLD_PKT_ERR:
{
switch (HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(*msg_word)) {
case HTT_RX_OFLD_PKT_ERR_TYPE_MIC_ERR:
{
struct ol_error_info err_info;
struct ol_txrx_vdev_t *vdev;
struct ol_txrx_peer_t *peer;
uint16_t peer_id =
HTT_RX_OFLD_PKT_ERR_MIC_ERR_PEER_ID_GET
(*(msg_word + 1));
peer = ol_txrx_peer_find_by_id(pdev->txrx_pdev,
peer_id);
if (!peer) {
cdf_print("%s: invalid peer id %d\n",
__func__, peer_id);
cdf_assert(0);
break;
}
vdev = peer->vdev;
err_info.u.mic_err.vdev_id = vdev->vdev_id;
err_info.u.mic_err.key_id =
HTT_RX_OFLD_PKT_ERR_MIC_ERR_KEYID_GET
(*(msg_word + 1));
cdf_mem_copy(err_info.u.mic_err.da,
(uint8_t *)(msg_word + 2),
OL_TXRX_MAC_ADDR_LEN);
cdf_mem_copy(err_info.u.mic_err.sa,
(uint8_t *)(msg_word + 4),
OL_TXRX_MAC_ADDR_LEN);
cdf_mem_copy(&err_info.u.mic_err.pn,
(uint8_t *)(msg_word + 6), 6);
cdf_mem_copy(err_info.u.mic_err.ta,
peer->mac_addr.raw, OL_TXRX_MAC_ADDR_LEN);
wma_indicate_err(OL_RX_ERR_TKIP_MIC, &err_info);
break;
}
default:
{
cdf_print("%s: unhandled error type %d\n",
__func__,
HTT_RX_OFLD_PKT_ERR_MSG_SUB_TYPE_GET(*msg_word));
break;
}
}
}
default:
break;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
* Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@ -38,25 +38,9 @@
#include <ol_ctrl_api.h> /* ol_vdev_handle */
#include <ol_txrx_api.h> /* ol_txrx_peer_handle, etc. */
#include <ol_txrx_types.h> /* OL_TXRX_MAC_ADDR_LEN */
#include <cds_ieee80211_common.h> /* ieee80211_frame */
enum ol_rx_err_type {
OL_RX_ERR_DEFRAG_MIC,
OL_RX_ERR_PN,
OL_RX_ERR_UNKNOWN_PEER,
OL_RX_ERR_MALFORMED,
OL_RX_ERR_TKIP_MIC,
OL_RX_ERR_DECRYPT,
OL_RX_ERR_MPDU_LENGTH,
OL_RX_ERR_ENCRYPT_REQUIRED,
OL_RX_ERR_DUP,
OL_RX_ERR_UNKNOWN,
OL_RX_ERR_FCS,
OL_RX_ERR_PRIVACY,
OL_RX_ERR_NONE_FRAG,
OL_RX_ERR_NONE = 0xFF
};
#ifdef SUPPORT_HOST_STATISTICS
/** * @brief Update tx statistics
* @details
@ -186,5 +170,4 @@ void ol_tx_paused_peer_data(ol_peer_handle peer, int has_tx_data);
void ol_txrx_set_peer_authorized_event(struct ol_txrx_vdev_t *vdev);
#endif /* _OL_CTRL_TXRX_API__H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
* Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@ -47,9 +47,6 @@
#include "ol_txrx_htt_api.h"
#include "ol_htt_tx_api.h"
#include "ol_htt_rx_api.h"
#include <ol_ctrl_txrx_api.h>
#include <ol_txrx_ctrl_api.h>
/*
* The target may allocate multiple IDs for a peer.
@ -1008,4 +1005,50 @@ struct ol_txrx_peer_t {
uint16_t last_pkt_center_freq;
};
enum ol_rx_err_type {
OL_RX_ERR_DEFRAG_MIC,
OL_RX_ERR_PN,
OL_RX_ERR_UNKNOWN_PEER,
OL_RX_ERR_MALFORMED,
OL_RX_ERR_TKIP_MIC,
OL_RX_ERR_DECRYPT,
OL_RX_ERR_MPDU_LENGTH,
OL_RX_ERR_ENCRYPT_REQUIRED,
OL_RX_ERR_DUP,
OL_RX_ERR_UNKNOWN,
OL_RX_ERR_FCS,
OL_RX_ERR_PRIVACY,
OL_RX_ERR_NONE_FRAG,
OL_RX_ERR_NONE = 0xFF
};
/**
* ol_mic_error_info - carries the information associated with
* a MIC error
* @vdev_id: virtual device ID
* @key_id: Key ID
* @pn: packet number
* @sa: source address
* @da: destination address
* @ta: transmitter address
*/
struct ol_mic_error_info {
uint8_t vdev_id;
uint32_t key_id;
uint64_t pn;
uint8_t sa[OL_TXRX_MAC_ADDR_LEN];
uint8_t da[OL_TXRX_MAC_ADDR_LEN];
uint8_t ta[OL_TXRX_MAC_ADDR_LEN];
};
/**
* ol_error_info - carries the information associated with an
* error indicated by the firmware
* @mic_err: MIC error information
*/
struct ol_error_info {
union {
struct ol_mic_error_info mic_err;
} u;
};
#endif /* _OL_TXRX_TYPES__H_ */

View File

@ -2050,4 +2050,7 @@ static inline CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle,
return CDF_STATUS_SUCCESS;
}
#endif
void
wma_indicate_err(enum ol_rx_err_type err_type,
struct ol_error_info *err_info);
#endif

View File

@ -3077,3 +3077,86 @@ CDF_STATUS wma_lro_config_cmd(tp_wma_handle wma_handle,
return CDF_STATUS_SUCCESS;
}
#endif
/**
* wma_indicate_err() - indicate an error to the protocol stack
* @err_type: error type
* @err_info: information associated with the error
*
* This function indicates an error encountered in the data path
* to the protocol stack
*
* Return: none
*/
void
wma_indicate_err(
enum ol_rx_err_type err_type,
struct ol_error_info *err_info)
{
switch (err_type) {
case OL_RX_ERR_TKIP_MIC:
{
tp_wma_handle wma = cds_get_context(CDF_MODULE_ID_WMA);
tpSirSmeMicFailureInd mic_err_ind;
cds_msg_t cds_msg;
uint8_t vdev_id;
if (NULL == wma) {
WMA_LOGE("%s: Failed to get wma context",
__func__);
return;
}
mic_err_ind = cdf_mem_malloc(sizeof(*mic_err_ind));
if (!mic_err_ind) {
WMA_LOGE("%s: MIC indication mem alloc failed",
__func__);
return;
}
cdf_mem_set((void *) mic_err_ind, 0,
sizeof(*mic_err_ind));
mic_err_ind->messageType = eWNI_SME_MIC_FAILURE_IND;
mic_err_ind->length = sizeof(*mic_err_ind);
vdev_id = err_info->u.mic_err.vdev_id;
cdf_copy_macaddr(&mic_err_ind->bssId,
(struct cdf_mac_addr *) &wma->interfaces[vdev_id].bssid);
WMA_LOGE("MIC error: BSSID:%02x:%02x:%02x:%02x:%02x:%02x\n",
mic_err_ind->bssId.bytes[0], mic_err_ind->bssId.bytes[1],
mic_err_ind->bssId.bytes[2], mic_err_ind->bssId.bytes[3],
mic_err_ind->bssId.bytes[4], mic_err_ind->bssId.bytes[5]);
cdf_mem_copy(mic_err_ind->info.taMacAddr,
(struct cdf_mac_addr *) err_info->u.mic_err.ta,
sizeof(tSirMacAddr));
cdf_mem_copy(mic_err_ind->info.srcMacAddr,
(struct cdf_mac_addr *) err_info->u.mic_err.sa,
sizeof(tSirMacAddr));
cdf_mem_copy(mic_err_ind->info.dstMacAddr,
(struct cdf_mac_addr *) err_info->u.mic_err.da,
sizeof(tSirMacAddr));
mic_err_ind->info.keyId = err_info->u.mic_err.key_id;
mic_err_ind->info.multicast =
IEEE80211_IS_MULTICAST(err_info->u.mic_err.da);
cdf_mem_copy(mic_err_ind->info.TSC,
(void *)&err_info->
u.mic_err.pn, SIR_CIPHER_SEQ_CTR_SIZE);
cdf_mem_set(&cds_msg, sizeof(cds_msg_t), 0);
cds_msg.type = eWNI_SME_MIC_FAILURE_IND;
cds_msg.bodyptr = (void *) mic_err_ind;
if (CDF_STATUS_SUCCESS !=
cds_mq_post_message(CDS_MQ_ID_SME,
(cds_msg_t *) &cds_msg)) {
WMA_LOGE("%s: mic failure ind post to SME failed",
__func__);
cdf_mem_free((void *)mic_err_ind);
}
break;
}
default:
{
WMA_LOGE("%s: unhandled ol error type %d", __func__, err_type);
break;
}
}
}