Ver código fonte

qcacmn: Break from the desc_freelist loop on REO cmd enqueue failure

UPDATE_RX_REO_QUEUE commands are queued in the REO_CMD
ring as part of peer cleanup for each tid. The cb
registered defers pocessing the entries in the
reo_desc_freelist based on either number of pending
entries or time threshold. In the scenario when
these entries from the freelist are processed as part
of next disconnection and if the REO_CMD enqueue fails,
the while loop over reo_desc_freelist does not exit
and will end up in a perpetual loop.

Fix is to break from the desc_freelist loop on REO
cmd enqueue failure.

Change-Id: I18ee31ec6a6150cd6952903cc154634b7de4ce60
CRs-Fixed: 2751223
Yeshwanth Sriram Guntuka 4 anos atrás
pai
commit
acc1ea0d14
2 arquivos alterados com 39 adições e 16 exclusões
  1. 38 16
      dp/wifi3.0/dp_peer.c
  2. 1 0
      dp/wifi3.0/dp_types.h

+ 38 - 16
dp/wifi3.0/dp_peer.c

@@ -2329,10 +2329,13 @@ static inline void dp_reo_limit_clean_batch_sz(uint32_t *list_size)
  * @desc: desc with resend update cmd flag set
  * @rx_tid: Desc RX tid associated with update cmd for resetting
  * valid field to 0 in h/w
+ *
+ * Return: QDF status
  */
-static void dp_resend_update_reo_cmd(struct dp_soc *soc,
-				     struct reo_desc_list_node *desc,
-				     struct dp_rx_tid *rx_tid)
+static QDF_STATUS
+dp_resend_update_reo_cmd(struct dp_soc *soc,
+			 struct reo_desc_list_node *desc,
+			 struct dp_rx_tid *rx_tid)
 {
 	struct hal_reo_cmd_params params;
 
@@ -2361,7 +2364,10 @@ static void dp_resend_update_reo_cmd(struct dp_soc *soc,
 				     (qdf_list_node_t *)desc);
 		dp_err_log("failed to send reo cmd CMD_UPDATE_RX_REO_QUEUE");
 		DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
+		return QDF_STATUS_E_FAILURE;
 	}
+
+	return QDF_STATUS_SUCCESS;
 }
 
 /*
@@ -2382,6 +2388,7 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt,
 	unsigned long curr_ts = qdf_get_system_timestamp();
 	uint32_t desc_size, tot_desc_size;
 	struct hal_reo_cmd_params params;
+	bool flush_failure = false;
 
 	if (reo_status->rx_queue_status.header.status == HAL_REO_CMD_DRAIN) {
 		qdf_mem_zero(reo_status, sizeof(*reo_status));
@@ -2392,11 +2399,10 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt,
 	} else if (reo_status->rx_queue_status.header.status !=
 		HAL_REO_CMD_SUCCESS) {
 		/* Should not happen normally. Just print error for now */
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			  "%s: Rx tid HW desc deletion failed(%d): tid %d",
-			  __func__,
-			  reo_status->rx_queue_status.header.status,
-			  freedesc->rx_tid.tid);
+		dp_info_rl("%s: Rx tid HW desc deletion failed(%d): tid %d",
+			   __func__,
+			   reo_status->rx_queue_status.header.status,
+			   freedesc->rx_tid.tid);
 	}
 
 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
@@ -2431,13 +2437,19 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt,
 
 		/* First process descs with resend_update_reo_cmd set */
 		if (desc->resend_update_reo_cmd) {
-			dp_resend_update_reo_cmd(soc, desc, rx_tid);
-			continue;
+			if (dp_resend_update_reo_cmd(soc, desc, rx_tid) !=
+			    QDF_STATUS_SUCCESS)
+				break;
+			else
+				continue;
 		}
 
 		/* Flush and invalidate REO descriptor from HW cache: Base and
 		 * extension descriptors should be flushed separately */
-		tot_desc_size = rx_tid->hw_qdesc_alloc_size;
+		if (desc->pending_ext_desc_size)
+			tot_desc_size = desc->pending_ext_desc_size;
+		else
+			tot_desc_size = rx_tid->hw_qdesc_alloc_size;
 		/* Get base descriptor size by passing non-qos TID */
 		desc_size = hal_get_reo_qdesc_size(soc->hal_soc, 0,
 						   DP_NON_QOS_TID);
@@ -2456,13 +2468,22 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt,
 							&params,
 							NULL,
 							NULL)) {
-				dp_err_rl("fail to send CMD_CACHE_FLUSH:"
-					  "tid %d desc %pK", rx_tid->tid,
-					  (void *)(rx_tid->hw_qdesc_paddr));
-				DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
+				dp_info_rl("fail to send CMD_CACHE_FLUSH:"
+					   "tid %d desc %pK", rx_tid->tid,
+					   (void *)(rx_tid->hw_qdesc_paddr));
+				desc->pending_ext_desc_size = tot_desc_size +
+								      desc_size;
+				dp_reo_desc_clean_up(soc, desc, reo_status);
+				flush_failure = true;
+				break;
 			}
 		}
 
+		if (flush_failure)
+			break;
+		else
+			desc->pending_ext_desc_size = desc_size;
+
 		/* Flush base descriptor */
 		qdf_mem_zero(&params, sizeof(params));
 		params.std.need_status = 1;
@@ -2486,10 +2507,11 @@ void dp_rx_tid_delete_cb(struct dp_soc *soc, void *cb_ctxt,
 			 * In case of MCL path add the desc back to the free
 			 * desc list and defer deletion.
 			 */
-			dp_err_log("%s: fail to send REO cmd to flush cache: tid %d",
+			dp_info_rl("%s: fail to send REO cmd to flush cache: tid %d",
 				   __func__, rx_tid->tid);
 			dp_reo_desc_clean_up(soc, desc, &reo_status);
 			DP_STATS_INC(soc, rx.err.reo_cmd_send_fail, 1);
+			break;
 		}
 	}
 	qdf_spin_unlock_bh(&soc->reo_desc_freelist_lock);

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

@@ -721,6 +721,7 @@ struct reo_desc_list_node {
 	unsigned long free_ts;
 	struct dp_rx_tid rx_tid;
 	bool resend_update_reo_cmd;
+	uint32_t pending_ext_desc_size;
 };
 
 #ifdef WLAN_FEATURE_DP_EVENT_HISTORY