qcacmn: Raw mode re-factoring and cleanup in rx

Cleaned raw mode specific code and moved the rx
processing to single API dp_rx_sg_create

Change-Id: I7696786d9a0f10983d3299956b46b2ec76b388a5
CRs-fixed: 2204824
This commit is contained in:
Chaithanya Garrepalli
2018-02-21 18:37:34 +05:30
committed by nshrivas
vanhempi bc62989ce4
commit 72dc9132a6
2 muutettua tiedostoa jossa 123 lisäystä ja 90 poistoa

Näytä tiedosto

@@ -257,7 +257,6 @@ dp_rx_deliver_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf_list,
DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf); DP_RX_LIST_APPEND(deliver_list_head, deliver_list_tail, nbuf);
DP_STATS_INC(vdev->pdev, rx_raw_pkts, 1);
/* /*
* reset the chfrag_start and chfrag_end bits in nbuf cb * reset the chfrag_start and chfrag_end bits in nbuf cb
* as this is a non-amsdu pkt and RAW mode simulation expects * as this is a non-amsdu pkt and RAW mode simulation expects
@@ -355,6 +354,15 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
struct dp_peer *da_peer; struct dp_peer *da_peer;
struct dp_ast_entry *ast_entry; struct dp_ast_entry *ast_entry;
qdf_nbuf_t nbuf_copy; qdf_nbuf_t nbuf_copy;
struct dp_vdev *vdev = sa_peer->vdev;
/*
* intrabss forwarding is not applicable if
* vap is nawds enabled or ap_bridge is false.
*/
if (vdev->nawds_enabled)
return false;
/* check if the destination peer is available in peer table /* check if the destination peer is available in peer table
* and also check if the source peer and destination peer * and also check if the source peer and destination peer
@@ -906,80 +914,115 @@ static void dp_rx_lro(uint8_t *rx_tlv, struct dp_peer *peer,
} }
#endif #endif
static inline void dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len) /**
* dp_rx_adjust_nbuf_len() - set appropriate msdu length in nbuf.
*
* @nbuf: pointer to msdu.
* @mpdu_len: mpdu length
*
* Return: returns true if nbuf is last msdu of mpdu else retuns false.
*/
static inline bool dp_rx_adjust_nbuf_len(qdf_nbuf_t nbuf, uint16_t *mpdu_len)
{ {
if (*mpdu_len >= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN)) bool last_nbuf;
if (*mpdu_len >= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN)) {
qdf_nbuf_set_pktlen(nbuf, RX_BUFFER_SIZE); qdf_nbuf_set_pktlen(nbuf, RX_BUFFER_SIZE);
else last_nbuf = false;
} else {
qdf_nbuf_set_pktlen(nbuf, (*mpdu_len + RX_PKT_TLVS_LEN)); qdf_nbuf_set_pktlen(nbuf, (*mpdu_len + RX_PKT_TLVS_LEN));
last_nbuf = true;
}
*mpdu_len -= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN); *mpdu_len -= (RX_BUFFER_SIZE - RX_PKT_TLVS_LEN);
return last_nbuf;
} }
/** /**
* dp_rx_sg_create() - create a frag_list for MSDUs which are spread across * dp_rx_sg_create() - create a frag_list for MSDUs which are spread across
* multiple nbufs. * multiple nbufs.
* @nbuf: nbuf which can may be part of frag_list. * @nbuf: pointer to the first msdu of an amsdu.
* @rx_tlv_hdr: pointer to the start of RX TLV headers. * @rx_tlv_hdr: pointer to the start of RX TLV headers.
* @mpdu_len: mpdu length. *
* @is_first_frag: is this the first nbuf in the fragmented MSDU.
* @frag_list_len: length of all the fragments combined.
* @head_frag_nbuf: parent nbuf
* @frag_list_head: pointer to the first nbuf in the frag_list.
* @frag_list_tail: pointer to the last nbuf in the frag_list.
* *
* This function implements the creation of RX frag_list for cases * This function implements the creation of RX frag_list for cases
* where an MSDU is spread across multiple nbufs. * where an MSDU is spread across multiple nbufs.
* *
* Return: returns the head nbuf which contains complete frag_list.
*/ */
void dp_rx_sg_create(qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr)
uint16_t *mpdu_len, bool *is_first_frag,
uint16_t *frag_list_len, qdf_nbuf_t *head_frag_nbuf,
qdf_nbuf_t *frag_list_head, qdf_nbuf_t *frag_list_tail)
{ {
if (qdf_unlikely(qdf_nbuf_is_rx_chfrag_cont(nbuf))) { qdf_nbuf_t parent, next, frag_list;
if (!(*is_first_frag)) { uint16_t frag_list_len = 0;
*is_first_frag = 1; uint16_t mpdu_len;
qdf_nbuf_set_rx_chfrag_start(nbuf, 1); bool last_nbuf;
*mpdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr);
dp_rx_adjust_nbuf_len(nbuf, mpdu_len); /*
*head_frag_nbuf = nbuf; * this is a case where the complete msdu fits in one single nbuf.
} else { * in this case HW sets both start and end bit and we only need to
dp_rx_adjust_nbuf_len(nbuf, mpdu_len); * reset these bits for RAW mode simulator to decap the pkt
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); */
*frag_list_len += qdf_nbuf_len(nbuf); if (qdf_nbuf_is_rx_chfrag_start(nbuf) &&
qdf_nbuf_is_rx_chfrag_end(nbuf)) {
DP_RX_LIST_APPEND(*frag_list_head, qdf_nbuf_set_rx_chfrag_start(nbuf, 0);
*frag_list_tail, qdf_nbuf_set_rx_chfrag_end(nbuf, 0);
nbuf); return nbuf;
}
} else {
if (qdf_unlikely(*is_first_frag)) {
qdf_nbuf_set_rx_chfrag_start(nbuf, 0);
dp_rx_adjust_nbuf_len(nbuf, mpdu_len);
qdf_nbuf_pull_head(nbuf,
RX_PKT_TLVS_LEN);
*frag_list_len += qdf_nbuf_len(nbuf);
DP_RX_LIST_APPEND(*frag_list_head,
*frag_list_tail,
nbuf);
qdf_nbuf_append_ext_list(*head_frag_nbuf,
*frag_list_head,
*frag_list_len);
*is_first_frag = 0;
return;
}
*head_frag_nbuf = nbuf;
} }
/*
* This is a case where we have multiple msdus (A-MSDU) spread across
* multiple nbufs. here we create a fraglist out of these nbufs.
*
* the moment we encounter a nbuf with continuation bit set we
* know for sure we have an MSDU which is spread across multiple
* nbufs. We loop through and reap nbufs till we reach last nbuf.
*/
parent = nbuf;
frag_list = nbuf->next;
nbuf = nbuf->next;
/*
* set the start bit in the first nbuf we encounter with continuation
* bit set. This has the proper mpdu length set as it is the first
* msdu of the mpdu. this becomes the parent nbuf and the subsequent
* nbufs will form the frag_list of the parent nbuf.
*/
qdf_nbuf_set_rx_chfrag_start(parent, 1);
mpdu_len = hal_rx_msdu_start_msdu_len_get(rx_tlv_hdr);
last_nbuf = dp_rx_adjust_nbuf_len(parent, &mpdu_len);
/*
* this is where we set the length of the fragments which are
* associated to the parent nbuf. We iterate through the frag_list
* till we hit the last_nbuf of the list.
*/
do {
last_nbuf = dp_rx_adjust_nbuf_len(nbuf, &mpdu_len);
qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
frag_list_len += qdf_nbuf_len(nbuf);
if (last_nbuf) {
next = nbuf->next;
nbuf->next = NULL;
break;
}
nbuf = nbuf->next;
} while (!last_nbuf);
qdf_nbuf_set_rx_chfrag_start(nbuf, 0);
qdf_nbuf_append_ext_list(parent, frag_list, frag_list_len);
parent->next = next;
qdf_nbuf_pull_head(parent, RX_PKT_TLVS_LEN);
return parent;
} }
static inline void dp_rx_deliver_to_stack(struct dp_vdev *vdev, static inline void dp_rx_deliver_to_stack(struct dp_vdev *vdev,
struct dp_peer *peer, struct dp_peer *peer,
qdf_nbuf_t nbuf_list) qdf_nbuf_t nbuf_head,
qdf_nbuf_t nbuf_tail)
{ {
/* /*
* highly unlikely to have a vdev without a registerd rx * highly unlikely to have a vdev without a registerd rx
@@ -988,19 +1031,21 @@ static inline void dp_rx_deliver_to_stack(struct dp_vdev *vdev,
if (qdf_unlikely(!vdev->osif_rx)) { if (qdf_unlikely(!vdev->osif_rx)) {
qdf_nbuf_t nbuf; qdf_nbuf_t nbuf;
do { do {
nbuf = nbuf_list; nbuf = nbuf_head;
nbuf_list = nbuf_list->next; nbuf_head = nbuf_head->next;
qdf_nbuf_free(nbuf); qdf_nbuf_free(nbuf);
} while (nbuf_list); } while (nbuf_head);
return; return;
} }
if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw) || if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw) ||
(vdev->rx_decap_type == htt_cmn_pkt_type_native_wifi)) (vdev->rx_decap_type == htt_cmn_pkt_type_native_wifi)) {
dp_rx_deliver_raw(vdev, nbuf_list, peer); vdev->osif_rsim_rx_decap(vdev->osif_vdev, &nbuf_head,
else &nbuf_tail, (struct cdp_peer *) peer);
vdev->osif_rx(vdev->osif_vdev, nbuf_list); }
vdev->osif_rx(vdev->osif_vdev, nbuf_head);
} }
@@ -1270,12 +1315,6 @@ dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint32_t quota)
struct dp_soc *soc = int_ctx->soc; struct dp_soc *soc = int_ctx->soc;
uint8_t ring_id = 0; uint8_t ring_id = 0;
uint8_t core_id = 0; uint8_t core_id = 0;
bool is_first_frag = 0;
uint16_t mpdu_len = 0;
qdf_nbuf_t head_frag_nbuf = NULL;
qdf_nbuf_t frag_list_head = NULL;
qdf_nbuf_t frag_list_tail = NULL;
uint16_t frag_list_len = 0;
qdf_nbuf_t nbuf_head = NULL; qdf_nbuf_t nbuf_head = NULL;
qdf_nbuf_t nbuf_tail = NULL; qdf_nbuf_t nbuf_tail = NULL;
qdf_nbuf_t deliver_list_head = NULL; qdf_nbuf_t deliver_list_head = NULL;
@@ -1437,7 +1476,8 @@ done:
rx_bufs_used++; rx_bufs_used++;
if (deliver_list_head && peer && (vdev != peer->vdev)) { if (deliver_list_head && peer && (vdev != peer->vdev)) {
dp_rx_deliver_to_stack(vdev, peer, deliver_list_head); dp_rx_deliver_to_stack(vdev, peer, deliver_list_head,
deliver_list_tail);
deliver_list_head = NULL; deliver_list_head = NULL;
deliver_list_tail = NULL; deliver_list_tail = NULL;
} }
@@ -1478,21 +1518,10 @@ done:
if (qdf_unlikely(vdev->rx_decap_type == if (qdf_unlikely(vdev->rx_decap_type ==
htt_cmn_pkt_type_raw)) { htt_cmn_pkt_type_raw)) {
dp_rx_sg_create(nbuf, rx_tlv_hdr, &mpdu_len, DP_STATS_INC(vdev->pdev, rx_raw_pkts, 1);
&is_first_frag, &frag_list_len,
&head_frag_nbuf,
&frag_list_head,
&frag_list_tail);
if (is_first_frag) { nbuf = dp_rx_sg_create(nbuf, rx_tlv_hdr);
nbuf = next; next = nbuf->next;
continue;
} else {
frag_list_head = NULL;
frag_list_tail = NULL;
nbuf = head_frag_nbuf;
rx_tlv_hdr = qdf_nbuf_data(nbuf);
}
} }
if (!dp_wds_rx_policy_check(rx_tlv_hdr, vdev, peer, if (!dp_wds_rx_policy_check(rx_tlv_hdr, vdev, peer,
@@ -1618,7 +1647,8 @@ done:
} }
if (deliver_list_head) if (deliver_list_head)
dp_rx_deliver_to_stack(vdev, peer, deliver_list_head); dp_rx_deliver_to_stack(vdev, peer, deliver_list_head,
deliver_list_tail);
return rx_bufs_used; /* Assume no scale factor for now */ return rx_bufs_used; /* Assume no scale factor for now */
} }

Näytä tiedosto

@@ -295,15 +295,18 @@ uint32_t dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota);
uint32_t uint32_t
dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota); dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota);
void /**
dp_rx_sg_create(qdf_nbuf_t nbuf, * dp_rx_sg_create() - create a frag_list for MSDUs which are spread across
uint8_t *rx_tlv_hdr, * multiple nbufs.
uint16_t *mpdu_len, * @nbuf: pointer to the first msdu of an amsdu.
bool *is_first_frag, * @rx_tlv_hdr: pointer to the start of RX TLV headers.
uint16_t *frag_list_len, *
qdf_nbuf_t *head_frag_nbuf, * This function implements the creation of RX frag_list for cases
qdf_nbuf_t *frag_list_head, * where an MSDU is spread across multiple nbufs.
qdf_nbuf_t *frag_list_tail); *
* Return: returns the head nbuf which contains complete frag_list.
*/
qdf_nbuf_t dp_rx_sg_create(qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr);
QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc,
uint32_t pool_id, uint32_t pool_id,