Browse Source

qcacld-3.0: Maintain length for each TSO segment

In current codeflow, we are maintaining the length of the TSO segments
belonging to one jumbo packet inside tso_info, which is common for
all the segments of one jumbo packet. This works if the length of
the segments (frag[1]) is the same. In case it is not, it ends up
assigning incorrect length to all the segments. This is resulting
GMS login failure.
Fix issue by maintaining the total length of the segment in the
qdf_tso_seg_t structure.
Re-factor code for easy readability
Add TSO_DEBUG prints which can be enabled (compile time) to debug
TSO issues

Change-Id: Ie0cf8434902c0713ef8d36dc36c105afa6b5eabc
CRs-Fixed: 1062556
(cherry picked from commit 0a851f054171cf4b2f5bd7e8cd6841e90d999928)
Mohit Khanna 8 years ago
parent
commit
38d0e9335d
3 changed files with 30 additions and 5 deletions
  1. 26 3
      core/dp/htt/htt_tx.c
  2. 3 1
      core/dp/txrx/ol_tx_desc.c
  3. 1 1
      core/dp/txrx/ol_txrx_internal.h

+ 26 - 3
core/dp/htt/htt_tx.c

@@ -1355,6 +1355,18 @@ htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc,
 		 tso_seg->seg.tso_flags;
 
 	/* First 24 bytes (6*4) contain the TSO flags */
+	TSO_DEBUG("%s seq# %u l2 len %d, ip len %d flags 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+		  __func__,
+		  tso_seg->seg.tso_flags.tcp_seq_num,
+		  tso_seg->seg.tso_flags.l2_len,
+		  tso_seg->seg.tso_flags.ip_len,
+		  *word,
+		  *(word + 1),
+		  *(word + 2),
+		  *(word + 3),
+		  *(word + 4),
+		  *(word + 5));
+
 	word += 6;
 
 	for (i = 0; i < tso_seg->seg.num_frags; i++) {
@@ -1369,6 +1381,12 @@ htt_tx_desc_fill_tso_info(htt_pdev_handle pdev, void *desc,
 		/* [31:16] length of the first buffer */
 		*word = (tso_seg->seg.tso_frags[i].length << 16) | hi;
 		word++;
+		TSO_DEBUG("%s frag[%d] ptr_low 0x%x ptr_hi 0x%x len %u\n",
+			__func__, i,
+			msdu_ext_desc->frags[i].u.frag32.ptr_low,
+			msdu_ext_desc->frags[i].u.frag32.ptr_hi,
+			msdu_ext_desc->frags[i].u.frag32.len);
+
 	}
 
 	if (tso_seg->seg.num_frags < FRAG_NUM_MAX) {
@@ -1671,10 +1689,15 @@ htt_tx_desc_init(htt_pdev_handle pdev,
 
 	local_word1 = 0;
 
-	if (tso_info->is_tso)
-		HTT_TX_DESC_FRM_LEN_SET(local_word1, tso_info->total_len);
-	else
+	if (tso_info->is_tso) {
+		uint32_t total_len = tso_info->curr_seg->seg.total_len;
+
+		HTT_TX_DESC_FRM_LEN_SET(local_word1, total_len);
+		TSO_DEBUG("%s setting HTT TX DESC Len = curr_seg->seg.total_len %d\n",
+			  __func__, total_len);
+	} else {
 		HTT_TX_DESC_FRM_LEN_SET(local_word1, qdf_nbuf_len(msdu));
+	}
 
 	HTT_TX_DESC_FRM_ID_SET(local_word1, msdu_id);
 	*word1 = local_word1;

+ 3 - 1
core/dp/txrx/ol_tx_desc.c

@@ -656,7 +656,9 @@ void ol_tx_desc_frame_list_free(struct ol_txrx_pdev_t *pdev,
 		/* restore original hdr offset */
 		OL_TX_RESTORE_HDR(tx_desc, msdu);
 #endif
-		qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_TO_DEVICE);
+		if (qdf_nbuf_get_users(msdu) <= 1)
+			qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_TO_DEVICE);
+
 		/* free the tx desc */
 		ol_tx_desc_free(pdev, tx_desc);
 		/* link the netbuf into a list to free as a batch */

+ 1 - 1
core/dp/txrx/ol_txrx_internal.h

@@ -693,7 +693,7 @@ NOT_IP_TCP:
 	do { \
 		if (_p_cntrs == 1) { \
 			TXRX_STATS_ADD(_pdev, pub.tx.tso.tso_hist.pkts_1, 1); \
-		} else if (_p_cntrs > 2 && _p_cntrs <= 5) {                   \
+		} else if (_p_cntrs >= 2 && _p_cntrs <= 5) {                   \
 			TXRX_STATS_ADD(_pdev,                                 \
 				pub.tx.tso.tso_hist.pkts_2_5, 1);             \
 		} else if (_p_cntrs > 5 && _p_cntrs <= 10) {                  \