浏览代码

qcacmn: Ensure nbuf count is less than no of segs

While preparing raw packets for transmission, the count
of nbuf belonging to one mpdu must be less than the
number of segments.This makes sure the frags array inside
seg_info does not go out of bounds.

Change-Id: I7fffba7f64da274aa73c558cfc63d90f4419a04d
Debasis Das 4 年之前
父节点
当前提交
c1184913b7
共有 4 个文件被更改,包括 16 次插入3 次删除
  1. 2 0
      dp/inc/cdp_txrx_stats_struct.h
  2. 1 0
      dp/wifi3.0/dp_internal.h
  3. 2 0
      dp/wifi3.0/dp_stats.c
  4. 11 3
      dp/wifi3.0/dp_tx.c

+ 2 - 0
dp/inc/cdp_txrx_stats_struct.h

@@ -1161,6 +1161,7 @@ struct cdp_rx_stats {
  * @bcast: Number of broadcast packets
  * @raw_pkt: Total Raw packets
  * @dma_map_error: DMA map error
+ * @num_frags_overflow_err: msdu's nbuf count exceeds num of segemnts
  * @num_seg: No of segments in TSO packets
  * @tso_pkt:total no of TSO packets
  * @non_tso_pkts: non - TSO packets
@@ -1206,6 +1207,7 @@ struct cdp_tx_ingress_stats {
 		struct cdp_pkt_info raw_pkt;
 		uint32_t dma_map_error;
 		uint32_t invalid_raw_pkt_datatype;
+		uint32_t num_frags_overflow_err;
 	} raw;
 
 	/* Scatter Gather packet info */

+ 1 - 0
dp/wifi3.0/dp_internal.h

@@ -714,6 +714,7 @@ static inline void dp_update_pdev_ingress_stats(struct dp_pdev *tgtobj,
 	DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.inspect_pkts);
 	DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.raw.raw_pkt);
 	DP_STATS_AGGR(tgtobj, srcobj, tx_i.raw.dma_map_error);
+	DP_STATS_AGGR(tgtobj, srcobj, tx_i.raw.num_frags_overflow_err);
 	DP_STATS_AGGR(tgtobj, srcobj, tx_i.sg.dropped_host.num);
 	DP_STATS_AGGR(tgtobj, srcobj, tx_i.sg.dropped_target);
 	DP_STATS_AGGR_PKT(tgtobj, srcobj, tx_i.sg.sg_pkt);

+ 2 - 0
dp/wifi3.0/dp_stats.c

@@ -6200,6 +6200,8 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev)
 		       pdev->stats.tx_i.raw.dma_map_error);
 	DP_PRINT_STATS("        RAW pkt type[!data] error = %d",
 		       pdev->stats.tx_i.raw.invalid_raw_pkt_datatype);
+	DP_PRINT_STATS("        Frags count overflow  error = %d",
+		       pdev->stats.tx_i.raw.num_frags_overflow_err);
 	DP_PRINT_STATS("Reinjected:");
 	DP_PRINT_STATS("	Packets = %d",
 		       pdev->stats.tx_i.reinject_pkts.num);

+ 11 - 3
dp/wifi3.0/dp_tx.c

@@ -1036,7 +1036,15 @@ static qdf_nbuf_t dp_tx_prepare_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 
 	for (curr_nbuf = nbuf, i = 0; curr_nbuf;
 			curr_nbuf = qdf_nbuf_next(curr_nbuf), i++) {
-
+		/*
+		 * Number of nbuf's must not exceed the size of the frags
+		 * array in seg_info.
+		 */
+		if (i >= DP_TX_MAX_NUM_FRAGS) {
+			dp_err_rl("nbuf cnt exceeds the max number of segs");
+			DP_STATS_INC(vdev, tx_i.raw.num_frags_overflow_err, 1);
+			goto error;
+		}
 		if (QDF_STATUS_SUCCESS !=
 			qdf_nbuf_map_nbytes_single(vdev->osdev,
 						   curr_nbuf,
@@ -1045,10 +1053,10 @@ static qdf_nbuf_t dp_tx_prepare_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				"%s dma map error ", __func__);
 			DP_STATS_INC(vdev, tx_i.raw.dma_map_error, 1);
-			mapped_buf_num = i;
 			goto error;
 		}
-
+		/* Update the count of mapped nbuf's */
+		mapped_buf_num++;
 		paddr = qdf_nbuf_get_frag_paddr(curr_nbuf, 0);
 		seg_info->frags[i].paddr_lo = paddr;
 		seg_info->frags[i].paddr_hi = ((uint64_t)paddr >> 32);