qcacmn: Waikiki tx monitor packet construction
Added function to construct packet and send to stack after parsing. Change-Id: I4621eb24840253db261aea63079e27f744f92698 CRs-Fixed: 3115608
This commit is contained in:

committed by
Madan Koyyalamudi

parent
dffdb7c215
commit
f0064e8e52
@@ -106,12 +106,96 @@ dp_tx_mon_process_2_0(struct dp_soc *soc, struct dp_intr *int_ctx,
|
||||
#define MAX_STATUS_BUFFER_IN_PPDU (64)
|
||||
#define TXMON_NO_BUFFER_SZ (64)
|
||||
|
||||
#define TXMON_PPDU(ppdu_info, field) ppdu_info->field
|
||||
#define TXMON_PPDU_USR(ppdu_info, user_index, field) \
|
||||
#define DP_BA_ACK_FRAME_SIZE (sizeof(struct ieee80211_ctlframe_addr2) + 36)
|
||||
#define DP_ACK_FRAME_SIZE (sizeof(struct ieee80211_frame_min_one))
|
||||
#define DP_CTS_FRAME_SIZE (sizeof(struct ieee80211_frame_min_one))
|
||||
#define DP_ACKNOACK_FRAME_SIZE (sizeof(struct ieee80211_frame) + 16)
|
||||
|
||||
#define DP_IEEE80211_BAR_CTL_TID_S 12
|
||||
#define DP_IEEE80211_BAR_CTL_TID_M 0xf
|
||||
#define DP_IEEE80211_BAR_CTL_POLICY_S 0
|
||||
#define DP_IEEE80211_BAR_CTL_POLICY_M 0x1
|
||||
#define DP_IEEE80211_BA_S_SEQ_S 4
|
||||
#define DP_IEEE80211_BAR_CTL_COMBA 0x0004
|
||||
|
||||
#define TXMON_PPDU(ppdu_info, field) ppdu_info->field
|
||||
#define TXMON_PPDU_USR(ppdu_info, user_index, field) \
|
||||
ppdu_info->hal_txmon.rx_user_status[user_index].field
|
||||
#define TXMON_PPDU_COM(ppdu_info, field) ppdu_info->hal_txmon.rx_status.field
|
||||
#define TXMON_PPDU_HAL(ppdu_info, field) ppdu_info->hal_txmon.field
|
||||
|
||||
#define HE_DATA_CNT 6
|
||||
|
||||
/**
|
||||
* bf_type - tx monitor supported Beamformed type
|
||||
*/
|
||||
enum bf_type {
|
||||
NO_BF = 0,
|
||||
LEGACY_BF,
|
||||
SU_BF,
|
||||
MU_BF
|
||||
};
|
||||
|
||||
/**
|
||||
* dot11b_preamble_type - tx monitor supported 11b preamble type
|
||||
*/
|
||||
enum dot11b_preamble_type {
|
||||
SHORT_PREAMBLE = 0,
|
||||
LONG_PREAMBLE,
|
||||
};
|
||||
|
||||
/**
|
||||
* bw_type - tx monitor supported bandwidth type
|
||||
*/
|
||||
enum bw_type {
|
||||
TXMON_BW_20_MHZ = 0,
|
||||
TXMON_BW_40_MHZ,
|
||||
TXMON_BW_80_MHZ,
|
||||
TXMON_BW_160_MHZ,
|
||||
TXMON_BW_240_MHZ,
|
||||
TXMON_BW_320_MHZ
|
||||
};
|
||||
|
||||
/**
|
||||
* ppdu_start_reason - tx monitor supported PPDU start reason type
|
||||
*/
|
||||
enum ppdu_start_reason {
|
||||
TXMON_FES_PROTECTION_FRAME,
|
||||
TXMON_FES_AFTER_PROTECTION,
|
||||
TXMON_FES_ONLY,
|
||||
TXMON_RESPONSE_FRAME,
|
||||
TXMON_TRIG_RESPONSE_FRAME,
|
||||
TXMON_DYNAMIC_PROTECTION_FES_ONLY
|
||||
};
|
||||
|
||||
/**
|
||||
* guard_interval - tx monitor supported Guard interval type
|
||||
*/
|
||||
enum guard_interval {
|
||||
TXMON_GI_0_8_US = 0,
|
||||
TXMON_GI_0_4_US,
|
||||
TXMON_GI_1_6_US,
|
||||
TXMON_GI_3_2_US
|
||||
};
|
||||
|
||||
/**
|
||||
* RU_size_start - tx monitor supported RU size start type
|
||||
*/
|
||||
enum RU_size_start {
|
||||
TXMON_RU_26 = 0,
|
||||
TXMON_RU_52,
|
||||
TXMON_RU_106,
|
||||
TXMON_RU_242,
|
||||
TXMON_RU_484,
|
||||
TXMON_RU_996,
|
||||
TXMON_RU_1992,
|
||||
TXMON_RU_FULLBW_240,
|
||||
TXMON_RU_FULLBW_320,
|
||||
TXMON_RU_MULTI_LARGE,
|
||||
TXMON_RU_78,
|
||||
TXMON_RU_132
|
||||
};
|
||||
|
||||
/**
|
||||
* response_type_expected - expected response type
|
||||
*/
|
||||
@@ -144,6 +228,16 @@ enum response_type_expected {
|
||||
TXMON_RESP_UL_MU_RANGING_LMR
|
||||
};
|
||||
|
||||
/**
|
||||
* resposne_to_respone - tx monitor supported response to response type
|
||||
*/
|
||||
enum resposne_to_respone {
|
||||
TXMON_RESP_TO_RESP_NONE = 0,
|
||||
TXMON_RESP_TO_RESP_SU_BA,
|
||||
TXMON_RESP_TO_RESP_MU_BA,
|
||||
TXMON_RESP_TO_RESP_CMD
|
||||
};
|
||||
|
||||
/**
|
||||
* medium_protection_type - tx monitor supported protection type
|
||||
*/
|
||||
@@ -157,12 +251,22 @@ enum medium_protection_type {
|
||||
TXMON_MEDIUM_QOS_NULL_NO_ACK_4ADDR,
|
||||
};
|
||||
|
||||
/**
|
||||
* ndp_frame - tx monitor supported ndp frame type
|
||||
*/
|
||||
enum ndp_frame {
|
||||
TXMON_NO_NDP_TRANSMISSION,
|
||||
TXMON_BEAMFORMING_NDP,
|
||||
TXMON_HE_RANGING_NDP,
|
||||
TXMON_HE_FEEDBACK_NDP,
|
||||
};
|
||||
|
||||
/**
|
||||
* tx_ppdu_info_type - tx monitor supported ppdu type
|
||||
*/
|
||||
enum tx_ppdu_info_type {
|
||||
TX_PROT_PPDU_INFO,
|
||||
TX_DATA_PPDU_INFO
|
||||
TX_DATA_PPDU_INFO,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -217,6 +217,54 @@ dp_tx_mon_generate_cts2self_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate CTS/ CTS2SELF frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
uint16_t duration_le = 0;
|
||||
struct ieee80211_frame_min_one *wh_min = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
|
||||
/*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
|
||||
if (!mpdu_nbuf)
|
||||
return;
|
||||
|
||||
wh_min = (struct ieee80211_frame_min_one *)qdf_nbuf_data(mpdu_nbuf);
|
||||
qdf_mem_zero(wh_min, MAX_DUMMY_FRM_BODY);
|
||||
|
||||
wh_min->i_fc[1] = 0;
|
||||
wh_min->i_fc[0] = (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
|
||||
IEEE80211_FC0_SUBTYPE_CTS);
|
||||
duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
|
||||
wh_min->i_dur[1] = (duration_le & 0xFF00) >> 8;
|
||||
wh_min->i_dur[0] = (duration_le & 0xFF);
|
||||
|
||||
qdf_mem_copy(wh_min->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min));
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,6 +280,56 @@ dp_tx_mon_generate_rts_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate RTS frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
uint16_t duration_le = 0;
|
||||
struct ieee80211_ctlframe_addr2 *wh_min = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
/*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
|
||||
if (!mpdu_nbuf)
|
||||
return;
|
||||
|
||||
wh_min = (struct ieee80211_ctlframe_addr2 *)qdf_nbuf_data(mpdu_nbuf);
|
||||
qdf_mem_zero(wh_min, MAX_DUMMY_FRM_BODY);
|
||||
|
||||
wh_min->i_fc[1] = 0;
|
||||
wh_min->i_fc[0] = (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
|
||||
IEEE80211_FC0_SUBTYPE_RTS);
|
||||
duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
|
||||
wh_min->i_aidordur[1] = (duration_le & 0xFF00) >> 8;
|
||||
wh_min->i_aidordur[0] = (duration_le & 0xFF);
|
||||
|
||||
qdf_mem_copy(wh_min->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_min->i_addr2,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr2),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_min));
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,6 +345,50 @@ dp_tx_mon_generate_ack_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate ACK frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
struct ieee80211_frame_min_one *wh_addr1 = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
uint8_t user_id = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
/*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
|
||||
if (!mpdu_nbuf)
|
||||
return;
|
||||
|
||||
wh_addr1 = (struct ieee80211_frame_min_one *)qdf_nbuf_data(mpdu_nbuf);
|
||||
wh_addr1->i_fc[1] = 0;
|
||||
wh_addr1->i_fc[0] = (IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
|
||||
IEEE80211_FC0_SUBTYPE_ACK);
|
||||
qdf_mem_copy(wh_addr1->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
/* set duration zero for ack frame */
|
||||
*(u_int16_t *)(&wh_addr1->i_dur) = qdf_cpu_to_le16(0x0000);
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr1));
|
||||
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, user_id, mpdu_nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,6 +406,62 @@ dp_tx_mon_generate_3addr_qos_null_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate 3 address qos null frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
struct ieee80211_qosframe *wh_addr3 = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
uint16_t duration_le = 0;
|
||||
uint8_t num_users = 0;
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
/*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
|
||||
if (!mpdu_nbuf)
|
||||
return;
|
||||
|
||||
wh_addr3 = (struct ieee80211_qosframe *)qdf_nbuf_data(mpdu_nbuf);
|
||||
qdf_mem_zero(wh_addr3, sizeof(struct ieee80211_qosframe));
|
||||
wh_addr3->i_fc[0] = 0;
|
||||
wh_addr3->i_fc[1] = 0;
|
||||
wh_addr3->i_fc[0] = (IEEE80211_FC0_VERSION_0 |
|
||||
IEEE80211_FC0_TYPE_DATA |
|
||||
IEEE80211_FC0_SUBTYPE_QOS_NULL);
|
||||
|
||||
duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
|
||||
wh_addr3->i_dur[1] = (duration_le & 0xFF00) >> 8;
|
||||
wh_addr3->i_dur[0] = (duration_le & 0xFF);
|
||||
|
||||
qdf_mem_copy(wh_addr3->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr3->i_addr2,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr2),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr3->i_addr3,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr3),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr3));
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, num_users, mpdu_nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,8 +479,76 @@ dp_tx_mon_generate_4addr_qos_null_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate 4 address qos null frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
struct ieee80211_qosframe_addr4 *wh_addr4 = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
uint16_t duration_le = 0;
|
||||
uint8_t num_users = 0;
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
/*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
MAX_DUMMY_FRM_BODY, 0, 4, FALSE);
|
||||
if (!mpdu_nbuf)
|
||||
return;
|
||||
|
||||
wh_addr4 = (struct ieee80211_qosframe_addr4 *)qdf_nbuf_data(mpdu_nbuf);
|
||||
qdf_mem_zero(wh_addr4, sizeof(struct ieee80211_qosframe_addr4));
|
||||
wh_addr4->i_fc[1] = 0;
|
||||
wh_addr4->i_fc[0] = (IEEE80211_FC0_VERSION_0 |
|
||||
IEEE80211_FC0_TYPE_DATA |
|
||||
IEEE80211_FC0_SUBTYPE_QOS_NULL);
|
||||
|
||||
duration_le = qdf_cpu_to_le16(TXMON_PPDU_COM(tx_ppdu_info, duration));
|
||||
wh_addr4->i_dur[1] = (duration_le & 0xFF00) >> 8;
|
||||
wh_addr4->i_dur[0] = (duration_le & 0xFF);
|
||||
|
||||
qdf_mem_copy(wh_addr4->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr4->i_addr2,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr2),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr4->i_addr3,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr3),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr4->i_addr4,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr4),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf, sizeof(*wh_addr4));
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, num_users, mpdu_nbuf);
|
||||
}
|
||||
|
||||
#define TXMON_BA_CTRL_SZ 2
|
||||
#define TXMON_BA_INFO_SZ(bitmap_sz) ((4 * (bitmap_sz)) + 6)
|
||||
#define TXMON_MU_BA_ACK_FRAME_SZ(bitmap_sz) \
|
||||
(sizeof(struct ieee80211_ctlframe_addr2) +\
|
||||
TXMON_BA_CTRL_SZ + (bitmap_sz))
|
||||
|
||||
#define TXMON_BA_ACK_FRAME_SZ(bitmap_sz) \
|
||||
(sizeof(struct ieee80211_ctlframe_addr2) +\
|
||||
TXMON_BA_CTRL_SZ + TXMON_BA_INFO_SZ(bitmap_sz))
|
||||
|
||||
/**
|
||||
* dp_tx_mon_generate_mu_block_ack_frm() - API to generate MU block ack frame
|
||||
* @pdev: pdev Handle
|
||||
@@ -296,6 +562,99 @@ dp_tx_mon_generate_mu_block_ack_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate MU block ack frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
uint8_t *frm = NULL;
|
||||
uint32_t ba_sz = 0;
|
||||
uint8_t num_users = TXMON_PPDU_HAL(tx_ppdu_info, num_users);
|
||||
uint8_t i = 0;
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
for (i = 0; i < num_users; i++)
|
||||
ba_sz += (4 << TXMON_BA_INFO_SZ(TXMON_PPDU_USR(tx_ppdu_info,
|
||||
i,
|
||||
ba_bitmap_sz)));
|
||||
|
||||
/*
|
||||
* for multi sta block ack, do we need to increase the size
|
||||
* or copy info on subsequent frame offset
|
||||
*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
TXMON_MU_BA_ACK_FRAME_SZ(ba_sz), 0, 4,
|
||||
FALSE);
|
||||
if (!mpdu_nbuf) {
|
||||
/* TODO: update status and break */
|
||||
return;
|
||||
}
|
||||
|
||||
wh_addr2 = (struct ieee80211_ctlframe_addr2 *)qdf_nbuf_data(mpdu_nbuf);
|
||||
qdf_mem_zero(wh_addr2, DP_BA_ACK_FRAME_SIZE);
|
||||
|
||||
wh_addr2->i_fc[0] = 0;
|
||||
wh_addr2->i_fc[1] = 0;
|
||||
wh_addr2->i_fc[0] = (IEEE80211_FC0_VERSION_0 |
|
||||
IEEE80211_FC0_TYPE_CTL |
|
||||
IEEE80211_FC0_BLOCK_ACK);
|
||||
*(u_int16_t *)(&wh_addr2->i_aidordur) = qdf_cpu_to_le16(0x0000);
|
||||
|
||||
qdf_mem_copy(wh_addr2->i_addr2,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr2),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr2->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
frm = (uint8_t *)&wh_addr2[6];
|
||||
|
||||
frm += 1;
|
||||
/* BA control */
|
||||
*((uint16_t *)frm) = qdf_cpu_to_le16(TXMON_PPDU_USR(tx_ppdu_info,
|
||||
0, ba_control));
|
||||
frm += 2;
|
||||
|
||||
for (i = 0; i < num_users; i++) {
|
||||
*((uint16_t *)frm) =
|
||||
qdf_cpu_to_le16((TXMON_PPDU_USR(tx_ppdu_info, i, tid) <<
|
||||
DP_IEEE80211_BAR_CTL_TID_S) |
|
||||
(TXMON_PPDU_USR(tx_ppdu_info, i,
|
||||
aid) & 0x7FF));
|
||||
frm += 2;
|
||||
*((uint16_t *)frm) = TXMON_PPDU_USR(tx_ppdu_info,
|
||||
i, start_seq) & 0xFFF;
|
||||
frm += 2;
|
||||
qdf_mem_copy(frm,
|
||||
TXMON_PPDU_USR(tx_ppdu_info, i, ba_bitmap),
|
||||
4 <<
|
||||
TXMON_PPDU_USR(tx_ppdu_info,
|
||||
i, ba_bitmap_sz));
|
||||
frm += 4 << TXMON_PPDU_USR(tx_ppdu_info, i, ba_bitmap_sz);
|
||||
}
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf,
|
||||
(frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
|
||||
|
||||
/* always enqueue to first active user */
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,6 +670,119 @@ dp_tx_mon_generate_block_ack_frm(struct dp_pdev *pdev,
|
||||
{
|
||||
/* allocate and populate block ack frame */
|
||||
/* enqueue 802.11 payload to per user mpdu_q */
|
||||
struct dp_mon_pdev *mon_pdev;
|
||||
struct dp_mon_pdev_be *mon_pdev_be;
|
||||
struct dp_pdev_tx_capture_be *tx_cap_be;
|
||||
struct hal_tx_status_info *tx_status_info;
|
||||
struct ieee80211_ctlframe_addr2 *wh_addr2 = NULL;
|
||||
qdf_nbuf_t mpdu_nbuf = NULL;
|
||||
uint8_t *frm = NULL;
|
||||
uint8_t user_id = TXMON_PPDU(tx_ppdu_info, cur_usr_idx);
|
||||
uint32_t ba_bitmap_sz = TXMON_PPDU_USR(tx_ppdu_info,
|
||||
user_id, ba_bitmap_sz);
|
||||
|
||||
/* sanity check */
|
||||
if (qdf_unlikely(!pdev))
|
||||
return;
|
||||
|
||||
mon_pdev = pdev->monitor_pdev;
|
||||
if (qdf_unlikely(!mon_pdev))
|
||||
return;
|
||||
|
||||
mon_pdev_be = dp_get_be_mon_pdev_from_dp_mon_pdev(mon_pdev);
|
||||
if (qdf_unlikely(!mon_pdev_be))
|
||||
return;
|
||||
|
||||
tx_cap_be = &mon_pdev_be->tx_capture_be;
|
||||
tx_status_info = &tx_cap_be->prot_status_info;
|
||||
/*
|
||||
* for multi sta block ack, do we need to increase the size
|
||||
* or copy info on subsequent frame offset
|
||||
*
|
||||
* for radiotap we allocate new skb,
|
||||
* so we don't need reserver skb header
|
||||
*/
|
||||
mpdu_nbuf = qdf_nbuf_alloc(pdev->soc->osdev,
|
||||
TXMON_BA_ACK_FRAME_SZ(ba_bitmap_sz),
|
||||
0, 4, FALSE);
|
||||
if (!mpdu_nbuf) {
|
||||
/* TODO: update status and break */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* BA CONTROL
|
||||
* fields required to construct block ack information
|
||||
* B0 - BA ACK POLICY
|
||||
* 0 - Normal ACK
|
||||
* 1 - No ACK
|
||||
* B1 - MULTI TID
|
||||
* B2 - COMPRESSED BITMAP
|
||||
* B12
|
||||
* 00 - Basic block ack
|
||||
* 01 - Compressed block ack
|
||||
* 10 - Reserved
|
||||
* 11 - Multi tid block ack
|
||||
* B3-B11 - Reserved
|
||||
* B12-B15 - TID info
|
||||
*
|
||||
* BA INFORMATION
|
||||
* Per sta tid info
|
||||
* AID: 11 bits
|
||||
* ACK type: 1 bit
|
||||
* TID: 4 bits
|
||||
*
|
||||
* BA SEQ CTRL
|
||||
*
|
||||
* BA bitmap
|
||||
*
|
||||
*/
|
||||
|
||||
wh_addr2 = (struct ieee80211_ctlframe_addr2 *)qdf_nbuf_data(mpdu_nbuf);
|
||||
qdf_mem_zero(wh_addr2, DP_BA_ACK_FRAME_SIZE);
|
||||
|
||||
wh_addr2->i_fc[0] = 0;
|
||||
wh_addr2->i_fc[1] = 0;
|
||||
wh_addr2->i_fc[0] = (IEEE80211_FC0_VERSION_0 |
|
||||
IEEE80211_FC0_TYPE_CTL |
|
||||
IEEE80211_FC0_BLOCK_ACK);
|
||||
*(u_int16_t *)(&wh_addr2->i_aidordur) = qdf_cpu_to_le16(0x0000);
|
||||
|
||||
qdf_mem_copy(wh_addr2->i_addr2,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr2),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(wh_addr2->i_addr1,
|
||||
TXMON_STATUS_INFO(tx_status_info, addr1),
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
|
||||
frm = (uint8_t *)&wh_addr2[6];
|
||||
|
||||
frm += 1;
|
||||
/* BA control */
|
||||
*((uint16_t *)frm) = qdf_cpu_to_le16(TXMON_PPDU_USR(tx_ppdu_info,
|
||||
0, ba_control));
|
||||
frm += 2;
|
||||
*((uint16_t *)frm) = qdf_cpu_to_le16((TXMON_PPDU_USR(tx_ppdu_info,
|
||||
user_id, tid) <<
|
||||
DP_IEEE80211_BAR_CTL_TID_S) |
|
||||
(TXMON_PPDU_USR(tx_ppdu_info,
|
||||
user_id,
|
||||
aid) & 0x7FF));
|
||||
frm += 2;
|
||||
*((uint16_t *)frm) = TXMON_PPDU_USR(tx_ppdu_info, user_id,
|
||||
start_seq) & 0xFFF;
|
||||
|
||||
frm += 2;
|
||||
qdf_mem_copy(frm,
|
||||
TXMON_PPDU_USR(tx_ppdu_info, user_id, ba_bitmap),
|
||||
4 << TXMON_PPDU_USR(tx_ppdu_info, user_id, ba_bitmap_sz));
|
||||
|
||||
frm += 4 << TXMON_PPDU_USR(tx_ppdu_info, user_id, ba_bitmap_sz);
|
||||
|
||||
qdf_nbuf_set_pktlen(mpdu_nbuf,
|
||||
(frm - (uint8_t *)qdf_nbuf_data(mpdu_nbuf)));
|
||||
|
||||
dp_tx_mon_enqueue_mpdu_nbuf(tx_ppdu_info, 0, mpdu_nbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,11 +862,12 @@ dp_tx_mon_generate_data_frm(struct dp_pdev *pdev,
|
||||
if (!mpdu_nbuf)
|
||||
QDF_BUG(0);
|
||||
|
||||
/* add function to either copy or add frag to frag_list */
|
||||
qdf_nbuf_add_frag(pdev->soc->osdev,
|
||||
TXMON_STATUS_INFO(tx_status_info, buffer),
|
||||
mpdu_nbuf,
|
||||
TXMON_STATUS_INFO(tx_status_info, offset),
|
||||
TXMON_STATUS_INFO(tx_status_info, len_bytes),
|
||||
TXMON_STATUS_INFO(tx_status_info, length),
|
||||
TX_MON_STATUS_BUF_SIZE,
|
||||
TRUE, TXMON_NO_BUFFER_SZ);
|
||||
}
|
||||
@@ -803,7 +1276,7 @@ QDF_STATUS dp_tx_mon_process_status_tlv(struct dp_soc *soc,
|
||||
|
||||
if (qdf_unlikely(last_frag_q_idx > MAX_STATUS_BUFFER_IN_PPDU)) {
|
||||
dp_mon_err("status frag queue for a ppdu[%d] exceed %d\n",
|
||||
mon_pdev_be->be_ppdu_id,
|
||||
tx_cap_be->be_ppdu_id,
|
||||
MAX_STATUS_BUFFER_IN_PPDU);
|
||||
dp_tx_mon_status_queue_free(pdev, tx_cap_be);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
Reference in New Issue
Block a user