Przeglądaj źródła

qcacmn: Lock Spectral detector list and session info structs

Add locks for detector list, per-session report info
and per-session detector map, to avoid inconsistent
concurrent accesses.
Using spin_lock_bh for locking between Process and
Tasklet context.

CRs-Fixed: 2983801
Change-Id: If709fd91f193072f07b9dae19bf48e6da2d369d3
Jhalak Naik 4 lat temu
rodzic
commit
0405359a6c

+ 32 - 3
target_if/spectral/target_if_spectral.c

@@ -2474,6 +2474,10 @@ target_if_spectral_detach(struct target_if_spectral *spectral)
 		qdf_spinlock_destroy(&spectral->spectral_lock);
 		qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
 
+		qdf_spinlock_destroy(&spectral->detector_list_lock);
+		qdf_spinlock_destroy(&spectral->session_report_info_lock);
+		qdf_spinlock_destroy(&spectral->session_det_map_lock);
+
 		qdf_mem_free(spectral);
 		spectral = NULL;
 	}
@@ -2900,11 +2904,14 @@ target_if_spectral_detector_list_init(struct target_if_spectral *spectral)
 	for (; ch_width <= CH_WIDTH_80P80MHZ; ch_width++) {
 		/* Normal spectral scan */
 		smode = SPECTRAL_SCAN_MODE_NORMAL;
+		spectral_debug("is_hw_mode_sbs: %d is_using_phya1:%d",
+			       is_hw_mode_sbs, is_using_phya1);
+
+		qdf_spin_lock_bh(&spectral->detector_list_lock);
+
 		det_list = &spectral->detector_list[smode][ch_width];
 		det_list->num_detectors = 1;
 
-		spectral_debug("is_hw_mode_sbs: %d is_using_phya1:%d",
-			       is_hw_mode_sbs, is_using_phya1);
 		if (is_hw_mode_sbs && is_using_phya1)
 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1;
 		else
@@ -2927,12 +2934,16 @@ target_if_spectral_detector_list_init(struct target_if_spectral *spectral)
 			 * scan. Only 20/40/80 MHz is supported on platforms
 			 * with fragmentation, as only 1 detector is available.
 			 */
-			if (is_ch_width_160_or_80p80(ch_width))
+			if (is_ch_width_160_or_80p80(ch_width)) {
+				qdf_spin_unlock_bh(
+						&spectral->detector_list_lock);
 				continue;
+			}
 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_2;
 		} else {
 			det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1;
 		}
+		qdf_spin_unlock_bh(&spectral->detector_list_lock);
 	}
 
 	return QDF_STATUS_SUCCESS;
@@ -3134,6 +3145,10 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
 			init_160mhz_delivery_state_machine(spectral);
 	}
 
+	qdf_spinlock_create(&spectral->detector_list_lock);
+	qdf_spinlock_create(&spectral->session_report_info_lock);
+	qdf_spinlock_create(&spectral->session_det_map_lock);
+
 	return spectral;
 
 fail:
