summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/dp/txrx/ol_tx_desc.c47
-rw-r--r--core/dp/txrx/ol_tx_desc.h24
-rw-r--r--core/dp/txrx/ol_tx_send.c40
3 files changed, 72 insertions, 39 deletions
diff --git a/core/dp/txrx/ol_tx_desc.c b/core/dp/txrx/ol_tx_desc.c
index 08294827a010..c3f39316ae13 100644
--- a/core/dp/txrx/ol_tx_desc.c
+++ b/core/dp/txrx/ol_tx_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2018, 2020 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
@@ -33,6 +33,7 @@
#include <ol_txrx_encap.h> /* OL_TX_RESTORE_HDR, etc */
#endif
#include <ol_txrx.h>
+#include <utils_api.h>
#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
static inline void ol_tx_desc_sanity_checks(struct ol_txrx_pdev_t *pdev,
@@ -1003,4 +1004,48 @@ void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev,
pdev->tso_num_seg_pool.num_free++;
qdf_spin_unlock_bh(&pdev->tso_num_seg_pool.tso_num_seg_mutex);
}
+
+bool collect_tso_frags(struct ol_txrx_pdev_t *pdev,
+ struct qdf_tso_seg_elem_t *tso_seg,
+ qdf_nbuf_t netbuf)
+{
+ uint8_t frag_cnt, num_frags = 0;
+ int frag_len = 0;
+ uint32_t tcp_seq_num;
+ uint16_t ip_len;
+
+ qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex);
+
+ if (tso_seg->seg.num_frags > 0)
+ num_frags = tso_seg->seg.num_frags - 1;
+
+ /*Num of frags in a tso seg cannot be less than 2 */
+ if (num_frags < 1) {
+ qdf_print("ERROR: num of frags in tso segment is %d\n",
+ (num_frags + 1));
+ qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
+ return false;
+ }
+
+ tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num;
+ tcp_seq_num = ani_cpu_to_be32(tcp_seq_num);
+
+ ip_len = tso_seg->seg.tso_flags.ip_len;
+ ip_len = ani_cpu_to_be16(ip_len);
+
+ for (frag_cnt = 0; frag_cnt < num_frags; frag_cnt++) {
+ qdf_mem_copy(qdf_nbuf_data(netbuf) + frag_len,
+ tso_seg->seg.tso_frags[frag_cnt].vaddr,
+ tso_seg->seg.tso_frags[frag_cnt].length);
+ frag_len += tso_seg->seg.tso_frags[frag_cnt].length;
+ }
+
+ qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
+
+ qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_PKT_LEN_OFFSET),
+ &ip_len, sizeof(ip_len));
+ qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_TCP_SEQ_NUM_OFFSET),
+ &tcp_seq_num, sizeof(tcp_seq_num));
+ return true;
+}
#endif
diff --git a/core/dp/txrx/ol_tx_desc.h b/core/dp/txrx/ol_tx_desc.h
index 6f920e4f0555..b29422ca0496 100644
--- a/core/dp/txrx/ol_tx_desc.h
+++ b/core/dp/txrx/ol_tx_desc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2017, 2020 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
@@ -239,7 +239,20 @@ void ol_tso_num_seg_free(struct ol_txrx_pdev_t *pdev,
void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev,
struct ol_txrx_msdu_info_t *msdu_info,
bool is_tso_seg_mapping_done);
-
+/**
+ * collect_tso_frags() - collect all TSO fragments
+ * @pdev: The txrx pdev sending the data
+ * @tso_seg: The TSO segment element to be checked
+ * @netbuf: Target netbuf used to store all data from TSO fragments
+ *
+ * This function collects data contained in all TSO fragments related
+ * to a certain TSO segment element and put them into a single netbuf.
+ *
+ * Return: true if TSO fragments are really collected; false otherwise
+ */
+bool collect_tso_frags(struct ol_txrx_pdev_t *pdev,
+ struct qdf_tso_seg_elem_t *tso_seg,
+ qdf_nbuf_t netbuf);
#else
#define ol_tso_alloc_segment(pdev) /*no-op*/
#define ol_tso_free_segment(pdev, tso_seg) /*no-op*/
@@ -247,6 +260,13 @@ void ol_free_remaining_tso_segs(ol_txrx_vdev_handle vdev,
#define ol_tso_num_seg_free(pdev, tso_num_seg) /*no-op*/
/*no-op*/
#define ol_free_remaining_tso_segs(vdev, msdu_info, is_tso_seg_mapping_done)
+static inline
+bool collect_tso_frags(struct ol_txrx_pdev_t *dev,
+ struct qdf_tso_seg_elem_t *tso_seg,
+ qdf_nbuf_t netbuf)
+{
+ return false;
+}
#endif
/**
diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c
index a1c433499fe2..66860a314865 100644
--- a/core/dp/txrx/ol_tx_send.c
+++ b/core/dp/txrx/ol_tx_send.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 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
@@ -837,6 +837,7 @@ ol_tx_process_mon_tx_completion(
int nbuf_len;
struct qdf_tso_seg_elem_t *tso_seg = NULL;
struct ol_mon_tx_status pkt_tx_status = {0};
+ bool frags_collected = false;
pkt_tx_status.status = status;
pkt_tx_status.tx_retry_cnt = payload->tx_retry_cnt;
@@ -881,44 +882,11 @@ ol_tx_process_mon_tx_completion(
qdf_nbuf_put_tail(netbuf, nbuf_len);
if (tx_desc->pkt_type == OL_TX_FRM_TSO) {
- uint8_t frag_cnt, num_frags = 0;
- int frag_len = 0;
- uint32_t tcp_seq_num;
- uint16_t ip_len;
-
- qdf_spin_lock_bh(&pdev->tso_seg_pool.tso_mutex);
-
- if (tso_seg->seg.num_frags > 0)
- num_frags = tso_seg->seg.num_frags - 1;
-
- /*Num of frags in a tso seg cannot be less than 2 */
- if (num_frags < 1) {
- qdf_print("ERROR: num of frags in tso segment is %d\n",
- (num_frags + 1));
+ frags_collected = collect_tso_frags(pdev, tso_seg, netbuf);
+ if (!frags_collected) {
qdf_nbuf_free(netbuf);
- qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
return;
}
-
- tcp_seq_num = tso_seg->seg.tso_flags.tcp_seq_num;
- tcp_seq_num = ani_cpu_to_be32(tcp_seq_num);
-
- ip_len = tso_seg->seg.tso_flags.ip_len;
- ip_len = ani_cpu_to_be16(ip_len);
-
- for (frag_cnt = 0; frag_cnt < num_frags; frag_cnt++) {
- qdf_mem_copy(qdf_nbuf_data(netbuf) + frag_len,
- tso_seg->seg.tso_frags[frag_cnt].vaddr,
- tso_seg->seg.tso_frags[frag_cnt].length);
- frag_len += tso_seg->seg.tso_frags[frag_cnt].length;
- }
-
- qdf_spin_unlock_bh(&pdev->tso_seg_pool.tso_mutex);
-
- qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_PKT_LEN_OFFSET),
- &ip_len, sizeof(ip_len));
- qdf_mem_copy((qdf_nbuf_data(netbuf) + IPV4_TCP_SEQ_NUM_OFFSET),
- &tcp_seq_num, sizeof(tcp_seq_num));
} else {
qdf_mem_copy(qdf_nbuf_data(netbuf),
qdf_nbuf_data(tx_desc->netbuf),