qcacmn: Add support for delivering unencrypted errors

In mesh mode, it is possible to receive unencrypted frames while security
is enabled. Deliver such frames to OS stack.

Change-Id: Id148b6ecc1432b419ae97c92f2340155f3d851bf
CRs-Fixed: 2004658
This commit is contained in:
Pamidipati, Vijay 2017-05-01 00:55:56 +05:30 • committed by snandini
commit eb8a92cedc
4 changed files with 134 additions and 22 deletions

View file

@ -220,7 +220,7 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
*/
void
dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list,
struct cdp_peer *peer)
struct dp_peer *peer)
{
qdf_nbuf_t deliver_list_head = NULL;
qdf_nbuf_t deliver_list_tail = NULL;
@ -248,7 +248,7 @@ dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list,
}
vdev->osif_rsim_rx_decap(vdev->osif_vdev, &deliver_list_head,
&deliver_list_tail, peer);
&deliver_list_tail, (struct cdp_peer*) peer);
vdev->osif_rx(vdev->osif_vdev, deliver_list_head);
}
@ -1308,8 +1308,7 @@ done:
if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw) ||
(vdev->rx_decap_type == htt_cmn_pkt_type_native_wifi))
dp_rx_deliver_raw(vdev, deliver_list_head,
(struct cdp_peer *) peer);
dp_rx_deliver_raw(vdev, deliver_list_head, peer);
else if (qdf_likely(vdev->osif_rx) && deliver_list_head)
vdev->osif_rx(vdev->osif_vdev, deliver_list_head);
}

View file

