From 718d14b1ee2eb24076e2d16111401df2dcf19367 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Fri, 2 Aug 2019 09:48:34 +0530 Subject: [PATCH] qcacld-3.0: Add support for addba/delba HTT message In case of high latency data path, addba/delba messages needs to be handled to support partial reorder. This reverts commit b8919e14c5de8ab111d8c65eb3fa4df76c60032c and fix below security isses in ol_tx_addba_handler. 1. handle memory allocation failure scenario. 2. Free array memory before assign new memory to avoid memory leak. Change-Id: I4f577c9e8bcb40f70ffb1b305659a059eac68d8d CRs-Fixed: 2488966 --- core/dp/htt/htt_t2h.c | 25 ++++++- core/dp/ol/inc/ol_txrx_htt_api.h | 43 ++++++++++- core/dp/txrx/ol_rx_reorder.c | 120 ++++++++++++++++++++++++++++++- 3 files changed, 182 insertions(+), 6 deletions(-) diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index dc504d80ecc0..715a920bf448 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -337,12 +337,33 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg, } case HTT_T2H_MSG_TYPE_RX_ADDBA: { - qdf_print("HTT_T2H_MSG_TYPE_RX_ADDBA not supported "); + uint16_t peer_id; + uint8_t tid; + uint8_t win_sz; + uint16_t start_seq_num; + + /* + * FOR NOW, the host doesn't need to know the initial + * sequence number for rx aggregation. + * Thus, any value will do - specify 0. + */ + start_seq_num = 0; + peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); + tid = HTT_RX_ADDBA_TID_GET(*msg_word); + win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); + ol_rx_addba_handler(pdev->txrx_pdev, peer_id, tid, + win_sz, start_seq_num, + 0 /* success */); break; } case HTT_T2H_MSG_TYPE_RX_DELBA: { - qdf_print("HTT_T2H_MSG_TYPE_RX_DELBA not supported "); + uint16_t peer_id; + uint8_t tid; + + peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word); + tid = HTT_RX_DELBA_TID_GET(*msg_word); + ol_rx_delba_handler(pdev->txrx_pdev, peer_id, tid); break; } case HTT_T2H_MSG_TYPE_PEER_MAP: diff --git a/core/dp/ol/inc/ol_txrx_htt_api.h b/core/dp/ol/inc/ol_txrx_htt_api.h index 8c342dd058ae..c6e394ba97ba 100644 --- a/core/dp/ol/inc/ol_txrx_htt_api.h +++ b/core/dp/ol/inc/ol_txrx_htt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -503,6 +503,47 @@ ol_rx_sec_ind_handler(ol_txrx_pdev_handle pdev, enum htt_sec_type sec_type, int is_unicast, uint32_t *michael_key, uint32_t *rx_pn); +/** + * @brief Process an ADDBA message sent by the target. + * @details + * When the target notifies the host of an ADDBA event for a specified + * peer-TID, the host will set up the rx reordering state for the peer-TID. + * Specifically, the host will create a rx reordering array whose length + * is based on the window size specified in the ADDBA. + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - which peer the ADDBA event is for + * @param tid - which traffic ID within the peer the ADDBA event is for + * @param win_sz - how many sequence numbers are in the ARQ block ack window + * set up by the ADDBA event + * @param start_seq_num - the initial value of the sequence number during the + * block ack agreement, as specified by the ADDBA request. + * @param failed - indicate whether the target's ADDBA setup succeeded: + * 0 -> success, 1 -> fail + */ +void +ol_rx_addba_handler(ol_txrx_pdev_handle pdev, + uint16_t peer_id, + uint8_t tid, + uint8_t win_sz, uint16_t start_seq_num, uint8_t failed); + +/** + * @brief Process a DELBA message sent by the target. + * @details + * When the target notifies the host of a DELBA event for a specified + * peer-TID, the host will clean up the rx reordering state for the peer-TID. + * Specifically, the host will remove the rx reordering array, and will + * set the reorder window size to be 1 (stop and go ARQ). + * + * @param pdev - data physical device handle + * (registered with HTT as a context pointer during attach time) + * @param peer_id - which peer the ADDBA event is for + * @param tid - which traffic ID within the peer the ADDBA event is for + */ +void +ol_rx_delba_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id, uint8_t tid); + enum htt_rx_flush_action { htt_rx_flush_release, htt_rx_flush_discard, diff --git a/core/dp/txrx/ol_rx_reorder.c b/core/dp/txrx/ol_rx_reorder.c index 5ec5be971a10..8aa10215d78c 100644 --- a/core/dp/txrx/ol_rx_reorder.c +++ b/core/dp/txrx/ol_rx_reorder.c @@ -36,12 +36,24 @@ #include /*=== data types and defines ===*/ - -/*---*/ +#define OL_RX_REORDER_ROUND_PWR2(value) g_log2ceil[value] /*=== global variables ===*/ -/*---*/ +static char g_log2ceil[] = { + 1, /* 0 -> 1 */ + 1, /* 1 -> 1 */ + 2, /* 2 -> 2 */ + 4, 4, /* 3-4 -> 4 */ + 8, 8, 8, 8, /* 5-8 -> 8 */ + 16, 16, 16, 16, 16, 16, 16, 16, /* 9-16 -> 16 */ + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, /* 17-32 -> 32 */ + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, /* 33-64 -> 64 */ +}; /*=== function definitions ===*/ @@ -504,6 +516,108 @@ ol_rx_reorder_peer_cleanup(struct ol_txrx_vdev_t *vdev, /* functions called by HTT */ +void +ol_rx_addba_handler(ol_txrx_pdev_handle pdev, + uint16_t peer_id, + uint8_t tid, + uint8_t win_sz, uint16_t start_seq_num, uint8_t failed) +{ + uint8_t round_pwr2_win_sz; + unsigned int array_size; + struct ol_txrx_peer_t *peer; + struct ol_rx_reorder_t *rx_reorder; + void *array_mem = NULL; + + if (tid >= OL_TXRX_NUM_EXT_TIDS) { + ol_txrx_err("invalid tid, %u", tid); + WARN_ON(1); + return; + } + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (!peer) { + ol_txrx_err("not able to find peer, %u", peer_id); + return; + } + + if (pdev->cfg.host_addba) { + ol_ctrl_rx_addba_complete(pdev->ctrl_pdev, + &peer->mac_addr.raw[0], tid, failed); + } + if (failed) + return; + + peer->tids_last_seq[tid] = IEEE80211_SEQ_MAX; /* invalid */ + rx_reorder = &peer->tids_rx_reorder[tid]; + + TXRX_ASSERT2(win_sz <= 64); + round_pwr2_win_sz = OL_RX_REORDER_ROUND_PWR2(win_sz); + array_size = + round_pwr2_win_sz * sizeof(struct ol_rx_reorder_array_elem_t); + + array_mem = qdf_mem_malloc(array_size); + if (!array_mem) { + ol_txrx_err("memory allocation failed"); + return; + } + + if (rx_reorder->array != &rx_reorder->base) { + ol_txrx_info("delete array for tid %d", tid); + qdf_mem_free(rx_reorder->array); + } + + rx_reorder->array = array_mem; + rx_reorder->win_sz = win_sz; + TXRX_ASSERT1(rx_reorder->array); + + rx_reorder->win_sz_mask = round_pwr2_win_sz - 1; + rx_reorder->num_mpdus = 0; + + peer->tids_next_rel_idx[tid] = + OL_RX_REORDER_IDX_INIT(start_seq_num, rx_reorder->win_sz, + rx_reorder->win_sz_mask); +} + +void +ol_rx_delba_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id, uint8_t tid) +{ + struct ol_txrx_peer_t *peer; + struct ol_rx_reorder_t *rx_reorder; + + if (tid >= OL_TXRX_NUM_EXT_TIDS) { + ol_txrx_err("invalid tid, %u", tid); + WARN_ON(1); + return; + } + + peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (!peer) { + ol_txrx_err("not able to find peer, %u", peer_id); + return; + } + + peer->tids_next_rel_idx[tid] = INVALID_REORDER_INDEX; + rx_reorder = &peer->tids_rx_reorder[tid]; + + /* check that there really was a block ack agreement */ + TXRX_ASSERT1(rx_reorder->win_sz_mask != 0); + /* + * Deallocate the old rx reorder array. + * The call to ol_rx_reorder_init below + * will reset rx_reorder->array to point to + * the single-element statically-allocated reorder array + * used for non block-ack cases. + */ + if (rx_reorder->array != &rx_reorder->base) { + ol_txrx_dbg("delete reorder array, tid:%d", + tid); + qdf_mem_free(rx_reorder->array); + } + + /* set up the TID with default parameters (ARQ window size = 1) */ + ol_rx_reorder_init(rx_reorder, tid); +} + void ol_rx_flush_handler(ol_txrx_pdev_handle pdev, uint16_t peer_id,