diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 639c34506c8a..4a12bddcba46 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -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 #include /* HTC_PACKET */ #include /* HTT_T2H_MSG_TYPE, etc. */ #include /* cdf_nbuf_t */ @@ -49,6 +49,8 @@ #include #include #include +#include + /*--- 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; }; diff --git a/core/dp/txrx/ol_ctrl_txrx_api.h b/core/dp/txrx/ol_ctrl_txrx_api.h index 49a952e2733f..5a0d50f425b5 100644 --- a/core/dp/txrx/ol_ctrl_txrx_api.h +++ b/core/dp/txrx/ol_ctrl_txrx_api.h @@ -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_vdev_handle */ #include /* ol_txrx_peer_handle, etc. */ +#include /* OL_TXRX_MAC_ADDR_LEN */ #include /* 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_ */ diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index 3fc470bd107e..eab2ca009305 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -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 -#include - /* * 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_ */ diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 372d01defdfb..d338238480eb 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -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 diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 91bb65d4b57c..4054fd51e5fc 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -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; + } + } +}