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:
psimha
2018-01-10 15:30:03 -08:00
کامیت شده توسط snandini
والد 7e69eaa303
کامیت fc2f91b86a
6فایلهای تغییر یافته به همراه121 افزوده شده و 30 حذف شده

مشاهده پرونده

@@ -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