@@ -5001,6 +5016,7 @@ target_if_spectral_populate_session_report_info(
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
 	/* Fill per-session report information, based on the spectral mode */
 	rpt_info = &spectral->report_info[smode];
 
@@ -5018,6 +5034,8 @@ target_if_spectral_populate_session_report_info(
 		rpt_info->num_spans = 1;
 	}
 
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -5063,13 +5081,17 @@ target_if_spectral_populate_session_detector_info(
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
 	rpt_info = &spectral->report_info[smode];
+
+	qdf_spin_lock_bh(&spectral->detector_list_lock);
 	/* Fill per-sesion detector-level information */
 	detector_list = &spectral->detector_list[smode][rpt_info->sscan_bw];
 
 	for (det = 0; det < detector_list->num_detectors; det++) {
 		struct per_session_det_map *det_map;
 
+		qdf_spin_lock_bh(&spectral->session_det_map_lock);
 		det_map = &spectral->det_map[detector_list->detectors[det]];
 		if (detector_list->num_detectors > 1) {
 			if (det == 0) {
@@ -5118,7 +5140,11 @@ target_if_spectral_populate_session_detector_info(
 			is_sec80 = !is_sec80;
 		}
 		det_map->det_map_valid = true;
+		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 	}
+	qdf_spin_unlock_bh(&spectral->detector_list_lock);
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -5431,9 +5457,12 @@ target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev,
 	spectral->send_single_packet = 0;
 	spectral->sc_spectral_scan = 0;
 
+	qdf_spin_lock_bh(&spectral->session_det_map_lock);
 	for (det = 0; det < MAX_DETECTORS_PER_PDEV; det++)
 		spectral->det_map[det].det_map_valid = false;
 
+	qdf_spin_unlock_bh(&spectral->session_det_map_lock);
+
 	qdf_spin_unlock(&spectral->spectral_lock);
 
 	return QDF_STATUS_SUCCESS;

+ 6 - 0
target_if/spectral/target_if_spectral.h

@@ -1180,9 +1180,12 @@ struct sscan_detector_list {
  * @finite_scan: Parameters for finite Spectral scan
  * @detector_list: Detector list for a given Spectral scan mode and channel
  * width, based on the target type.
+ * @detector_list_lock: Lock to synchronize accesses to detector list
  * @det_map: Map of per-session detector information keyed by the Spectral HW
  * detector id.
+ * @session_det_map_lock: Lock to synchronize accesses to session detector map
  * @report_info: Per session info to be filled at report level in SAMP message
+ * @session_report_info_lock: Lock to synchronize access to session report info
  */
 struct target_if_spectral {
 	struct wlan_objmgr_pdev *pdev_obj;
@@ -1306,8 +1309,11 @@ struct target_if_spectral {
 					finite_scan[SPECTRAL_SCAN_MODE_MAX];
 	struct sscan_detector_list
 			detector_list[SPECTRAL_SCAN_MODE_MAX][CH_WIDTH_MAX];
+	qdf_spinlock_t detector_list_lock;
 	struct per_session_det_map det_map[MAX_DETECTORS_PER_PDEV];
+	qdf_spinlock_t session_det_map_lock;
 	struct per_session_report_info report_info[SPECTRAL_SCAN_MODE_MAX];
+	qdf_spinlock_t session_report_info_lock;
 };
 
 /**

+ 10 - 0
target_if/spectral/target_if_spectral_netlink.c

@@ -71,7 +71,10 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_det_map_lock);
+
 	if (!spectral->det_map[params->hw_detector_id].det_map_valid) {
+		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 		spectral_info("Detector Map not valid for det id = %d",
 			      params->hw_detector_id);
 		return QDF_STATUS_E_FAILURE;
@@ -83,6 +86,7 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 						  msg_type,
 						  det_map->buf_type);
 	if (!spec_samp_msg) {
+		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 		spectral_err_rl("Spectral SAMP message is NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
@@ -262,6 +266,8 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 
 		p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
 
+		qdf_spin_lock_bh(&spectral->session_report_info_lock);
+
 		rpt_info = &spectral->report_info[spectral_mode];
 		spec_samp_msg->signature = SPECTRAL_SIGNATURE;
 		p_sops->get_mac_address(spectral, spec_samp_msg->macaddr);
@@ -277,6 +283,9 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 		spec_samp_msg->sscan_bw = rpt_info->sscan_bw;
 		spec_samp_msg->fft_width = FFT_BIN_SIZE_1BYTE;
 		spec_samp_msg->num_freq_spans = rpt_info->num_spans;
+
+		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 		spec_samp_msg->spectral_upper_rssi = params->upper_rssi;
 		spec_samp_msg->spectral_lower_rssi = params->lower_rssi;
 		qdf_mem_copy(spec_samp_msg->spectral_chain_ctl_rssi,
@@ -296,6 +305,7 @@ target_if_spectral_fill_samp_msg(struct target_if_spectral *spectral,
 			reset_160mhz_delivery_state_machine(spectral,
 							    spectral_mode);
 	}
+	qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 55 - 1
target_if/spectral/target_if_spectral_phyerr.c

@@ -963,13 +963,18 @@ target_if_populate_det_start_end_freqs(struct target_if_spectral *spectral,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
+
 	ch_width = spectral->report_info[smode].sscan_bw;
 	is_fragmentation_160 = spectral->rparams.fragmentation_160[smode];
 
 	rpt_info = &spectral->report_info[smode];
+
+	qdf_spin_lock_bh(&spectral->detector_list_lock);
 	detector_list = &spectral->detector_list[smode][ch_width];
 
 	for (det = 0; det < detector_list->num_detectors; det++) {
+		qdf_spin_lock_bh(&spectral->session_det_map_lock);
 		det_map = &spectral->det_map
 				[detector_list->detectors[det]];
 		dest_det_info = &det_map->dest_det_info[0];
@@ -1004,6 +1009,11 @@ target_if_populate_det_start_end_freqs(struct target_if_spectral *spectral,
 			break;
 
 		default:
+			qdf_spin_unlock_bh(&spectral->session_det_map_lock);
+			qdf_spin_unlock_bh(&spectral->detector_list_lock);
+			qdf_spin_unlock_bh(
+					&spectral->session_report_info_lock);
+
 			return QDF_STATUS_E_FAILURE;
 		}
 
@@ -1014,8 +1024,13 @@ target_if_populate_det_start_end_freqs(struct target_if_spectral *spectral,
 						      start_end_freq_arr);
 		dest_det_info->start_freq = start_end_freq_arr[0];
 		dest_det_info->end_freq = start_end_freq_arr[1];
+
+		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 	}
 
+	qdf_spin_unlock_bh(&spectral->detector_list_lock);
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1053,6 +1068,8 @@ target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
+
 	ch_width = spectral->report_info[smode].sscan_bw;
 	is_fragmentation_160 = spectral->rparams.fragmentation_160[smode];
 	spectral_fft_size = spectral->params[smode].ss_fft_size;
@@ -1061,16 +1078,19 @@ target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
 		target_if_spectral_get_num_fft_bins(spectral_fft_size,
 						    rpt_mode);
 	if (num_fft_bins < 0) {
+		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
 		spectral_err_rl("Invalid number of FFT bins %d",
 				num_fft_bins);
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	qdf_spin_lock_bh(&spectral->detector_list_lock);
 	detector_list = &spectral->detector_list[smode][ch_width];
 
 	for (det = 0; det < detector_list->num_detectors; det++) {
 		uint16_t lb_extrabins_offset = 0;
 
+		qdf_spin_lock_bh(&spectral->session_det_map_lock);
 		det_map = &spectral->det_map
 				[detector_list->detectors[det]];
 		dest_det_info = &det_map->dest_det_info[0];
@@ -1104,6 +1124,11 @@ target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
 			}
 			break;
 		default:
+			qdf_spin_unlock_bh(&spectral->session_det_map_lock);
+			qdf_spin_unlock_bh(&spectral->detector_list_lock);
+			qdf_spin_unlock_bh(
+					&spectral->session_report_info_lock);
+
 			return QDF_STATUS_E_FAILURE;
 		}
 		dest_det_info->dest_start_bin_idx = start_bin;
@@ -1125,7 +1150,10 @@ target_if_populate_fft_bins_info(struct target_if_spectral *spectral,
 					dest_det_info->lb_extrabins_start_idx +
 					dest_det_info->lb_extrabins_num;
 		dest_det_info->src_start_bin_idx = 0;
+		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
 	}
+	qdf_spin_unlock_bh(&spectral->detector_list_lock);
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -1182,6 +1210,8 @@ target_if_update_session_info_from_report_ctx(
 
 	p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
+
 	rpt_info = &spectral->report_info[smode];
 	ch_width = rpt_info->sscan_bw;
 	is_fragmentation_160 = spectral->rparams.fragmentation_160[smode];
@@ -1199,6 +1229,7 @@ target_if_update_session_info_from_report_ctx(
 		rpt_info->pri20_freq, rpt_info->operating_bw, smode);
 
 	if (QDF_IS_STATUS_ERROR(ret)) {
+		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
 		spectral_err_rl("Unable to unify cfreq1/cfreq2");
 		return QDF_STATUS_E_FAILURE;
 	}
@@ -1214,6 +1245,7 @@ target_if_update_session_info_from_report_ctx(
 		rpt_info->sscan_cfreq1 = rpt_info->cfreq1;
 		rpt_info->sscan_cfreq2 = rpt_info->cfreq2;
 	}
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
 
 	if (ch_width == CH_WIDTH_80P80MHZ && wlan_psoc_nif_fw_ext_cap_get(
 	    psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
@@ -1230,8 +1262,10 @@ target_if_update_session_info_from_report_ctx(
 		 * normal/agile spectral scan. So, detector_list will
 		 * have only one detector
 		 */
+		qdf_spin_lock_bh(&spectral->detector_list_lock);
 		detector_list = &spectral->detector_list[smode][ch_width];
 
+		qdf_spin_lock_bh(&spectral->session_det_map_lock);
 		det_map = &spectral->det_map[detector_list->detectors[0]];
 
 		dest_det_info = &det_map->dest_det_info[0];
@@ -1242,6 +1276,7 @@ target_if_update_session_info_from_report_ctx(
 		dest_det_info->src_start_bin_idx = marker->start_pri80 *
 						   fft_bin_size;
 		/* Set start and end frequencies */
+		qdf_spin_lock_bh(&spectral->session_report_info_lock);
 		target_if_spectral_set_start_end_freq(rpt_info->sscan_cfreq1,
 						      ch_width,
 						      is_fragmentation_160,
@@ -1279,6 +1314,10 @@ target_if_update_session_info_from_report_ctx(
 		dest_det_info->end_freq =
 				max(det_map->dest_det_info[0].start_freq,
 				    det_map->dest_det_info[1].start_freq);
+
+		qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+		qdf_spin_unlock_bh(&spectral->session_det_map_lock);
+		qdf_spin_unlock_bh(&spectral->detector_list_lock);
 	} else {
 		ret = target_if_populate_fft_bins_info(spectral, smode);
 		if (QDF_IS_STATUS_ERROR(ret)) {
@@ -1292,6 +1331,7 @@ target_if_update_session_info_from_report_ctx(
 			return QDF_STATUS_E_FAILURE;
 		}
 	}
+
 	return QDF_STATUS_SUCCESS;
 }
 #endif /* OPTIMIZED_SAMP_MESSAGE */
@@ -1338,7 +1378,10 @@ target_if_spectral_populate_samp_params_gen2(
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
 	ch_width = spectral->report_info[smode].sscan_bw;
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 	acs_stats = phyerr_info->acs_stats;
 	pfft = phyerr_info->pfft;
 	p_sfft = phyerr_info->p_sfft;
@@ -1493,7 +1536,10 @@ target_if_process_phyerr_gen2(struct target_if_spectral *spectral,
 		goto fail;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
 	ch_width = spectral->report_info[SPECTRAL_SCAN_MODE_NORMAL].sscan_bw;
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
+
 	ptlv = (struct spectral_phyerr_tlv_gen2 *)data;
 
 	if (spectral->is_160_format)
@@ -3448,17 +3494,20 @@ target_if_consume_spectral_report_gen3(
 		goto fail;
 	}
 
+	qdf_spin_lock_bh(&spectral->detector_list_lock);
 	det_list = &spectral->detector_list[spectral_mode]
 			[spectral->report_info[spectral_mode].sscan_bw];
 	for (det = 0; det < det_list->num_detectors; det++) {
 		if (p_sfft->fft_detector_id == det_list->detectors[det])
 			break;
 		if (det == det_list->num_detectors - 1) {
+			qdf_spin_unlock_bh(&spectral->detector_list_lock);
 			spectral_info("Incorrect det id %d for given scan mode and channel width",
 				      p_sfft->fft_detector_id);
 			goto fail_no_print;
 		}
 	}
+	qdf_spin_unlock_bh(&spectral->detector_list_lock);
 
 	ret = target_if_update_session_info_from_report_ctx(
 						spectral,
@@ -3470,6 +3519,7 @@ target_if_consume_spectral_report_gen3(
 		goto fail;
 	}
 
+	qdf_spin_lock_bh(&spectral->session_report_info_lock);
 	/* Check FFT report are in order for 160 MHz and 80p80 */
 	if (is_ch_width_160_or_80p80(
 	    spectral->report_info[spectral_mode].sscan_bw) &&
@@ -3477,9 +3527,13 @@ target_if_consume_spectral_report_gen3(
 		ret = target_if_160mhz_delivery_state_change(
 				spectral, spectral_mode,
 				p_sfft->fft_detector_id);
-		if (ret != QDF_STATUS_SUCCESS)
+		if (ret != QDF_STATUS_SUCCESS) {
+			qdf_spin_unlock_bh(
+					&spectral->session_report_info_lock);
 			goto fail;
+		}
 	}
+	qdf_spin_unlock_bh(&spectral->session_report_info_lock);
 
 	p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data;
 	if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4))