qcacmn: Add RX defrag timeout handler
Add tid to the defrag waitlist & timeout if further fragments are not received. Change-Id: Iff2d2c23fe796cf70bcc6aa43ab02a308a33ee9f CRs-Fixed: 2174750
This commit is contained in:
@@ -1965,6 +1965,13 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
|
||||
reo_params.rx_hash_enabled = true;
|
||||
}
|
||||
|
||||
/* setup the global rx defrag waitlist */
|
||||
TAILQ_INIT(&soc->rx.defrag.waitlist);
|
||||
soc->rx.defrag.timeout_ms =
|
||||
wlan_cfg_get_rx_defrag_min_timeout(soc->wlan_cfg_ctx);
|
||||
soc->rx.flags.defrag_timeout_check =
|
||||
wlan_cfg_get_defrag_timeout_check(soc->wlan_cfg_ctx);
|
||||
|
||||
out:
|
||||
hal_reo_setup(soc->hal_soc, &reo_params);
|
||||
|
||||
|
@@ -83,7 +83,70 @@ static void dp_rx_clear_saved_desc_info(struct dp_peer *peer, unsigned tid)
|
||||
peer->rx_tid[tid].dst_ring_desc = NULL;
|
||||
}
|
||||
|
||||
#ifdef DEFRAG_TIMEOUT
|
||||
/*
|
||||
* dp_rx_reorder_flush_frag(): Flush the frag list
|
||||
* @peer: Pointer to the peer data structure
|
||||
* @tid: Transmit ID (TID)
|
||||
*
|
||||
* Flush the per-TID frag list
|
||||
*
|
||||
* Returns: None
|
||||
*/
|
||||
void dp_rx_reorder_flush_frag(struct dp_peer *peer,
|
||||
unsigned int tid)
|
||||
{
|
||||
struct dp_rx_reorder_array_elem *rx_reorder_array_elem;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Flushing TID %d"), tid);
|
||||
|
||||
rx_reorder_array_elem = peer->rx_tid[tid].array;
|
||||
if (rx_reorder_array_elem->head) {
|
||||
dp_rx_defrag_frames_free(rx_reorder_array_elem->head);
|
||||
rx_reorder_array_elem->head = NULL;
|
||||
rx_reorder_array_elem->tail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_rx_defrag_waitlist_flush(): Flush SOC defrag wait list
|
||||
* @soc: DP SOC
|
||||
*
|
||||
* Flush fragments of all waitlisted TID's
|
||||
*
|
||||
* Returns: None
|
||||
*/
|
||||
void dp_rx_defrag_waitlist_flush(struct dp_soc *soc)
|
||||
{
|
||||
struct dp_rx_tid *rx_reorder, *tmp;
|
||||
uint32_t now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks());
|
||||
|
||||
TAILQ_FOREACH_SAFE(rx_reorder, &soc->rx.defrag.waitlist,
|
||||
defrag_waitlist_elem, tmp) {
|
||||
struct dp_peer *peer;
|
||||
struct dp_rx_tid *rx_reorder_base;
|
||||
unsigned int tid;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Current time %u"), now_ms);
|
||||
|
||||
if (rx_reorder->defrag_timeout_ms > now_ms)
|
||||
break;
|
||||
|
||||
tid = rx_reorder->tid;
|
||||
/* get index 0 of the rx_reorder array */
|
||||
rx_reorder_base = rx_reorder - tid;
|
||||
peer =
|
||||
container_of(rx_reorder_base, struct dp_peer,
|
||||
rx_tid[0]);
|
||||
|
||||
TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder,
|
||||
defrag_waitlist_elem);
|
||||
//dp_rx_defrag_waitlist_remove(peer, tid);
|
||||
dp_rx_reorder_flush_frag(peer, tid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_rx_defrag_waitlist_add(): Update per-PDEV defrag wait list
|
||||
* @peer: Pointer to the peer data structure
|
||||
@@ -98,6 +161,9 @@ static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid)
|
||||
struct dp_soc *psoc = peer->vdev->pdev->soc;
|
||||
struct dp_rx_tid *rx_reorder = &peer->rx_tid[tid];
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Adding TID %u to waitlist"), tid);
|
||||
|
||||
/* TODO: use LIST macros instead of TAIL macros */
|
||||
TAILQ_INSERT_TAIL(&psoc->rx.defrag.waitlist, rx_reorder,
|
||||
defrag_waitlist_elem);
|
||||
@@ -112,7 +178,7 @@ static void dp_rx_defrag_waitlist_add(struct dp_peer *peer, unsigned tid)
|
||||
*
|
||||
* Returns: None
|
||||
*/
|
||||
static void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid)
|
||||
void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid)
|
||||
{
|
||||
struct dp_pdev *pdev = peer->vdev->pdev;
|
||||
struct dp_soc *soc = pdev->soc;
|
||||
@@ -125,23 +191,16 @@ static void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid)
|
||||
return;
|
||||
}
|
||||
|
||||
rx_reorder = &peer->rx_tid[tid];
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
|
||||
FL("Remove TID %u from waitlist"), tid);
|
||||
|
||||
if (rx_reorder->defrag_waitlist_elem.tqe_next != NULL) {
|
||||
|
||||
TAILQ_REMOVE(&soc->rx.defrag.waitlist, rx_reorder,
|
||||
defrag_waitlist_elem);
|
||||
rx_reorder->defrag_waitlist_elem.tqe_next = NULL;
|
||||
rx_reorder->defrag_waitlist_elem.tqe_prev = NULL;
|
||||
} else if (rx_reorder->defrag_waitlist_elem.tqe_prev == NULL) {
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"waitlist->tqe_prev is NULL");
|
||||
rx_reorder->defrag_waitlist_elem.tqe_next = NULL;
|
||||
qdf_assert(0);
|
||||
TAILQ_FOREACH(rx_reorder, &soc->rx.defrag.waitlist,
|
||||
defrag_waitlist_elem) {
|
||||
if (rx_reorder->tid == tid)
|
||||
TAILQ_REMOVE(&soc->rx.defrag.waitlist,
|
||||
rx_reorder, defrag_waitlist_elem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dp_rx_defrag_fraglist_insert(): Create a per-sequence fragment list
|
||||
@@ -1257,17 +1316,18 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
|
||||
rx_reorder_array_elem->head = NULL;
|
||||
rx_reorder_array_elem->tail = NULL;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s mismatch, dropping earlier sequence ",
|
||||
(rxseq == rx_tid->curr_seq_num)
|
||||
? "address"
|
||||
: "seq number");
|
||||
|
||||
/*
|
||||
* The sequence number for this fragment becomes the
|
||||
* new sequence number to be processed
|
||||
*/
|
||||
rx_tid->curr_seq_num = rxseq;
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
|
||||
"%s mismatch, dropping earlier sequence ",
|
||||
(rxseq == rx_tid->curr_seq_num)
|
||||
? "address"
|
||||
: "seq number");
|
||||
}
|
||||
} else {
|
||||
/* Start of a new sequence */
|
||||
@@ -1314,13 +1374,9 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEFRAG_TIMEOUT
|
||||
/* 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);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Yet to receive more fragments for this sequence number */
|
||||
if (!all_frag_present) {
|
||||
uint32_t now_ms =
|
||||
@@ -1329,6 +1385,8 @@ static QDF_STATUS dp_rx_defrag_store_fragment(struct dp_soc *soc,
|
||||
peer->rx_tid[tid].defrag_timeout_ms =
|
||||
now_ms + pdev->soc->rx.defrag.timeout_ms;
|
||||
|
||||
dp_rx_defrag_waitlist_add(peer, tid);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2018 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
|
||||
@@ -139,4 +139,8 @@ uint8_t dp_rx_get_pkt_dir(uint8_t *rx_desc_info)
|
||||
return mac_hdr->i_fc[1] & IEEE80211_FC1_DIR_MASK;
|
||||
}
|
||||
|
||||
void dp_rx_defrag_waitlist_flush(struct dp_soc *soc);
|
||||
void dp_rx_reorder_flush_frag(struct dp_peer *peer,
|
||||
unsigned int tid);
|
||||
void dp_rx_defrag_waitlist_remove(struct dp_peer *peer, unsigned tid);
|
||||
#endif /* _DP_RX_DEFRAG_H */
|
||||
|
@@ -879,6 +879,8 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
|
||||
done:
|
||||
hal_srng_access_end(hal_soc, hal_ring);
|
||||
|
||||
if (soc->rx.flags.defrag_timeout_check)
|
||||
dp_rx_defrag_waitlist_flush(soc);
|
||||
|
||||
/* Assume MAC id = 0, owner = 0 */
|
||||
if (rx_bufs_used) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2018 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
|
||||
@@ -187,6 +187,7 @@
|
||||
#define WLAN_CFG_HTT_PKT_TYPE 2
|
||||
#define WLAN_CFG_MAX_PEER_ID 64
|
||||
|
||||
#define WLAN_CFG_RX_DEFRAG_TIMEOUT 100
|
||||
|
||||
#ifdef CONFIG_MCL
|
||||
static const int tx_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = {
|
||||
@@ -351,6 +352,9 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach()
|
||||
/*Enable checksum offload by default*/
|
||||
wlan_cfg_ctx->tcp_udp_checksumoffload = 1;
|
||||
|
||||
wlan_cfg_ctx->defrag_timeout_check = 1;
|
||||
wlan_cfg_ctx->rx_defrag_min_timeout = WLAN_CFG_RX_DEFRAG_TIMEOUT;
|
||||
|
||||
return wlan_cfg_ctx;
|
||||
}
|
||||
|
||||
@@ -697,6 +701,17 @@ int wlan_cfg_get_checksum_offload(struct wlan_cfg_dp_soc_ctxt *cfg)
|
||||
{
|
||||
return cfg->tcp_udp_checksumoffload;
|
||||
}
|
||||
|
||||
int wlan_cfg_get_rx_defrag_min_timeout(struct wlan_cfg_dp_soc_ctxt *cfg)
|
||||
{
|
||||
return cfg->rx_defrag_min_timeout;
|
||||
}
|
||||
|
||||
int wlan_cfg_get_defrag_timeout_check(struct wlan_cfg_dp_soc_ctxt *cfg)
|
||||
{
|
||||
return cfg->defrag_timeout_check;
|
||||
}
|
||||
|
||||
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
/**
|
||||
* wlan_cfg_get_tx_flow_stop_queue_th() - Get flow control stop threshold
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
|
||||
* * Copyright (c) 2013-2018 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
|
||||
@@ -146,11 +146,13 @@ struct wlan_cfg_dp_soc_ctxt {
|
||||
bool tso_enabled;
|
||||
bool napi_enabled;
|
||||
bool tcp_udp_checksumoffload;
|
||||
bool defrag_timeout_check;
|
||||
int nss_cfg;
|
||||
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
|
||||
uint32_t tx_flow_stop_queue_threshold;
|
||||
uint32_t tx_flow_start_queue_offset;
|
||||
#endif
|
||||
uint32_t rx_defrag_min_timeout;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -663,4 +665,7 @@ int wlan_cfg_get_tx_flow_stop_queue_th(struct wlan_cfg_dp_soc_ctxt *cfg);
|
||||
|
||||
int wlan_cfg_get_tx_flow_start_queue_offset(struct wlan_cfg_dp_soc_ctxt *cfg);
|
||||
#endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
|
||||
int wlan_cfg_get_rx_defrag_min_timeout(struct wlan_cfg_dp_soc_ctxt *cfg);
|
||||
|
||||
int wlan_cfg_get_defrag_timeout_check(struct wlan_cfg_dp_soc_ctxt *cfg);
|
||||
#endif
|
||||
|
مرجع در شماره جدید
Block a user