summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandrasekaran, Manishekar <cmshekar@qti.qualcomm.com>2014-12-26 12:42:04 +0530
committerAnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com>2014-12-30 17:41:30 +0530
commit12e4cf04d8ca15ebe039f07c606ccc69ed2ac8b6 (patch)
treecd1cae1c261199b9fc77ebec9cb026dc530c4cdf
parentc611d6917368078ab1cafdcf52b37099fdc15402 (diff)
qcacld: Classify DHCP frames as high priority to avoid frame drop
For SDIO 2.0, the maximum UL is 50-60 Mbps. But, when high UDP traffic (300Mbps) is run on a p2p connection in SDIO 2.0, we are hitting low rsrc threshold and some queued frames are getting dropped to provide enough tx descriptors for new frames which may be of higher priority. This is as per our current implementation. Now, when DHCP renewal happens during the above mentioned scenario, TID of multicast packets are set to low priority mcast, bcast category and TID of unicast DHCP packets are received with TID as best effort When frame drop happens, the above DHCP frames are dropped because of lower priority. Hence DHCP renewal fails, P2P connection is terminated. This is fixed by marking the DHCP frames as high priority. Change-Id: I9318d444e311ae2041b325c404734bb292cd5b43 CRs-Fixed: 775540
-rw-r--r--CORE/CLD_TXRX/TXRX/ol_tx_classify.c20
-rw-r--r--CORE/SERVICES/COMMON/adf/adf_nbuf.c26
-rw-r--r--CORE/SERVICES/COMMON/adf/adf_nbuf.h18
-rw-r--r--CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h1
4 files changed, 62 insertions, 3 deletions
diff --git a/CORE/CLD_TXRX/TXRX/ol_tx_classify.c b/CORE/CLD_TXRX/TXRX/ol_tx_classify.c
index 0c523d90d42b..bc9d5652ce5e 100644
--- a/CORE/CLD_TXRX/TXRX/ol_tx_classify.c
+++ b/CORE/CLD_TXRX/TXRX/ol_tx_classify.c
@@ -94,6 +94,9 @@ ol_tx_classify_htt2_frm(
#define OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, netbuf, msdu_info) /* no-op */
#endif /* QCA_TX_HTT2_SUPPORT */
+/* DHCP go with voice priority: WMM_AC_TO_TID1(WMM_AC_VO);*/
+#define TX_DHCP_TID 6
+
/* EAPOL go with voice priority: WMM_AC_TO_TID1(WMM_AC_VO);*/
#define TX_EAPOL_TID 6
@@ -275,9 +278,15 @@ ol_tx_tid(
tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_ethernet;
ol_tx_set_ether_type(datap, tx_msdu_info);
- tid = tx_msdu_info->htt.info.ext_tid == ADF_NBUF_TX_EXT_TID_INVALID ?
- ol_tx_tid_by_ether_type(datap, tx_msdu_info) :
- tx_msdu_info->htt.info.ext_tid;
+ if (A_STATUS_OK == adf_nbuf_is_dhcp_pkt(tx_nbuf)) {
+ /* DHCP frame to go with voice priority */
+ tid = TX_DHCP_TID;
+ } else {
+ tid =
+ tx_msdu_info->htt.info.ext_tid == ADF_NBUF_TX_EXT_TID_INVALID ?
+ ol_tx_tid_by_ether_type(datap, tx_msdu_info) :
+ tx_msdu_info->htt.info.ext_tid;
+ }
} else if (pdev->frame_format == wlan_frm_fmt_native_wifi) {
struct llc_snap_hdr_t *llc;
@@ -343,6 +352,11 @@ ol_tx_classify(
vdev->mac_addr.raw[2], vdev->mac_addr.raw[3],
vdev->mac_addr.raw[4], vdev->mac_addr.raw[5]);
return NULL; /* error */
+ } else if (A_STATUS_OK ==
+ adf_nbuf_is_dhcp_pkt(tx_nbuf)) {
+ /* DHCP frame to go with voice priority */
+ txq = &peer->txqs[TX_DHCP_TID];
+ tx_msdu_info->htt.info.ext_tid = TX_DHCP_TID;
}
/*
* The following line assumes each peer object has a single ID.
diff --git a/CORE/SERVICES/COMMON/adf/adf_nbuf.c b/CORE/SERVICES/COMMON/adf/adf_nbuf.c
index bf8d95264500..b5a0cacd5517 100644
--- a/CORE/SERVICES/COMMON/adf/adf_nbuf.c
+++ b/CORE/SERVICES/COMMON/adf/adf_nbuf.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <adf_os_types.h>
#include <adf_nbuf.h>
+#include <adf_os_io.h>
adf_nbuf_trace_update_t trace_update_cb = NULL;
@@ -383,6 +384,30 @@ __adf_nbuf_reg_trace_cb(adf_nbuf_trace_update_t cb_func_ptr)
return;
}
+a_status_t
+__adf_nbuf_is_dhcp_pkt(struct sk_buff *skb)
+{
+ a_uint16_t SPort;
+ a_uint16_t DPort;
+
+ SPort = (a_uint16_t)(*(a_uint16_t *)(skb->data + ADF_NBUF_TRAC_IPV4_OFFSET +
+ ADF_NBUF_TRAC_IPV4_HEADER_SIZE));
+ DPort = (a_uint16_t)(*(a_uint16_t *)(skb->data + ADF_NBUF_TRAC_IPV4_OFFSET +
+ ADF_NBUF_TRAC_IPV4_HEADER_SIZE + sizeof(a_uint16_t)));
+
+ if (((ADF_NBUF_TRAC_DHCP_SRV_PORT == adf_os_cpu_to_be16(SPort)) &&
+ (ADF_NBUF_TRAC_DHCP_CLI_PORT == adf_os_cpu_to_be16(DPort))) ||
+ ((ADF_NBUF_TRAC_DHCP_CLI_PORT == adf_os_cpu_to_be16(SPort)) &&
+ (ADF_NBUF_TRAC_DHCP_SRV_PORT == adf_os_cpu_to_be16(DPort))))
+ {
+ return A_STATUS_OK;
+ }
+ else
+ {
+ return A_STATUS_FAILED;
+ }
+}
+
#ifdef QCA_PKT_PROTO_TRACE
void
__adf_nbuf_trace_update(struct sk_buff *buf, char *event_string)
@@ -449,3 +474,4 @@ EXPORT_SYMBOL(__adf_nbuf_get_tid);
EXPORT_SYMBOL(__adf_nbuf_set_tid);
EXPORT_SYMBOL(__adf_nbuf_get_exemption_type);
EXPORT_SYMBOL(__adf_nbuf_dmamap_set_cb);
+EXPORT_SYMBOL(__adf_nbuf_is_dhcp_pkt);
diff --git a/CORE/SERVICES/COMMON/adf/adf_nbuf.h b/CORE/SERVICES/COMMON/adf/adf_nbuf.h
index abec0928b53d..602e7d12e54c 100644
--- a/CORE/SERVICES/COMMON/adf/adf_nbuf.h
+++ b/CORE/SERVICES/COMMON/adf/adf_nbuf.h
@@ -54,6 +54,11 @@
#define NBUF_PKT_TRAC_MAX_STRING 12
#define NBUF_PKT_TRAC_PROTO_STRING 4
+#define ADF_NBUF_TRAC_IPV4_OFFSET 14
+#define ADF_NBUF_TRAC_IPV4_HEADER_SIZE 20
+#define ADF_NBUF_TRAC_DHCP_SRV_PORT 67
+#define ADF_NBUF_TRAC_DHCP_CLI_PORT 68
+
/**
* @brief Platform indepedent packet abstraction
*/
@@ -1133,4 +1138,17 @@ adf_nbuf_get_tx_parallel_dnload_frm(adf_nbuf_t buf)
return __adf_nbuf_get_tx_htt2_frm(buf);
}
+/**
+ * @brief this will return if the skb data is a dhcp packet or not
+ *
+ * @param[in] buf buffer
+ *
+ * @return A_STATUS_OK if packet is DHCP packet
+ */
+static inline a_status_t
+adf_nbuf_is_dhcp_pkt(adf_nbuf_t buf)
+{
+ return (__adf_nbuf_is_dhcp_pkt(buf));
+}
+
#endif
diff --git a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h
index fa168f4d40b6..bc51123a2d67 100644
--- a/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h
+++ b/CORE/SERVICES/COMMON/adf/linux/adf_nbuf_pvt.h
@@ -264,6 +264,7 @@ void __adf_nbuf_dmamap_info(__adf_os_dma_map_t bmap, adf_os_dmamap_in
void __adf_nbuf_frag_info(struct sk_buff *skb, adf_os_sglist_t *sg);
void __adf_nbuf_dmamap_set_cb(__adf_os_dma_map_t dmap, void *cb, void *arg);
void __adf_nbuf_reg_trace_cb(adf_nbuf_trace_update_t cb_func_ptr);
+a_status_t __adf_nbuf_is_dhcp_pkt(struct sk_buff *skb);
#ifdef QCA_PKT_PROTO_TRACE
void