qcacmn: Add poisoning support for Spectral DDMA buffers

All gen III chipsets use DDMA method to copy the spectral reports to
the Host. It is possible that the buffers can be improper/incompletely
DMAed, which leads to wrong values being present in the Spectral report.
To detect improper DMA, the DBR framework has the support to poison the
buffers before handing them over to the target. This framework expects
the buffer owner modules to check for poison values in key fields.
So, validate the Spectral reports and assert the target upon failure.

Change-Id: I519bf8abd87cfc9758fe7d126a195f39656d8ecc
CRs-Fixed: 2478592
This commit is contained in:
Shwetha G K
2019-07-23 19:19:41 +05:30
committed by nshrivas
parent 29121213c8
commit 0c000df15e
2 changed files with 80 additions and 1 deletions

View File

@@ -109,6 +109,8 @@
/* Mask for time stamp from descriptor */
#define SPECTRAL_TSMASK 0xFFFFFFFF
#define SPECTRAL_SIGNATURE 0xdeadbeef
/* Signature to write onto spectral buffer and then later validate */
#define MEM_POISON_SIGNATURE (htobe32(0xdeadbeef))
/* START of spectral GEN II HW specific details */
#define SPECTRAL_PHYERR_SIGNATURE_GEN2 0xbb
@@ -833,6 +835,8 @@ struct spectral_param_properties {
* report a bin count of 0 to higher layers.
* @last_fft_timestamp: last fft report timestamp
* @timestamp_war_offset: Offset to be added to correct timestamp
* @dbr_ring_debug: Whether Spectral DBR ring debug is enabled
* @dbr_buff_debug: Whether Spectral DBR buffer debug is enabled
*/
struct target_if_spectral {
struct wlan_objmgr_pdev *pdev_obj;
@@ -947,6 +951,8 @@ struct target_if_spectral {
uint32_t timestamp_war_offset[SPECTRAL_SCAN_MODE_MAX];
uint16_t fft_size_min;
uint16_t fft_size_max;
bool dbr_ring_debug;
bool dbr_buff_debug;
};
/**

View File

@@ -1540,6 +1540,78 @@ target_if_get_spectral_mode(enum spectral_detector_id detector_id,
return QDF_STATUS_SUCCESS;
}
#ifdef DIRECT_BUF_RX_DEBUG
static void target_if_spectral_check_buffer_poisoning(
struct target_if_spectral *spectral,
struct spectral_report *report,
int num_fft_bins, enum spectral_scan_mode smode)
{
uint32_t *data;
size_t len;
size_t words_to_check =
sizeof(struct spectral_sscan_summary_report_gen3) >> 2;
bool poisoned_words_found = false;
if (!spectral) {
spectral_err_rl("Spectral LMAC object is null");
return;
}
if (!spectral->dbr_buff_debug)
return;
if (!report) {
spectral_err_rl("Spectral report is null");
return;
}
/* Add search FFT report */
if (spectral->params[smode].ss_rpt_mode > 0)
words_to_check +=
sizeof(struct spectral_phyerr_fft_report_gen3) >> 2;
/* Now add the number of FFT bins */
if (spectral->params[smode].ss_rpt_mode > 1) {
/* Caller should take care to pass correct number of FFT bins */
if (spectral->fftbin_size_war ==
SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE)
words_to_check += num_fft_bins;
else if (spectral->fftbin_size_war ==
SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE)
words_to_check += (num_fft_bins >> 1);
}
data = (uint32_t *)report->data;
for (len = 0; len < words_to_check; ++len) {
if (*data == MEM_POISON_SIGNATURE) {
spectral_err("Pattern(%x) found in Spectral search FFT report at position %zu in the buffer %pK",
MEM_POISON_SIGNATURE,
(len << 2), report->data);
poisoned_words_found = true;
break;
}
++data;
}
/* Crash the FW even if one word is poisoned */
if (poisoned_words_found) {
spectral_err("Pattern(%x) found in Spectral report, Hex dump of the sfft follows",
MEM_POISON_SIGNATURE);
target_if_spectral_hexdump((unsigned char *)report->data,
words_to_check << 2);
spectral_err("Asserting the FW");
target_if_spectral_fw_hang(spectral);
}
}
#else
static void target_if_spectral_check_buffer_poisoning(
struct target_if_spectral *spectral,
struct spectral_report *report,
int num_fft_bins, enum spectral_scan_mode smode)
{
}
#endif
int
target_if_consume_spectral_report_gen3(
struct target_if_spectral *spectral,
@@ -1905,6 +1977,8 @@ target_if_consume_spectral_report_gen3(
goto fail;
}
target_if_spectral_check_buffer_poisoning(spectral, report,
fft_bin_len, params.smode);
qdf_mem_copy(&params.classifier_params,
&spectral->classifier_params,
sizeof(struct spectral_classifier_params));
@@ -1913,7 +1987,6 @@ target_if_consume_spectral_report_gen3(
target_if_spectral_create_samp_msg(spectral, &params);
return 0;
fail:
spectral_err_rl("Error while processing Spectral report");
reset_160mhz_delivery_state_machine(spectral,