qcacmn: Handle RX defrag in exception path

- Perform SW chaining of fragments.
- Reinject only the head fragment to REO.

Change-Id: I198db3ba4319b8a2e800eb7495cf190c5e86d4cd
CRs-Fixed: 2144197
This commit is contained in:
psimha
2017-11-16 17:18:51 -08:00
committed by snandini
parent e3947bd8d6
commit 223883fb88
6 changed files with 441 additions and 255 deletions

View File

@@ -647,6 +647,9 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
* @bm_action: put to idle_list or release to msdu_list * @bm_action: put to idle_list or release to msdu_list
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
QDF_STATUS
dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc, uint8_t bm_action);
QDF_STATUS QDF_STATUS
dp_rx_link_desc_buf_return(struct dp_soc *soc, struct dp_srng *dp_rxdma_srng, dp_rx_link_desc_buf_return(struct dp_soc *soc, struct dp_srng *dp_rxdma_srng,
void *buf_addr_info, uint8_t bm_action); void *buf_addr_info, uint8_t bm_action);

View File

@@ -77,14 +77,13 @@ static void dp_rx_defrag_frames_free(qdf_nbuf_t frames)
*/ */
static void dp_rx_clear_saved_desc_info(struct dp_peer *peer, unsigned tid) static void dp_rx_clear_saved_desc_info(struct dp_peer *peer, unsigned tid)
{ {
hal_rx_clear_mpdu_desc_info( if (peer->rx_tid[tid].dst_ring_desc)
&peer->rx_tid[tid].transcap_rx_mpdu_desc_info); qdf_mem_free(peer->rx_tid[tid].dst_ring_desc);
hal_rx_clear_msdu_link_ptr( peer->rx_tid[tid].dst_ring_desc = NULL;
&peer->rx_tid[tid].transcap_msdu_link_ptr[0],
HAL_RX_MAX_SAVED_RING_DESC);
} }
#ifdef DEFRAG_TIMEOUT
/* /*
* dp_rx_defrag_waitlist_add(): Update per-PDEV defrag wait list * dp_rx_defrag_waitlist_add(): Update per-PDEV defrag wait list
* @peer: Pointer to the peer data structure * @peer: Pointer to the peer data structure
@@ -142,6 +141,7 @@ static void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid)
qdf_assert(0); qdf_assert(0);
} }
} }
#endif
/* /*
* dp_rx_defrag_fraglist_insert(): Create a per-sequence fragment list * dp_rx_defrag_fraglist_insert(): Create a per-sequence fragment list
@@ -220,7 +220,7 @@ static void dp_rx_defrag_fraglist_insert(struct dp_peer *peer, unsigned tid,
next = qdf_nbuf_next(*head_addr); next = qdf_nbuf_next(*head_addr);
rx_desc_info = qdf_nbuf_data(*tail_addr); rx_desc_info = qdf_nbuf_data(*tail_addr);
last_morefrag = hal_rx_get_rx_more_frag_bit(rx_desc_info); last_morefrag = dp_rx_frag_get_more_frag_bit(rx_desc_info);
/* TODO: optimize the loop */ /* TODO: optimize the loop */
if (!last_morefrag) { if (!last_morefrag) {
@@ -617,40 +617,57 @@ static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key,
} }
/* /*
* dp_rx_defrag_decap_recombine(): Recombine the fragments * dp_rx_frag_pull_hdr(): Pulls the RXTLV & the 802.11 headers
* @peer: Pointer to the peer * @nbuf: buffer pointer
* @frag_list: list of fragments
* @tid: Transmit identifier
* @hdrsize: Header size
* *
* Recombine fragments * Pull the RXTLV & the 802.11 headers
* *
* Returns: QDF_STATUS * Returns: None
*/ */
static QDF_STATUS dp_rx_defrag_decap_recombine(struct dp_peer *peer, static void dp_rx_frag_pull_hdr(qdf_nbuf_t nbuf)
qdf_nbuf_t head_msdu, unsigned tid, uint16_t hdrsize)
{ {
qdf_nbuf_t msdu = head_msdu; uint16_t hdrsize = dp_rx_defrag_hdrsize(nbuf);
uint8_t i;
uint8_t num_ring_desc_saved = peer->rx_tid[tid].curr_ring_desc_idx;
uint8_t num_msdus;
/* Stitch fragments together */ qdf_nbuf_pull_head(nbuf,
for (i = 0; (i < num_ring_desc_saved) && msdu; i++) { RX_PKT_TLVS_LEN + hdrsize);
struct hal_rx_msdu_link_ptr_info *msdu_link_ptr_info = QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
&peer->rx_tid[tid].transcap_msdu_link_ptr[i]; "%s: final pktlen %d .11len %d\n",
__func__,
(uint32_t)qdf_nbuf_len(nbuf), hdrsize);
}
struct hal_rx_mpdu_desc_info *mpdu_desc_info = /*
&peer->rx_tid[tid].transcap_rx_mpdu_desc_info; * dp_rx_construct_fraglist(): Construct a nbuf fraglist
* @peer: Pointer to the peer
num_msdus = hal_rx_chain_msdu_links(msdu, msdu_link_ptr_info, * @head: Pointer to list of fragments
mpdu_desc_info); *
* Construct a nbuf fraglist
*
* Returns: None
*/
static void
dp_rx_construct_fraglist(struct dp_peer *peer, qdf_nbuf_t head)
{
qdf_nbuf_t msdu = qdf_nbuf_next(head);
qdf_nbuf_t rx_nbuf = msdu;
uint32_t len = 0;
while (msdu) {
dp_rx_frag_pull_hdr(msdu);
len += qdf_nbuf_len(msdu);
msdu = qdf_nbuf_next(msdu); msdu = qdf_nbuf_next(msdu);
} }
return QDF_STATUS_SUCCESS; qdf_nbuf_append_ext_list(head, rx_nbuf, len);
qdf_nbuf_set_next(head, NULL);
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
"%s: head len %d ext len %d data len %d \n",
__func__,
(uint32_t)qdf_nbuf_len(head),
(uint32_t)qdf_nbuf_len(rx_nbuf),
(uint32_t)(head->data_len));
} }
/** /**
@@ -676,179 +693,243 @@ static void dp_rx_defrag_err(uint8_t vdev_id, uint8_t *peer_mac_addr,
/* TODO: Who needs to know about the TKIP MIC error */ /* TODO: Who needs to know about the TKIP MIC error */
} }
/*
* dp_rx_defrag_qos_decap(): Remove QOS header from the frame
* @nbuf: Pointer to the frame buffer
* @hdrlen: Length of the header information
*
* Recombine fragments
*
* Returns: None
*/
static void dp_rx_defrag_qos_decap(qdf_nbuf_t nbuf, uint16_t hdrlen)
{
struct ieee80211_frame *wh;
uint16_t qoslen;
int pkt_tlv_size = sizeof(struct rx_pkt_tlvs); /* pkt TLV hdr size */
uint16_t fc = 0;
uint8_t *rx_tlv_hdr = qdf_nbuf_data(nbuf);
/* Get the frame control field if it is valid */
if (hal_rx_get_mpdu_frame_control_valid(rx_tlv_hdr))
fc = hal_rx_get_frame_ctrl_field(rx_tlv_hdr);
wh = (struct ieee80211_frame *)(qdf_nbuf_data(nbuf) + pkt_tlv_size);
if (DP_RX_DEFRAG_IEEE80211_QOS_HAS_SEQ(fc & 0xff)) {
qoslen = sizeof(struct ieee80211_qoscntl);
/* Qos frame with Order bit set indicates a HTC frame */
if (((fc & 0xff00) >> 8) & IEEE80211_FC1_ORDER)
qoslen += sizeof(struct ieee80211_htc);
/* remove QoS field from header */
hdrlen -= qoslen;
qdf_mem_move((uint8_t *)wh + qoslen, wh, hdrlen);
wh = (struct ieee80211_frame *)qdf_nbuf_pull_head(nbuf,
pkt_tlv_size +
qoslen);
/* clear QoS bit */
if (wh)
wh->i_fc[0] &= ~IEEE80211_FC0_SUBTYPE_QOS;
}
}
/* /*
* dp_rx_defrag_nwifi_to_8023(): Transcap 802.11 to 802.3 * dp_rx_defrag_nwifi_to_8023(): Transcap 802.11 to 802.3
* @msdu: Pointer to the fragment buffer * @nbuf: Pointer to the fragment buffer
* *
* Transcap the fragment from 802.11 to 802.3 * Transcap the fragment from 802.11 to 802.3
* *
* Returns: None * Returns: None
*/ */
static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t msdu) static void dp_rx_defrag_nwifi_to_8023(qdf_nbuf_t nbuf)
{ {
struct ieee80211_frame wh;
uint32_t hdrsize; uint32_t hdrsize;
struct llc_snap_hdr_t llchdr; struct llc_snap_hdr_t *llchdr;
struct ethernet_hdr_t *eth_hdr; struct ethernet_hdr_t *eth_hdr;
int rx_desc_len = sizeof(struct rx_pkt_tlvs); uint8_t ether_type[2];
struct ieee80211_frame *wh_ptr; uint16_t fc;
union dp_align_mac_addr mac_addr;
uint8_t *rx_desc_info = qdf_mem_malloc(RX_PKT_TLVS_LEN);
wh_ptr = (struct ieee80211_frame *)(qdf_nbuf_data(msdu) + if (rx_desc_info == NULL) {
rx_desc_len); QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
qdf_mem_copy(&wh, wh_ptr, sizeof(wh)); "%s: Memory alloc failed ! \n", __func__);
hdrsize = sizeof(struct ieee80211_frame); QDF_ASSERT(0);
qdf_mem_copy(&llchdr, ((uint8_t *) (qdf_nbuf_data(msdu) + return;
rx_desc_len)) + hdrsize, }
sizeof(struct llc_snap_hdr_t));
/* hdrsize = dp_rx_defrag_hdrsize(nbuf);
* Now move the data pointer to the beginning of the mac header :
* new-header = old-hdr + (wifihdrsize + llchdrsize - ethhdrsize) qdf_mem_copy(rx_desc_info, qdf_nbuf_data(nbuf), RX_PKT_TLVS_LEN);
*/
qdf_nbuf_pull_head(msdu, (rx_desc_len + hdrsize + llchdr = (struct llc_snap_hdr_t *)(qdf_nbuf_data(nbuf) +
RX_PKT_TLVS_LEN + hdrsize);
qdf_mem_copy(ether_type, llchdr->ethertype, 2);
qdf_nbuf_pull_head(nbuf, (RX_PKT_TLVS_LEN + hdrsize +
sizeof(struct llc_snap_hdr_t) - sizeof(struct llc_snap_hdr_t) -
sizeof(struct ethernet_hdr_t))); sizeof(struct ethernet_hdr_t)));
eth_hdr = (struct ethernet_hdr_t *)(qdf_nbuf_data(msdu));
switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { eth_hdr = (struct ethernet_hdr_t *)(qdf_nbuf_data(nbuf));
if (hal_rx_get_mpdu_frame_control_valid(rx_desc_info))
fc = hal_rx_get_frame_ctrl_field(rx_desc_info);
switch (((fc & 0xff00) >> 8) & IEEE80211_FC1_DIR_MASK) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
"%s: frame control type: 0x%x", __func__, fc);
case IEEE80211_FC1_DIR_NODS: case IEEE80211_FC1_DIR_NODS:
qdf_mem_copy(eth_hdr->dest_addr, wh.i_addr1, hal_rx_mpdu_get_addr1(rx_desc_info,
&mac_addr.raw[0]);
qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
qdf_mem_copy(eth_hdr->src_addr, wh.i_addr2, hal_rx_mpdu_get_addr2(rx_desc_info,
&mac_addr.raw[0]);
qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
break; break;
case IEEE80211_FC1_DIR_TODS: case IEEE80211_FC1_DIR_TODS:
qdf_mem_copy(eth_hdr->dest_addr, wh.i_addr3, hal_rx_mpdu_get_addr3(rx_desc_info,
&mac_addr.raw[0]);
qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
qdf_mem_copy(eth_hdr->src_addr, wh.i_addr2, hal_rx_mpdu_get_addr2(rx_desc_info,
&mac_addr.raw[0]);
qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
break; break;
case IEEE80211_FC1_DIR_FROMDS: case IEEE80211_FC1_DIR_FROMDS:
qdf_mem_copy(eth_hdr->dest_addr, wh.i_addr1, hal_rx_mpdu_get_addr1(rx_desc_info,
&mac_addr.raw[0]);
qdf_mem_copy(eth_hdr->dest_addr, &mac_addr.raw[0],
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
qdf_mem_copy(eth_hdr->src_addr, wh.i_addr3, hal_rx_mpdu_get_addr3(rx_desc_info,
&mac_addr.raw[0]);
qdf_mem_copy(eth_hdr->src_addr, &mac_addr.raw[0],
IEEE80211_ADDR_LEN); IEEE80211_ADDR_LEN);
break; break;
case IEEE80211_FC1_DIR_DSTODS: case IEEE80211_FC1_DIR_DSTODS:
break; break;
default:
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"%s: Unknown frame control type: 0x%x", __func__, fc);
} }
/* TODO: Is it requried to copy rx_pkt_tlvs qdf_mem_copy(eth_hdr->ethertype, ether_type,
* to the start of data buffer? sizeof(ether_type));
*/
qdf_mem_copy(eth_hdr->ethertype, llchdr.ethertype, qdf_nbuf_push_head(nbuf, RX_PKT_TLVS_LEN);
sizeof(llchdr.ethertype)); qdf_mem_copy(qdf_nbuf_data(nbuf), rx_desc_info, RX_PKT_TLVS_LEN);
qdf_mem_free(rx_desc_info);
} }
/* /*
* dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO * dp_rx_defrag_reo_reinject(): Reinject the fragment chain back into REO
* @peer: Pointer to the peer * @peer: Pointer to the peer
* @tid: Transmit Identifier * @tid: Transmit Identifier
* @head: Buffer to be reinjected back
* *
* Reinject the fragment chain back into REO * Reinject the fragment chain back into REO
* *
* Returns: QDF_STATUS * Returns: QDF_STATUS
*/ */
static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer, static QDF_STATUS dp_rx_defrag_reo_reinject(struct dp_peer *peer,
unsigned tid) unsigned tid, qdf_nbuf_t head)
{ {
struct dp_pdev *pdev = peer->vdev->pdev; struct dp_pdev *pdev = peer->vdev->pdev;
struct dp_soc *soc = pdev->soc; struct dp_soc *soc = pdev->soc;
QDF_STATUS status = QDF_STATUS_E_FAILURE; struct hal_buf_info buf_info;
void *ring_desc; void *link_desc_va;
enum hal_reo_error_status error; void *msdu0, *msdu_desc_info;
struct hal_rx_mpdu_desc_info *saved_mpdu_desc_info; void *ent_ring_desc, *ent_mpdu_desc_info, *ent_qdesc_addr;
void *dst_mpdu_desc_info, *dst_qdesc_addr;
qdf_dma_addr_t paddr;
uint32_t nbuf_len, seq_no;
uint32_t *mpdu_wrd;
void *dst_ring_desc =
peer->rx_tid[tid].dst_ring_desc;
void *hal_srng = soc->reo_reinject_ring.hal_srng; void *hal_srng = soc->reo_reinject_ring.hal_srng;
struct hal_rx_msdu_link_ptr_info *saved_msdu_link_ptr;
hal_rx_reo_buf_paddr_get(dst_ring_desc, &buf_info);
link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info);
qdf_assert(link_desc_va);
msdu0 = (uint8_t *)link_desc_va +
RX_MSDU_LINK_8_RX_MSDU_DETAILS_MSDU_0_OFFSET;
nbuf_len = qdf_nbuf_len(head) - RX_PKT_TLVS_LEN;
HAL_RX_UNIFORM_HDR_SET(link_desc_va, OWNER, UNI_DESC_OWNER_SW);
HAL_RX_UNIFORM_HDR_SET(link_desc_va, BUFFER_TYPE,
UNI_DESC_BUF_TYPE_RX_MSDU_LINK);
/* msdu reconfig */
msdu_desc_info = (uint8_t *)msdu0 +
RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET;
qdf_mem_zero(msdu_desc_info, sizeof(struct rx_msdu_desc_info));
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
FIRST_MSDU_IN_MPDU_FLAG, 1);
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
LAST_MSDU_IN_MPDU_FLAG, 1);
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
MSDU_CONTINUATION, 0x0);
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
REO_DESTINATION_INDICATION, 1);
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
MSDU_LENGTH, nbuf_len);
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
SA_IS_VALID, 1);
HAL_RX_MSDU_DESC_INFO_SET(msdu_desc_info,
DA_IS_VALID, 1);
/* change RX TLV's */
hal_rx_msdu_start_msdu_len_set(
qdf_nbuf_data(head), nbuf_len);
/* Lets fill entrance ring now !!! */
if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) { if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"HAL RING Access For WBM Release SRNG Failed: %pK",
hal_srng);
goto done;
}
ring_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng);
qdf_assert(ring_desc);
error = HAL_RX_ERROR_STATUS_GET(ring_desc);
if (qdf_unlikely(error == HAL_REO_ERROR_DETECTED)) {
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"HAL RING 0x%pK:error %d", hal_srng, error); "HAL RING Access For REO entrance SRNG Failed: %pK",
hal_srng);
/* Don't know how to deal with this condition -- assert */ return QDF_STATUS_E_FAILURE;
qdf_assert(0);
goto done;
} }
saved_mpdu_desc_info = ent_ring_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng);
&peer->rx_tid[tid].transcap_rx_mpdu_desc_info;
/* first msdu link pointer */ qdf_assert(ent_ring_desc);
saved_msdu_link_ptr =
&peer->rx_tid[tid].transcap_msdu_link_ptr[0];
hal_rx_defrag_update_src_ring_desc(ring_desc, paddr = (uint64_t)buf_info.paddr;
saved_mpdu_desc_info, saved_msdu_link_ptr); /* buf addr */
hal_rxdma_buff_addr_info_set(ent_ring_desc, paddr,
buf_info.sw_cookie,
HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST);
/* mpdu desc info */
ent_mpdu_desc_info = (uint8_t *)ent_ring_desc +
RX_MPDU_DETAILS_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET;
dst_mpdu_desc_info = (uint8_t *)dst_ring_desc +
REO_DESTINATION_RING_2_RX_MPDU_DESC_INFO_RX_MPDU_DESC_INFO_DETAILS_OFFSET;
qdf_mem_copy(ent_mpdu_desc_info, dst_mpdu_desc_info,
sizeof(struct rx_mpdu_desc_info));
qdf_mem_zero(ent_mpdu_desc_info, sizeof(uint32_t));
mpdu_wrd = (uint32_t *)dst_mpdu_desc_info;
seq_no = HAL_RX_MPDU_SEQUENCE_NUMBER_GET(mpdu_wrd);
HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
MSDU_COUNT, 0x1);
HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
MPDU_SEQUENCE_NUMBER, seq_no);
/* unset frag bit */
HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
FRAGMENT_FLAG, 0x0);
/* set sa/da valid bits */
HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
SA_IS_VALID, 0x1);
HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
DA_IS_VALID, 0x1);
HAL_RX_MPDU_DESC_INFO_SET(ent_mpdu_desc_info,
RAW_MPDU, 0x0);
/* qdesc addr */
ent_qdesc_addr = (uint8_t *)ent_ring_desc +
REO_ENTRANCE_RING_4_RX_REO_QUEUE_DESC_ADDR_31_0_OFFSET;
dst_qdesc_addr = (uint8_t *)dst_ring_desc +
REO_DESTINATION_RING_6_RX_REO_QUEUE_DESC_ADDR_31_0_OFFSET;
qdf_mem_copy(ent_qdesc_addr, dst_qdesc_addr, 8);
/* dst ind */
HAL_RX_FLD_SET(ent_ring_desc, REO_ENTRANCE_RING_5,
REO_DESTINATION_INDICATION, 0x1);
status = QDF_STATUS_SUCCESS;
done:
hal_srng_access_end(soc->hal_soc, hal_srng); hal_srng_access_end(soc->hal_soc, hal_srng);
return status;
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
"%s: reinjection done !\n", __func__);
return QDF_STATUS_SUCCESS;
} }
/* /*
* dp_rx_defrag(): Defragment the fragment chain * dp_rx_defrag(): Defragment the fragment chain
* @peer: Pointer to the peer * @peer: Pointer to the peer
* @tid: Transmit Identifier * @tid: Transmit Identifier
* @frag_list: Pointer to head list * @frag_list_head: Pointer to head list
* @frag_list_tail: Pointer to tail list * @frag_list_tail: Pointer to tail list
* *
* Defragment the fragment chain * Defragment the fragment chain
@@ -856,22 +937,29 @@ done:
* Returns: QDF_STATUS * Returns: QDF_STATUS
*/ */
static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid, static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
qdf_nbuf_t frag_list, qdf_nbuf_t frag_list_tail) qdf_nbuf_t frag_list_head, qdf_nbuf_t frag_list_tail)
{ {
qdf_nbuf_t tmp_next; qdf_nbuf_t tmp_next, prev;
qdf_nbuf_t cur = frag_list, msdu; qdf_nbuf_t cur = frag_list_head, msdu;
uint32_t index, tkip_demic = 0; uint32_t index, tkip_demic = 0;
uint16_t hdr_space; uint16_t hdr_space;
QDF_STATUS status;
uint8_t key[DEFRAG_IEEE80211_KEY_LEN]; uint8_t key[DEFRAG_IEEE80211_KEY_LEN];
struct dp_vdev *vdev = peer->vdev; struct dp_vdev *vdev = peer->vdev;
cur = frag_list;
hdr_space = dp_rx_defrag_hdrsize(cur); hdr_space = dp_rx_defrag_hdrsize(cur);
index = hal_rx_msdu_is_wlan_mcast(cur) ? index = hal_rx_msdu_is_wlan_mcast(cur) ?
dp_sec_mcast : dp_sec_ucast; dp_sec_mcast : dp_sec_ucast;
/* Remove FCS from all fragments */
while (cur) {
tmp_next = qdf_nbuf_next(cur);
qdf_nbuf_set_next(cur, NULL);
qdf_nbuf_trim_tail(cur, DEFRAG_IEEE80211_FCS_LEN);
prev = cur;
qdf_nbuf_set_next(cur, tmp_next);
cur = tmp_next;
}
switch (peer->security[index].sec_type) { switch (peer->security[index].sec_type) {
case htt_sec_type_tkip: case htt_sec_type_tkip:
tkip_demic = 1; tkip_demic = 1;
@@ -882,7 +970,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
if (dp_rx_defrag_tkip_decap(cur, hdr_space)) { if (dp_rx_defrag_tkip_decap(cur, hdr_space)) {
/* TKIP decap failed, discard frags */ /* TKIP decap failed, discard frags */
dp_rx_defrag_frames_free(frag_list); dp_rx_defrag_frames_free(frag_list_head);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE(QDF_MODULE_ID_TXRX,
QDF_TRACE_LEVEL_ERROR, QDF_TRACE_LEVEL_ERROR,
@@ -900,7 +988,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
if (dp_rx_defrag_ccmp_demic(cur, hdr_space)) { if (dp_rx_defrag_ccmp_demic(cur, hdr_space)) {
/* CCMP demic failed, discard frags */ /* CCMP demic failed, discard frags */
dp_rx_defrag_frames_free(frag_list); dp_rx_defrag_frames_free(frag_list_head);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE(QDF_MODULE_ID_TXRX,
QDF_TRACE_LEVEL_ERROR, QDF_TRACE_LEVEL_ERROR,
@@ -911,7 +999,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
if (dp_rx_defrag_ccmp_decap(cur, hdr_space)) { if (dp_rx_defrag_ccmp_decap(cur, hdr_space)) {
/* CCMP decap failed, discard frags */ /* CCMP decap failed, discard frags */
dp_rx_defrag_frames_free(frag_list); dp_rx_defrag_frames_free(frag_list_head);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE(QDF_MODULE_ID_TXRX,
QDF_TRACE_LEVEL_ERROR, QDF_TRACE_LEVEL_ERROR,
@@ -930,7 +1018,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
if (dp_rx_defrag_wep_decap(cur, hdr_space)) { if (dp_rx_defrag_wep_decap(cur, hdr_space)) {
/* WEP decap failed, discard frags */ /* WEP decap failed, discard frags */
dp_rx_defrag_frames_free(frag_list); dp_rx_defrag_frames_free(frag_list_head);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE(QDF_MODULE_ID_TXRX,
QDF_TRACE_LEVEL_ERROR, QDF_TRACE_LEVEL_ERROR,
@@ -965,36 +1053,24 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
} }
} }
dp_rx_defrag_qos_decap(cur, hdr_space);
/* Convert the header to 802.3 header */ /* Convert the header to 802.3 header */
dp_rx_defrag_nwifi_to_8023(cur); dp_rx_defrag_nwifi_to_8023(frag_list_head);
dp_rx_construct_fraglist(peer, frag_list_head);
status = dp_rx_defrag_decap_recombine(peer, cur, tid, hdr_space); return QDF_STATUS_SUCCESS;
if (QDF_IS_STATUS_ERROR(status)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"dp_rx_defrag_decap_recombine failed");
qdf_assert(0);
}
return status;
} }
/* /*
* dp_rx_defrag_cleanup(): Clean up activities * dp_rx_defrag_cleanup(): Clean up activities
* @peer: Pointer to the peer * @peer: Pointer to the peer
* @tid: Transmit Identifier * @tid: Transmit Identifier
* @seq: Sequence number
* *
* Returns: None * Returns: None
*/ */
static void dp_rx_defrag_cleanup(struct dp_peer *peer, unsigned tid, static void dp_rx_defrag_cleanup(struct dp_peer *peer, unsigned tid)
uint16_t seq)
{ {
struct dp_rx_reorder_array_elem *rx_reorder_array_elem = struct dp_rx_reorder_array_elem *rx_reorder_array_elem =
&peer->rx_tid[tid].array[seq]; peer->rx_tid[tid].array;
/* Free up nbufs */ /* Free up nbufs */
dp_rx_defrag_frames_free(rx_reorder_array_elem->head); dp_rx_defrag_frames_free(rx_reorder_array_elem->head);
@@ -1007,50 +1083,35 @@ static void dp_rx_defrag_cleanup(struct dp_peer *peer, unsigned tid,
peer->rx_tid[tid].defrag_timeout_ms = 0; peer->rx_tid[tid].defrag_timeout_ms = 0;
peer->rx_tid[tid].curr_frag_num = 0; peer->rx_tid[tid].curr_frag_num = 0;
peer->rx_tid[tid].curr_seq_num = 0; peer->rx_tid[tid].curr_seq_num = 0;
peer->rx_tid[tid].curr_ring_desc_idx = 0;
} }
/* /*
* dp_rx_defrag_save_info_from_ring_desc(): Save info from REO ring descriptor * dp_rx_defrag_save_info_from_ring_desc(): Save info from REO ring descriptor
* @ring_desc: Pointer to the ring descriptor * @ring_desc: Pointer to the dst ring descriptor
* @peer: Pointer to the peer * @peer: Pointer to the peer
* @tid: Transmit Identifier * @tid: Transmit Identifier
* @mpdu_desc_info: MPDU descriptor info
* *
* Returns: None * Returns: None
*/ */
static void dp_rx_defrag_save_info_from_ring_desc(void *ring_desc, static QDF_STATUS dp_rx_defrag_save_info_from_ring_desc(void *ring_desc,
struct dp_peer *peer, unsigned tid, struct dp_peer *peer, unsigned tid)
struct hal_rx_mpdu_desc_info *mpdu_desc_info)
{ {
struct dp_pdev *pdev = peer->vdev->pdev; void *dst_ring_desc = qdf_mem_malloc(
void *msdu_link_desc_va = NULL; sizeof(struct reo_destination_ring));
uint8_t idx = peer->rx_tid[tid].curr_ring_desc_idx;
uint8_t rbm;
struct hal_rx_msdu_link_ptr_info *msdu_link_ptr_info = if (dst_ring_desc == NULL) {
&peer->rx_tid[tid].transcap_msdu_link_ptr[++idx]; QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
struct hal_rx_mpdu_desc_info *tmp_mpdu_desc_info = "%s: Memory alloc failed !\n", __func__);
&peer->rx_tid[tid].transcap_rx_mpdu_desc_info; QDF_ASSERT(0);
struct hal_buf_info hbi; return QDF_STATUS_E_NOMEM;
rbm = hal_rx_ret_buf_manager_get(ring_desc);
if (qdf_unlikely(rbm != HAL_RX_BUF_RBM_SW3_BM)) {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Invalid RBM while chaining frag MSDUs");
return;
} }
hal_rx_reo_buf_paddr_get(ring_desc, &hbi); qdf_mem_copy(dst_ring_desc, ring_desc,
sizeof(struct reo_destination_ring));
msdu_link_desc_va = peer->rx_tid[tid].dst_ring_desc = dst_ring_desc;
dp_rx_cookie_2_link_desc_va(pdev->soc, &hbi);
hal_rx_defrag_save_info_from_ring_desc(msdu_link_desc_va, return QDF_STATUS_SUCCESS;
msdu_link_ptr_info, &hbi);
qdf_mem_copy(tmp_mpdu_desc_info, mpdu_desc_info,
sizeof(*tmp_mpdu_desc_info));
} }
/* /*
@@ -1058,9 +1119,9 @@ static void dp_rx_defrag_save_info_from_ring_desc(void *ring_desc,
* @soc: Pointer to the SOC data structure * @soc: Pointer to the SOC data structure
* @ring_desc: Pointer to the ring descriptor * @ring_desc: Pointer to the ring descriptor
* @mpdu_desc_info: MPDU descriptor info * @mpdu_desc_info: MPDU descriptor info
* @msdu_info: Pointer to MSDU descriptor info
* @tid: Traffic Identifier * @tid: Traffic Identifier
* @rx_desc: Pointer to rx descriptor * @rx_desc: Pointer to rx descriptor
* @rx_bfs: Number of bfs consumed
* *
* Returns: QDF_STATUS * Returns: QDF_STATUS
*/ */
@@ -1069,23 +1130,20 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
union dp_rx_desc_list_elem_t **head, union dp_rx_desc_list_elem_t **head,
union dp_rx_desc_list_elem_t **tail, union dp_rx_desc_list_elem_t **tail,
struct hal_rx_mpdu_desc_info *mpdu_desc_info, struct hal_rx_mpdu_desc_info *mpdu_desc_info,
struct hal_rx_msdu_desc_info *msdu_info, unsigned tid, struct dp_rx_desc *rx_desc,
unsigned tid, struct dp_rx_desc *rx_desc) uint32_t *rx_bfs)
{ {
uint8_t idx;
struct dp_rx_reorder_array_elem *rx_reorder_array_elem; struct dp_rx_reorder_array_elem *rx_reorder_array_elem;
struct dp_pdev *pdev; struct dp_pdev *pdev;
struct dp_peer *peer; struct dp_peer *peer;
uint16_t peer_id; uint16_t peer_id;
uint16_t rxseq, seq;
uint8_t fragno, more_frag, all_frag_present = 0; uint8_t fragno, more_frag, all_frag_present = 0;
uint16_t seq_num = mpdu_desc_info->mpdu_seq; uint16_t rxseq = mpdu_desc_info->mpdu_seq;
QDF_STATUS status; QDF_STATUS status;
struct dp_rx_tid *rx_tid; struct dp_rx_tid *rx_tid;
uint8_t mpdu_sequence_control_valid; uint8_t mpdu_sequence_control_valid;
uint8_t mpdu_frame_control_valid; uint8_t mpdu_frame_control_valid;
qdf_nbuf_t frag = rx_desc->nbuf; qdf_nbuf_t frag = rx_desc->nbuf;
uint8_t *rx_desc_info;
/* Check if the packet is from a valid peer */ /* Check if the packet is from a valid peer */
peer_id = DP_PEER_METADATA_PEER_ID_GET( peer_id = DP_PEER_METADATA_PEER_ID_GET(
@@ -1109,13 +1167,10 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
pdev = peer->vdev->pdev; pdev = peer->vdev->pdev;
rx_tid = &peer->rx_tid[tid]; rx_tid = &peer->rx_tid[tid];
seq = seq_num & (peer->rx_tid[tid].ba_win_size - 1); rx_reorder_array_elem = peer->rx_tid[tid].array;
qdf_assert(seq == 0);
rx_reorder_array_elem = &peer->rx_tid[tid].array[seq];
rx_desc_info = qdf_nbuf_data(frag);
mpdu_sequence_control_valid = mpdu_sequence_control_valid =
hal_rx_get_mpdu_sequence_control_valid(rx_desc_info); hal_rx_get_mpdu_sequence_control_valid(rx_desc->rx_buf_start);
/* Invalid MPDU sequence control field, MPDU is of no use */ /* Invalid MPDU sequence control field, MPDU is of no use */
if (!mpdu_sequence_control_valid) { if (!mpdu_sequence_control_valid) {
@@ -1129,7 +1184,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
} }
mpdu_frame_control_valid = mpdu_frame_control_valid =
hal_rx_get_mpdu_frame_control_valid(rx_desc_info); hal_rx_get_mpdu_frame_control_valid(rx_desc->rx_buf_start);
/* Invalid frame control field */ /* Invalid frame control field */
if (!mpdu_frame_control_valid) { if (!mpdu_frame_control_valid) {
@@ -1143,13 +1198,12 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
} }
/* Current mpdu sequence */ /* Current mpdu sequence */
rxseq = hal_rx_get_rx_sequence(rx_desc_info); more_frag = dp_rx_frag_get_more_frag_bit(rx_desc->rx_buf_start);
more_frag = hal_rx_get_rx_more_frag_bit(rx_desc_info);
/* HW does not populate the fragment number as of now /* HW does not populate the fragment number as of now
* need to get from the 802.11 header * need to get from the 802.11 header
*/ */
fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc_info); fragno = dp_rx_frag_get_mpdu_frag_number(rx_desc->rx_buf_start);
/* /*
* !more_frag: no more fragments to be delivered * !more_frag: no more fragments to be delivered
@@ -1173,7 +1227,6 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
/* Check if the fragment is for the same sequence or a different one */ /* Check if the fragment is for the same sequence or a different one */
if (rx_reorder_array_elem->head) { if (rx_reorder_array_elem->head) {
if (rxseq != rx_tid->curr_seq_num) { if (rxseq != rx_tid->curr_seq_num) {
/* Drop stored fragments if out of sequence /* Drop stored fragments if out of sequence
@@ -1198,6 +1251,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
} }
} else { } else {
/* Start of a new sequence */ /* Start of a new sequence */
dp_rx_defrag_cleanup(peer, tid);
rx_tid->curr_seq_num = rxseq; rx_tid->curr_seq_num = rxseq;
} }
@@ -1215,32 +1269,37 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
* have to use the next MSDU link descriptor and chain them together * have to use the next MSDU link descriptor and chain them together
* before reinjection * before reinjection
*/ */
if (more_frag == 0 || fragno == HAL_RX_NUM_MSDU_DESC) { if ((fragno == 0) && (rx_reorder_array_elem->head == frag)) {
/*
* Deep copy of MSDU link pointer and msdu descriptor structs
*/
idx = peer->rx_tid[tid].curr_ring_desc_idx;
if (idx < HAL_RX_MAX_SAVED_RING_DESC) {
dp_rx_defrag_save_info_from_ring_desc(ring_desc,
peer, tid, mpdu_desc_info);
peer->rx_tid[tid].curr_ring_desc_idx++; status = dp_rx_defrag_save_info_from_ring_desc(ring_desc,
} else { peer, tid);
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Max ring descr saved, dropping fragment"); if (status != QDF_STATUS_SUCCESS) {
/* QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
* Free up saved fragments and ring descriptors if any "%s: Unable to store ring desc !\n", __func__);
*/
goto end; goto end;
} }
} else {
dp_rx_add_to_free_desc_list(head, tail, rx_desc);
*rx_bfs = 1;
/* Return the non-head link desc */
if (dp_rx_link_desc_return(soc, ring_desc,
HAL_BM_ACTION_PUT_IN_IDLE_LIST) !=
QDF_STATUS_SUCCESS)
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to return link desc\n",
__func__);
} }
#ifdef DEFRAG_TIMEOUT
/* TODO: handle fragment timeout gracefully */ /* TODO: handle fragment timeout gracefully */
if (pdev->soc->rx.flags.defrag_timeout_check) { if (pdev->soc->rx.flags.defrag_timeout_check) {
dp_rx_defrag_waitlist_remove(peer, tid); dp_rx_defrag_waitlist_remove(peer, tid);
goto end; goto end;
} }
#endif
/* Yet to receive more fragments for this sequence number */ /* Yet to receive more fragments for this sequence number */
if (!all_frag_present) { if (!all_frag_present) {
uint32_t now_ms = uint32_t now_ms =
@@ -1249,8 +1308,7 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
peer->rx_tid[tid].defrag_timeout_ms = peer->rx_tid[tid].defrag_timeout_ms =
now_ms + pdev->soc->rx.defrag.timeout_ms; now_ms + pdev->soc->rx.defrag.timeout_ms;
dp_rx_defrag_waitlist_add(peer, tid); return QDF_STATUS_SUCCESS;
goto end;
} }
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
@@ -1266,16 +1324,22 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
} }
/* Re-inject the fragments back to REO for further processing */ /* Re-inject the fragments back to REO for further processing */
status = dp_rx_defrag_reo_reinject(peer, tid); status = dp_rx_defrag_reo_reinject(peer, tid,
if (QDF_IS_STATUS_SUCCESS(status)) rx_reorder_array_elem->head);
if (QDF_IS_STATUS_SUCCESS(status)) {
rx_reorder_array_elem->head = NULL;
rx_reorder_array_elem->tail = NULL;
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
"Fragmented sequence successfully reinjected"); "Fragmented sequence successfully reinjected");
}
else else
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Fragmented sequence reinjection failed"); "Fragmented sequence reinjection failed");
dp_rx_defrag_cleanup(peer, tid);
return QDF_STATUS_SUCCESS;
end: end:
dp_rx_defrag_cleanup(peer, tid, seq);
return QDF_STATUS_E_DEFRAG_ERROR; return QDF_STATUS_E_DEFRAG_ERROR;
} }
@@ -1308,8 +1372,9 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc,
void *link_desc_va; void *link_desc_va;
struct hal_buf_info buf_info; struct hal_buf_info buf_info;
struct hal_rx_msdu_list msdu_list; /* per MPDU list of MSDUs */ struct hal_rx_msdu_list msdu_list; /* per MPDU list of MSDUs */
uint32_t tid; qdf_nbuf_t msdu = NULL;
int idx; uint32_t tid, msdu_len;
int idx, rx_bfs = 0;
QDF_STATUS status; QDF_STATUS status;
qdf_assert(soc); qdf_assert(soc);
@@ -1345,20 +1410,38 @@ uint32_t dp_rx_frag_handle(struct dp_soc *soc, void *ring_desc,
qdf_assert(rx_desc); qdf_assert(rx_desc);
msdu = rx_desc->nbuf;
qdf_nbuf_unmap_single(soc->osdev, msdu,
QDF_DMA_BIDIRECTIONAL);
rx_desc->rx_buf_start = qdf_nbuf_data(msdu);
msdu_len = hal_rx_msdu_start_msdu_len_get(
rx_desc->rx_buf_start);
qdf_nbuf_set_pktlen(msdu, (msdu_len + RX_PKT_TLVS_LEN));
tid = hal_rx_mpdu_start_tid_get(rx_desc->rx_buf_start); tid = hal_rx_mpdu_start_tid_get(rx_desc->rx_buf_start);
/* Process fragment-by-fragment */ /* Process fragment-by-fragment */
status = dp_rx_defrag_store_fragment(soc, ring_desc, status = dp_rx_defrag_store_fragment(soc, ring_desc,
head, tail, mpdu_desc_info, head, tail, mpdu_desc_info,
&msdu_list.msdu_info[idx], tid, tid, rx_desc, &rx_bfs);
rx_desc);
if (QDF_IS_STATUS_SUCCESS(status)) if (QDF_IS_STATUS_SUCCESS(status)) {
if (rx_bfs)
rx_bufs_used++; rx_bufs_used++;
else } else {
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
"Rx Defragmentation error. mpdu_seq: 0x%x msdu_count: %d mpdu_flags: %d", "Rx Defrag err seq#:0x%x msdu_count:%d flags:%d",
mpdu_desc_info->mpdu_seq, mpdu_desc_info->msdu_count, mpdu_desc_info->mpdu_seq,
mpdu_desc_info->msdu_count,
mpdu_desc_info->mpdu_flags); mpdu_desc_info->mpdu_flags);
/* No point in processing rest of the fragments */
break;
}
} }
return rx_bufs_used; return rx_bufs_used;

View File

@@ -39,6 +39,8 @@
(IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == \
(IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
#define UNI_DESC_OWNER_SW 0x1
#define UNI_DESC_BUF_TYPE_RX_MSDU_LINK 0x6
/** /**
* struct dp_rx_defrag_cipher: structure to indicate cipher header * struct dp_rx_defrag_cipher: structure to indicate cipher header
* @ic_name: Name * @ic_name: Name
@@ -125,7 +127,16 @@ uint8_t dp_rx_frag_get_more_frag_bit(uint8_t *rx_desc_info)
struct ieee80211_frame *mac_hdr; struct ieee80211_frame *mac_hdr;
mac_hdr = dp_rx_frag_get_mac_hdr(rx_desc_info); mac_hdr = dp_rx_frag_get_mac_hdr(rx_desc_info);
return mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG; return (mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG) >> 2;
}
static inline
uint8_t dp_rx_get_pkt_dir(uint8_t *rx_desc_info)
{
struct ieee80211_frame *mac_hdr;
mac_hdr = dp_rx_frag_get_mac_hdr(rx_desc_info);
return mac_hdr->i_fc[1] & IEEE80211_FC1_DIR_MASK;
} }
#endif /* _DP_RX_DEFRAG_H */ #endif /* _DP_RX_DEFRAG_H */

View File

@@ -56,7 +56,7 @@ static inline bool dp_rx_desc_check_magic(struct dp_rx_desc *rx_desc)
* *
* Return: QDF_STATUS * Return: QDF_STATUS
*/ */
static QDF_STATUS QDF_STATUS
dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc, uint8_t bm_action) dp_rx_link_desc_return(struct dp_soc *soc, void *ring_desc, uint8_t bm_action)
{ {
void *buf_addr_info = HAL_RX_REO_BUF_ADDR_INFO_GET(ring_desc); void *buf_addr_info = HAL_RX_REO_BUF_ADDR_INFO_GET(ring_desc);
@@ -840,7 +840,10 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &hbi); link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &hbi);
hal_rx_msdu_list_get(link_desc_va, &msdu_list, &num_msdus); hal_rx_msdu_list_get(link_desc_va, &msdu_list, &num_msdus);
if (qdf_unlikely(msdu_list.rbm[0] != HAL_RX_BUF_RBM_SW3_BM)) { if (qdf_unlikely((msdu_list.rbm[0] !=
HAL_RX_BUF_RBM_SW3_BM) &&
(msdu_list.rbm[0] !=
HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST))) {
/* TODO */ /* TODO */
/* Call appropriate handler */ /* Call appropriate handler */
DP_STATS_INC(soc, rx.err.invalid_rbm, 1); DP_STATS_INC(soc, rx.err.invalid_rbm, 1);

View File

@@ -433,12 +433,8 @@ struct dp_rx_tid {
/* only used for defrag right now */ /* only used for defrag right now */
TAILQ_ENTRY(dp_rx_tid) defrag_waitlist_elem; TAILQ_ENTRY(dp_rx_tid) defrag_waitlist_elem;
/* MSDU link pointers used for reinjection */ /* Store dst desc for reinjection */
struct hal_rx_msdu_link_ptr_info void *dst_ring_desc;
transcap_msdu_link_ptr[HAL_RX_MAX_SAVED_RING_DESC];
struct hal_rx_mpdu_desc_info transcap_rx_mpdu_desc_info;
uint8_t curr_ring_desc_idx;
/* Sequence and fragments that are being processed currently */ /* Sequence and fragments that are being processed currently */
uint32_t curr_seq_num; uint32_t curr_seq_num;

View File

@@ -414,8 +414,23 @@ RX_MSDU_DETAILS_2_RX_MSDU_DESC_INFO_RX_MSDU_DESC_INFO_DETAILS_OFFSET))
RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \ RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_MASK, \
RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB)) RX_MPDU_INFO_2_FRAME_ENCRYPTION_INFO_VALID_LSB))
#define HAL_RX_FLD_SET(_ptr, _wrd, _field, _val) \
(*(uint32_t *)(((uint8_t *)_ptr) + \
_wrd ## _ ## _field ## _OFFSET) |= \
((_val << _wrd ## _ ## _field ## _LSB) & \
_wrd ## _ ## _field ## _MASK))
#define HAL_RX_UNIFORM_HDR_SET(_rx_msdu_link, _field, _val) \
HAL_RX_FLD_SET(_rx_msdu_link, UNIFORM_DESCRIPTOR_HEADER_0, \
_field, _val)
#define HAL_RX_MSDU_DESC_INFO_SET(_msdu_info_ptr, _field, _val) \
HAL_RX_FLD_SET(_msdu_info_ptr, RX_MSDU_DESC_INFO_0, \
_field, _val)
#define HAL_RX_MPDU_DESC_INFO_SET(_mpdu_info_ptr, _field, _val) \
HAL_RX_FLD_SET(_mpdu_info_ptr, RX_MPDU_DESC_INFO_0, \
_field, _val)
static inline void hal_rx_mpdu_desc_info_get(void *desc_addr, static inline void hal_rx_mpdu_desc_info_get(void *desc_addr,
struct hal_rx_mpdu_desc_info *mpdu_desc_info) struct hal_rx_mpdu_desc_info *mpdu_desc_info)
@@ -1028,6 +1043,28 @@ hal_rx_msdu_start_msdu_len_get(uint8_t *buf)
return msdu_len; return msdu_len;
} }
/**
* hal_rx_msdu_start_msdu_len_set(): API to set the MSDU length
* from rx_msdu_start TLV
*
* @buf: pointer to the start of RX PKT TLV headers
* @len: msdu length
*
* Return: none
*/
static inline void
hal_rx_msdu_start_msdu_len_set(uint8_t *buf, uint32_t len)
{
struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
struct rx_msdu_start *msdu_start =
&pkt_tlvs->msdu_start_tlv.rx_msdu_start;
void *wrd1;
wrd1 = (uint8_t *)msdu_start + RX_MSDU_START_1_MSDU_LENGTH_OFFSET;
*(uint32_t *)wrd1 &= (~RX_MSDU_START_1_MSDU_LENGTH_MASK);
*(uint32_t *)wrd1 |= len;
}
#define HAL_RX_MSDU_START_BW_GET(_rx_msdu_start) \ #define HAL_RX_MSDU_START_BW_GET(_rx_msdu_start) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\ (_HAL_MS((*_OFFSET_TO_WORD_PTR((_rx_msdu_start),\
RX_MSDU_START_5_RECEIVE_BANDWIDTH_OFFSET)), \ RX_MSDU_START_5_RECEIVE_BANDWIDTH_OFFSET)), \
@@ -1484,6 +1521,12 @@ hal_rx_mpdu_get_fr_ds(uint8_t *buf)
RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \ RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_MASK, \
RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB)) RX_MPDU_INFO_2_MAC_ADDR_AD2_VALID_LSB))
#define HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(_rx_mpdu_info) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \
RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_OFFSET)), \
RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_MASK, \
RX_MPDU_INFO_2_MAC_ADDR_AD3_VALID_LSB))
#define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \ #define HAL_RX_MPDU_AD1_31_0_GET(_rx_mpdu_info) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \
RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \ RX_MPDU_INFO_15_MAC_ADDR_AD1_31_0_OFFSET)), \
@@ -1508,6 +1551,18 @@ hal_rx_mpdu_get_fr_ds(uint8_t *buf)
RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \ RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_MASK, \
RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB)) RX_MPDU_INFO_17_MAC_ADDR_AD2_47_16_LSB))
#define HAL_RX_MPDU_AD3_31_0_GET(_rx_mpdu_info) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \
RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_OFFSET)), \
RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_MASK, \
RX_MPDU_INFO_18_MAC_ADDR_AD3_31_0_LSB))
#define HAL_RX_MPDU_AD3_47_32_GET(_rx_mpdu_info) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info, \
RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_OFFSET)), \
RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_MASK, \
RX_MPDU_INFO_19_MAC_ADDR_AD3_47_32_LSB))
/* /*
* hal_rx_mpdu_get_addr1(): API to check get address1 of the mpdu * hal_rx_mpdu_get_addr1(): API to check get address1 of the mpdu
* *
@@ -1577,6 +1632,41 @@ QDF_STATUS hal_rx_mpdu_get_addr2(uint8_t *buf, uint8_t *mac_addr)
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
/*
* hal_rx_mpdu_get_addr3(): API to get address3 of the mpdu
* in the packet
*
* @buf: pointer to the start of RX PKT TLV header
* @mac_addr: pointer to mac address
* Return: sucess/failure
*/
static inline
QDF_STATUS hal_rx_mpdu_get_addr3(uint8_t *buf, uint8_t *mac_addr)
{
struct __attribute__((__packed__)) hal_addr3 {
uint16_t ad3_15_0;
uint32_t ad3_47_16;
};
struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
struct rx_mpdu_start *mpdu_start =
&pkt_tlvs->mpdu_start_tlv.rx_mpdu_start;
struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details;
struct hal_addr3 *addr = (struct hal_addr3 *)mac_addr;
uint32_t mac_addr_ad3_valid;
mac_addr_ad3_valid = HAL_RX_MPDU_MAC_ADDR_AD3_VALID_GET(mpdu_info);
if (mac_addr_ad3_valid) {
addr->ad3_15_0 = HAL_RX_MPDU_AD3_31_0_GET(mpdu_info);
addr->ad3_47_16 = HAL_RX_MPDU_AD3_47_32_GET(mpdu_info);
return QDF_STATUS_SUCCESS;
}
return QDF_STATUS_E_FAILURE;
}
#define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \ #define HAL_RX_MSDU_END_DA_IDX_GET(_rx_msdu_end) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end, \
RX_MSDU_END_13_DA_IDX_OFFSET)), \ RX_MSDU_END_13_DA_IDX_OFFSET)), \