|
@@ -50,11 +50,13 @@
|
|
#include "../../core/src/wlan_cp_stats_defs.h"
|
|
#include "../../core/src/wlan_cp_stats_defs.h"
|
|
#include "cdp_txrx_host_stats.h"
|
|
#include "cdp_txrx_host_stats.h"
|
|
#include "utils_mlo.h"
|
|
#include "utils_mlo.h"
|
|
|
|
+#include "wlan_mlo_mgr_sta.h"
|
|
|
|
|
|
#define MAX_CTRL_STAT_VDEV_ENTRIES 1
|
|
#define MAX_CTRL_STAT_VDEV_ENTRIES 1
|
|
#define MAX_CTRL_STAT_MAC_ADDR_ENTRIES 1
|
|
#define MAX_CTRL_STAT_MAC_ADDR_ENTRIES 1
|
|
#define MAX_RMM_STA_STATS_REQUESTED 2
|
|
#define MAX_RMM_STA_STATS_REQUESTED 2
|
|
-#define MAX_MEAS_DURATION_FOR_STA_STATS 10
|
|
|
|
|
|
+#define MIN_MEAS_DURATION_FOR_STA_STATS 10
|
|
|
|
+
|
|
/* Max passive scan dwell for wide band rrm scan, in milliseconds */
|
|
/* Max passive scan dwell for wide band rrm scan, in milliseconds */
|
|
#define RRM_SCAN_MAX_DWELL_TIME 110
|
|
#define RRM_SCAN_MAX_DWELL_TIME 110
|
|
|
|
|
|
@@ -581,24 +583,28 @@ void rrm_get_country_code_from_connected_profile(struct mac_context *mac,
|
|
* @chan: channel number
|
|
* @chan: channel number
|
|
* @req_mode: Request mode
|
|
* @req_mode: Request mode
|
|
* @duration: The duration over which the Beacon report was measured
|
|
* @duration: The duration over which the Beacon report was measured
|
|
- * @vdev_id: vdev Id
|
|
|
|
|
|
+ * @pe_session: pe session pointer
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
|
|
wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
|
|
uint8_t op_class, uint8_t chan,
|
|
uint8_t op_class, uint8_t chan,
|
|
uint8_t req_mode, uint32_t duration,
|
|
uint8_t req_mode, uint32_t duration,
|
|
- uint8_t vdev_id)
|
|
|
|
|
|
+ struct pe_session *pe_session)
|
|
{
|
|
{
|
|
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt);
|
|
WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt);
|
|
|
|
|
|
qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
|
|
qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
|
|
|
|
|
|
- wlan_diag_event.diag_cmn.vdev_id = vdev_id;
|
|
|
|
|
|
+ wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(pe_session->vdev);
|
|
wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
|
|
wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
|
|
wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
|
|
wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
|
|
|
|
|
|
wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_REQ_EVENT;
|
|
wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_REQ_EVENT;
|
|
- wlan_diag_event.version = DIAG_BCN_RPT_VERSION;
|
|
|
|
|
|
+ wlan_diag_event.version = DIAG_BCN_RPT_VERSION_2;
|
|
|
|
+
|
|
|
|
+ if (mlo_is_mld_sta(pe_session->vdev))
|
|
|
|
+ wlan_diag_event.band =
|
|
|
|
+ wlan_convert_freq_to_diag_band(pe_session->curr_op_freq);
|
|
|
|
|
|
wlan_diag_event.meas_token = token;
|
|
wlan_diag_event.meas_token = token;
|
|
wlan_diag_event.mode = mode;
|
|
wlan_diag_event.mode = mode;
|
|
@@ -614,7 +620,7 @@ static void
|
|
wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
|
|
wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
|
|
uint8_t op_class, uint8_t chan,
|
|
uint8_t op_class, uint8_t chan,
|
|
uint8_t req_mode, uint32_t duration,
|
|
uint8_t req_mode, uint32_t duration,
|
|
- uint8_t vdev_id)
|
|
|
|
|
|
+ struct pe_session *pe_session)
|
|
{
|
|
{
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -889,6 +895,48 @@ get_stats_fail:
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+/* -------------------------------------------------------------------- */
|
|
|
|
+/**
|
|
|
|
+ * rrm_get_max_meas_duration() - calculate max measurement duration for a
|
|
|
|
+ * rrm req
|
|
|
|
+ * @mac: global mac context
|
|
|
|
+ * @pe_session: per vdev pe context
|
|
|
|
+ *
|
|
|
|
+ * Return: max measurement duration
|
|
|
|
+ */
|
|
|
|
+static uint16_t rrm_get_max_meas_duration(struct mac_context *mac,
|
|
|
|
+ struct pe_session *pe_session)
|
|
|
|
+{
|
|
|
|
+ int8_t max_dur;
|
|
|
|
+ uint16_t max_meas_dur, sign;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * The logic here is to check the measurement duration passed in the
|
|
|
|
+ * beacon request. Following are the cases handled.
|
|
|
|
+ * Case 1: If measurement duration received in the beacon request is
|
|
|
|
+ * greater than the max measurement duration advertised in the RRM
|
|
|
|
+ * capabilities(Assoc Req), and Duration Mandatory bit is set to 1,
|
|
|
|
+ * REFUSE the beacon request.
|
|
|
|
+ * Case 2: If measurement duration received in the beacon request is
|
|
|
|
+ * greater than the max measurement duration advertised in the RRM
|
|
|
|
+ * capabilities(Assoc Req), and Duration Mandatory bit is set to 0,
|
|
|
|
+ * perform measurement for the duration advertised in the
|
|
|
|
+ * RRM capabilities
|
|
|
|
+ * maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
|
|
|
|
+ */
|
|
|
|
+ max_dur = mac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
|
|
|
|
+ sign = (max_dur < 0) ? 1 : 0;
|
|
|
|
+ max_dur = (1L << ABS(max_dur));
|
|
|
|
+ if (!sign)
|
|
|
|
+ max_meas_dur =
|
|
|
|
+ max_dur * pe_session->beaconParams.beaconInterval;
|
|
|
|
+ else
|
|
|
|
+ max_meas_dur =
|
|
|
|
+ pe_session->beaconParams.beaconInterval / max_dur;
|
|
|
|
+
|
|
|
|
+ return max_meas_dur;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* rrm_process_sta_stats_report_req: Process RRM sta stats request
|
|
* rrm_process_sta_stats_report_req: Process RRM sta stats request
|
|
* @mac: mac context
|
|
* @mac: mac context
|
|
@@ -905,16 +953,31 @@ rrm_process_sta_stats_report_req(struct mac_context *mac,
|
|
struct pe_session *pe_session)
|
|
struct pe_session *pe_session)
|
|
{
|
|
{
|
|
QDF_STATUS status;
|
|
QDF_STATUS status;
|
|
- uint8_t meas_duration = 1;
|
|
|
|
|
|
+ uint16_t meas_duration = MIN_MEAS_DURATION_FOR_STA_STATS;
|
|
|
|
+ uint8_t max_meas_duration;
|
|
struct rrm_sta_stats *rrm_sta_statistics;
|
|
struct rrm_sta_stats *rrm_sta_statistics;
|
|
|
|
|
|
|
|
+ max_meas_duration = rrm_get_max_meas_duration(mac, pe_session);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Keep timer value atleast of 10 ms even if measurement duration
|
|
|
|
+ * provided in meas request is < 10 ms because FW takes some time to
|
|
|
|
+ * calculate and respond stats.
|
|
|
|
+ * Start timer of 10 ms even if meas duration is 0.
|
|
|
|
+ * To get stats from FW.
|
|
|
|
+ */
|
|
if (sta_stats_req->measurement_request.sta_stats.meas_duration >
|
|
if (sta_stats_req->measurement_request.sta_stats.meas_duration >
|
|
- MAX_MEAS_DURATION_FOR_STA_STATS) {
|
|
|
|
- pe_err("Dropping req measurement duration > threshold %d",
|
|
|
|
- sta_stats_req->measurement_request.sta_stats.meas_duration);
|
|
|
|
- return eRRM_INCAPABLE;
|
|
|
|
- }
|
|
|
|
|
|
+ MIN_MEAS_DURATION_FOR_STA_STATS)
|
|
|
|
+ meas_duration =
|
|
|
|
+ sta_stats_req->measurement_request.sta_stats.meas_duration;
|
|
|
|
|
|
|
|
+ if (meas_duration > max_meas_duration) {
|
|
|
|
+ if (sta_stats_req->durationMandatory) {
|
|
|
|
+ pe_nofl_err("Dropping the req: duration mandatory & max duration > meas duration");
|
|
|
|
+ return eRRM_REFUSED;
|
|
|
|
+ }
|
|
|
|
+ meas_duration = max_meas_duration;
|
|
|
|
+ }
|
|
if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)
|
|
if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)
|
|
sta_stats_req->measurement_request.sta_stats.peer_mac_addr)) {
|
|
sta_stats_req->measurement_request.sta_stats.peer_mac_addr)) {
|
|
pe_err("Dropping req: broadcast address not supported");
|
|
pe_err("Dropping req: broadcast address not supported");
|
|
@@ -922,9 +985,6 @@ rrm_process_sta_stats_report_req(struct mac_context *mac,
|
|
}
|
|
}
|
|
|
|
|
|
rrm_sta_statistics = &mac->rrm.rrmPEContext.rrm_sta_stats;
|
|
rrm_sta_statistics = &mac->rrm.rrmPEContext.rrm_sta_stats;
|
|
- if (sta_stats_req->measurement_request.sta_stats.meas_duration)
|
|
|
|
- meas_duration =
|
|
|
|
- sta_stats_req->measurement_request.sta_stats.meas_duration;
|
|
|
|
|
|
|
|
rrm_sta_statistics->rrm_report.token = pCurrentReq->token;
|
|
rrm_sta_statistics->rrm_report.token = pCurrentReq->token;
|
|
rrm_sta_statistics->rrm_report.type = pCurrentReq->type;
|
|
rrm_sta_statistics->rrm_report.type = pCurrentReq->type;
|
|
@@ -946,12 +1006,8 @@ rrm_process_sta_stats_report_req(struct mac_context *mac,
|
|
return eRRM_REFUSED;
|
|
return eRRM_REFUSED;
|
|
mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId =
|
|
mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId =
|
|
pe_session->peSessionId;
|
|
pe_session->peSessionId;
|
|
- /*
|
|
|
|
- * Start timer of 1 sec even if meas duration is 0.
|
|
|
|
- * To get stats from FW.
|
|
|
|
- */
|
|
|
|
tx_timer_change(&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
|
|
tx_timer_change(&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
|
|
- SYS_MS_TO_TICKS(meas_duration * 1000), 0);
|
|
|
|
|
|
+ SYS_MS_TO_TICKS(meas_duration), 0);
|
|
/* Activate sta stats resp timer */
|
|
/* Activate sta stats resp timer */
|
|
if (tx_timer_activate(
|
|
if (tx_timer_activate(
|
|
&mac->lim.lim_timers.rrm_sta_stats_resp_timer) !=
|
|
&mac->lim.lim_timers.rrm_sta_stats_resp_timer) !=
|
|
@@ -1120,48 +1176,6 @@ failure:
|
|
return QDF_STATUS_E_FAILURE;
|
|
return QDF_STATUS_E_FAILURE;
|
|
}
|
|
}
|
|
|
|
|
|
-/* -------------------------------------------------------------------- */
|
|
|
|
-/**
|
|
|
|
- * rrm_get_max_meas_duration() - calculate max measurement duration for a
|
|
|
|
- * rrm req
|
|
|
|
- * @mac: global mac context
|
|
|
|
- * @pe_session: per vdev pe context
|
|
|
|
- *
|
|
|
|
- * Return: max measurement duration
|
|
|
|
- */
|
|
|
|
-static uint16_t rrm_get_max_meas_duration(struct mac_context *mac,
|
|
|
|
- struct pe_session *pe_session)
|
|
|
|
-{
|
|
|
|
- int8_t max_dur;
|
|
|
|
- uint16_t max_meas_dur, sign;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * The logic here is to check the measurement duration passed in the
|
|
|
|
- * beacon request. Following are the cases handled.
|
|
|
|
- * Case 1: If measurement duration received in the beacon request is
|
|
|
|
- * greater than the max measurement duration advertised in the RRM
|
|
|
|
- * capabilities(Assoc Req), and Duration Mandatory bit is set to 1,
|
|
|
|
- * REFUSE the beacon request.
|
|
|
|
- * Case 2: If measurement duration received in the beacon request is
|
|
|
|
- * greater than the max measurement duration advertised in the RRM
|
|
|
|
- * capabilities(Assoc Req), and Duration Mandatory bit is set to 0,
|
|
|
|
- * perform measurement for the duration advertised in the
|
|
|
|
- * RRM capabilities
|
|
|
|
- * maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
|
|
|
|
- */
|
|
|
|
- max_dur = mac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
|
|
|
|
- sign = (max_dur < 0) ? 1 : 0;
|
|
|
|
- max_dur = (1L << ABS(max_dur));
|
|
|
|
- if (!sign)
|
|
|
|
- max_meas_dur =
|
|
|
|
- max_dur * pe_session->beaconParams.beaconInterval;
|
|
|
|
- else
|
|
|
|
- max_meas_dur =
|
|
|
|
- pe_session->beaconParams.beaconInterval / max_dur;
|
|
|
|
-
|
|
|
|
- return max_meas_dur;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* rrm_process_beacon_report_req
|
|
* rrm_process_beacon_report_req
|
|
*
|
|
*
|
|
@@ -1241,7 +1255,7 @@ rrm_process_beacon_report_req(struct mac_context *mac,
|
|
pBeaconReq->measurement_request.Beacon.meas_mode,
|
|
pBeaconReq->measurement_request.Beacon.meas_mode,
|
|
pBeaconReq->measurement_request.Beacon.regClass,
|
|
pBeaconReq->measurement_request.Beacon.regClass,
|
|
pBeaconReq->measurement_request.Beacon.channel,
|
|
pBeaconReq->measurement_request.Beacon.channel,
|
|
- req_mode, measDuration, wlan_vdev_get_id(pe_session->vdev));
|
|
|
|
|
|
+ req_mode, measDuration, pe_session);
|
|
|
|
|
|
if (measDuration == 0 &&
|
|
if (measDuration == 0 &&
|
|
pBeaconReq->measurement_request.Beacon.meas_mode !=
|
|
pBeaconReq->measurement_request.Beacon.meas_mode !=
|
|
@@ -1254,8 +1268,8 @@ rrm_process_beacon_report_req(struct mac_context *mac,
|
|
if (pBeaconReq->durationMandatory) {
|
|
if (pBeaconReq->durationMandatory) {
|
|
pe_nofl_err("RX: [802.11 BCN_RPT] Dropping the req: duration mandatory & maxduration > measduration");
|
|
pe_nofl_err("RX: [802.11 BCN_RPT] Dropping the req: duration mandatory & maxduration > measduration");
|
|
return eRRM_REFUSED;
|
|
return eRRM_REFUSED;
|
|
- } else
|
|
|
|
- measDuration = maxMeasduration;
|
|
|
|
|
|
+ }
|
|
|
|
+ measDuration = maxMeasduration;
|
|
}
|
|
}
|
|
|
|
|
|
pe_debug("measurement duration %d", measDuration);
|
|
pe_debug("measurement duration %d", measDuration);
|
|
@@ -2044,6 +2058,9 @@ rrm_process_channel_load_req(struct mac_context *mac,
|
|
uint8_t op_class, channel, reporting_condition;
|
|
uint8_t op_class, channel, reporting_condition;
|
|
uint16_t randomization_intv, meas_duration, max_meas_duration;
|
|
uint16_t randomization_intv, meas_duration, max_meas_duration;
|
|
bool present;
|
|
bool present;
|
|
|
|
+ uint8_t country[WNI_CFG_COUNTRY_CODE_LEN];
|
|
|
|
+ qdf_freq_t chan_freq;
|
|
|
|
+ bool is_freq_enabled;
|
|
|
|
|
|
present = chan_load_req->measurement_request.channel_load.rrm_reporting.present;
|
|
present = chan_load_req->measurement_request.channel_load.rrm_reporting.present;
|
|
reporting_condition = chan_load_req->measurement_request.channel_load.rrm_reporting.reporting_condition;
|
|
reporting_condition = chan_load_req->measurement_request.channel_load.rrm_reporting.reporting_condition;
|
|
@@ -2063,11 +2080,11 @@ rrm_process_channel_load_req(struct mac_context *mac,
|
|
if (chan_load_req->durationMandatory) {
|
|
if (chan_load_req->durationMandatory) {
|
|
pe_nofl_err("RX:[802.11 CH_LOAD] Dropping the req: duration mandatory & max duration > meas duration");
|
|
pe_nofl_err("RX:[802.11 CH_LOAD] Dropping the req: duration mandatory & max duration > meas duration");
|
|
return eRRM_REFUSED;
|
|
return eRRM_REFUSED;
|
|
- } else {
|
|
|
|
- meas_duration = max_meas_duration;
|
|
|
|
}
|
|
}
|
|
|
|
+ meas_duration = max_meas_duration;
|
|
}
|
|
}
|
|
- pe_debug("RX:[802.11 CH_LOAD] seq:%d Token:%d op_c:%d ch:%d meas_dur:%d, rand intv: %d, max_dur:%d",
|
|
|
|
|
|
+ pe_debug("RX:[802.11 CH_LOAD] vdev :%d, seq:%d Token:%d op_c:%d ch:%d meas_dur:%d, rand intv: %d, max_dur:%d",
|
|
|
|
+ pe_session->vdev_id,
|
|
mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
|
|
mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
|
|
chan_load_req->measurement_token, op_class,
|
|
chan_load_req->measurement_token, op_class,
|
|
channel, meas_duration, randomization_intv,
|
|
channel, meas_duration, randomization_intv,
|
|
@@ -2075,6 +2092,33 @@ rrm_process_channel_load_req(struct mac_context *mac,
|
|
if (!meas_duration || meas_duration > RRM_SCAN_MAX_DWELL_TIME)
|
|
if (!meas_duration || meas_duration > RRM_SCAN_MAX_DWELL_TIME)
|
|
return eRRM_REFUSED;
|
|
return eRRM_REFUSED;
|
|
|
|
|
|
|
|
+ if (!wlan_reg_is_6ghz_supported(mac->psoc) &&
|
|
|
|
+ (wlan_reg_is_6ghz_op_class(mac->pdev, op_class))) {
|
|
|
|
+ pe_debug("RX: [802.11 CH_LOAD] Ch belongs to 6 ghz spectrum, abort");
|
|
|
|
+ return eRRM_INCAPABLE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rrm_get_country_code_from_connected_profile(mac, pe_session->vdev_id,
|
|
|
|
+ country);
|
|
|
|
+ chan_freq = wlan_reg_country_chan_opclass_to_freq(mac->pdev,
|
|
|
|
+ country, channel,
|
|
|
|
+ op_class, false);
|
|
|
|
+ if (!chan_freq) {
|
|
|
|
+ pe_debug("Invalid ch freq for country code %c%c 0x%x",
|
|
|
|
+ country[0], country[1], country[2]);
|
|
|
|
+ return eRRM_INCAPABLE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pe_debug("freq:%d, country code %c%c 0x%x", chan_freq, country[0],
|
|
|
|
+ country[1], country[2]);
|
|
|
|
+
|
|
|
|
+ is_freq_enabled = wlan_reg_is_freq_enabled(mac->pdev, chan_freq,
|
|
|
|
+ REG_CURRENT_PWR_MODE);
|
|
|
|
+ if (!is_freq_enabled) {
|
|
|
|
+ pe_debug("No channels populated with requested operation class and current country, Hence abort the rrm operation");
|
|
|
|
+ return eRRM_INCAPABLE;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Prepare the request to send to SME. */
|
|
/* Prepare the request to send to SME. */
|
|
load_ind = qdf_mem_malloc(sizeof(struct ch_load_ind));
|
|
load_ind = qdf_mem_malloc(sizeof(struct ch_load_ind));
|
|
if (!load_ind)
|
|
if (!load_ind)
|
|
@@ -2582,6 +2626,8 @@ QDF_STATUS rrm_initialize(struct mac_context *mac)
|
|
pRRMCaps->APChanReport = 1;
|
|
pRRMCaps->APChanReport = 1;
|
|
pRRMCaps->fine_time_meas_rpt = 1;
|
|
pRRMCaps->fine_time_meas_rpt = 1;
|
|
pRRMCaps->lci_capability = 1;
|
|
pRRMCaps->lci_capability = 1;
|
|
|
|
+ pRRMCaps->ChannelLoad = 1;
|
|
|
|
+ pRRMCaps->statistics = 1;
|
|
|
|
|
|
pRRMCaps->operatingChanMax = 3;
|
|
pRRMCaps->operatingChanMax = 3;
|
|
pRRMCaps->nonOperatingChanMax = 3;
|
|
pRRMCaps->nonOperatingChanMax = 3;
|