@ -305,7 +305,7 @@ void dp_rx_desc_pool_free(struct dp_soc *soc,
struct rx_desc_pool *rx_desc_pool);
void dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list,
struct cdp_peer *peer);
struct dp_peer *peer);
/**
* dp_rx_add_to_free_desc_list() - Adds to a local free descriptor list

View file

@ -342,10 +342,7 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
* Advance the packet start pointer by total size of
* pre-header TLV's
*/
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
if (l2_hdr_offset)
qdf_nbuf_pull_head(nbuf, l2_hdr_offset);
qdf_nbuf_pull_head(nbuf, (l2_hdr_offset + RX_PKT_TLVS_LEN));
nbuf_data = qdf_nbuf_data(nbuf);
for (count = 0; count < soc->mect_cnt; count++) {
@ -393,7 +390,7 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw)) {
qdf_nbuf_set_next(nbuf, NULL);
dp_rx_deliver_raw(vdev, nbuf, (struct cdp_peer *) peer);
dp_rx_deliver_raw(vdev, nbuf, peer);
} else {
if (qdf_unlikely(peer->bss_peer)) {
QDF_TRACE(QDF_MODULE_ID_DP,
@ -423,6 +420,115 @@ fail:
return rx_bufs_used;
}
/**
* dp_rx_err_deliver() - Function to deliver error frames to OS
*
* @soc: core DP main context
* @rx_desc : pointer to the sw rx descriptor
* @head: pointer to head of rx descriptors to be added to free list
* @tail: pointer to tail of rx descriptors to be added to free list
* quota: upper limit of descriptors that can be reaped
*
* Return: uint32_t: No. of Rx buffers reaped
*/
static uint32_t
dp_rx_err_deliver(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail,
uint32_t quota)
{
uint32_t rx_bufs_used = 0;
uint32_t pkt_len, l2_hdr_offset;
uint16_t msdu_len;
qdf_nbuf_t nbuf;
struct dp_vdev *vdev;
uint16_t peer_id = 0xFFFF;
struct dp_peer *peer = NULL;
rx_bufs_used++;
nbuf = rx_desc->nbuf;
qdf_nbuf_unmap_single(soc->osdev, nbuf,
QDF_DMA_BIDIRECTIONAL);
rx_desc->rx_buf_start = qdf_nbuf_data(nbuf);
/*
* Check if DMA completed -- msdu_done is the last bit
* to be written
*/
if (!hal_rx_attn_msdu_done_get(rx_desc->rx_buf_start)) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("MSDU DONE failure"));
hal_rx_dump_pkt_tlvs(rx_desc->rx_buf_start,
QDF_TRACE_LEVEL_INFO);
qdf_assert(0);
}
peer_id = hal_rx_mpdu_start_sw_peer_id_get(rx_desc->rx_buf_start);
peer = dp_peer_find_by_id(soc, peer_id);
if (!peer) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("peer is NULL"));
DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1,
qdf_nbuf_len(nbuf));
/* Drop & free packet */
qdf_nbuf_free(nbuf);
goto fail;
}
vdev = peer->vdev;
if (!vdev) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
FL("INVALID vdev %p OR osif_rx"), vdev);
/* Drop & free packet */
qdf_nbuf_free(nbuf);
DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
goto fail;
}
/* Drop & free packet if mesh mode not enabled */
if (!vdev->mesh_vdev) {
qdf_nbuf_free(nbuf);
DP_STATS_INC(soc, rx.err.invalid_vdev, 1);
goto fail;
}
l2_hdr_offset =
hal_rx_msdu_end_l3_hdr_padding_get(rx_desc->rx_buf_start);
msdu_len =
hal_rx_msdu_start_msdu_len_get(rx_desc->rx_buf_start);
pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN;
/* Set length in nbuf */
qdf_nbuf_set_pktlen(nbuf, pkt_len);
qdf_nbuf_set_next(nbuf, NULL);
/*
* Advance the packet start pointer by total size of
* pre-header TLV's
*/
qdf_nbuf_pull_head(nbuf, (l2_hdr_offset + RX_PKT_TLVS_LEN));
if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw)) {
dp_rx_deliver_raw(vdev, nbuf, peer);
} else {
DP_STATS_INC(vdev->pdev, rx.to_stack.num, 1);
vdev->osif_rx(vdev->osif_vdev, nbuf);
}
fail:
dp_rx_add_to_free_desc_list(head, tail, rx_desc);
return rx_bufs_used;
}
/**
* dp_rx_link_desc_return() - Return a MPDU link descriptor to HW
* (WBM), following error handling
@ -432,7 +538,7 @@ fail:
*
* Return: QDF_STATUS
*/
static QDF_STATUS
static QDF_STATUS
dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc)
{
void *buf_addr_info = HAL_RX_REO_BUF_ADDR_INFO_GET(ring_desc);
@ -646,6 +752,7 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
struct dp_pdev *dp_pdev;
struct dp_srng *dp_rxdma_srng;
struct rx_desc_pool *rx_desc_pool;
uint8_t pool_id;
/* Debug -- Remove later */
qdf_assert(soc && hal_ring);
@ -702,6 +809,8 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
continue;
}
pool_id = rx_desc->pool_id;
/* XXX */
buf_type = HAL_RX_WBM_BUF_TYPE_GET(ring_desc);
@ -716,7 +825,6 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
HAL_RX_WBM_REO_PUSH_REASON_GET(ring_desc);
if (push_reason == HAL_RX_WBM_REO_PSH_RSN_ERROR) {
uint8_t reo_error_code =
HAL_RX_WBM_REO_ERROR_CODE_GET(ring_desc);
@ -734,11 +842,11 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
"Got pkt with REO ERROR: %d",
reo_error_code);
rx_bufs_used[rx_desc->pool_id] +=
rx_bufs_used[pool_id] +=
dp_rx_null_q_desc_handle(soc,
rx_desc,
&head[rx_desc->pool_id],
&tail[rx_desc->pool_id], quota);
&head[pool_id],
&tail[pool_id], quota);
continue;
/* TODO */
/* Add per error code accounting */
@ -763,15 +871,20 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
rxdma_error_code], 1);
switch (rxdma_error_code) {
/* TODO */
/* Add per error code accounting */
case HAL_RXDMA_ERR_UNENCRYPTED:
rx_bufs_used[pool_id] +=
dp_rx_err_deliver(soc,
rx_desc,
&head[pool_id],
&tail[pool_id],
quota);
continue;
default:
QDF_TRACE(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
"RXDMA error %d detected",
rxdma_error_code);
QDF_TRACE_LEVEL_ERROR,
"RXDMA error %d",
rxdma_error_code);
}
}
} else {

View file

@ -1827,7 +1827,7 @@ enum hal_rxdma_error_code {
HAL_RXDMA_ERR_FCS,
HAL_RXDMA_ERR_DECRYPT,
HAL_RXDMA_ERR_TKIP_MIC,
HAL_RXDMA_ERR_UNECRYPTED,
HAL_RXDMA_ERR_UNENCRYPTED,
HAL_RXDMA_ERR_MSDU_LEN,
HAL_RXDMA_ERR_MSDU_LIMIT,
HAL_RXDMA_ERR_WIFI_PARSE,