qcacld-3.0: Handle BEACON_REPORTING_DO_NOT_RESUME vendor attribute
Optionally set by userspace to request the driver not to resume beacon reporting after a pause is completed, when the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START. If this flag is set, the driver will not resume beacon reporting after beacon reporting pause is completed. Userspace has to send QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command again in order to initiate beacon reporting again. If this flag is set in the recent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command, then in the subsequent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE event (if any) the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be set by the driver. Change-Id: I371a218cb513dcb077b7df675c549818c2b657b2 CRs-Fixed: 2466480
This commit is contained in:
@@ -28,19 +28,19 @@ struct wireless_dev;
|
||||
struct wiphy;
|
||||
|
||||
/**
|
||||
* wlan_hdd_cfg80211_bcn_rcv_start() - Process bcn recv start ind
|
||||
* wlan_hdd_cfg80211_bcn_rcv_op() - Process beacon report operations
|
||||
* @wiphy: Pointer to wireless phy
|
||||
* @wdev: Pointer to wireless device
|
||||
* @data: Pointer to data
|
||||
* @data_len: Length of @data
|
||||
*
|
||||
* Wrapper function of __wlan_hdd_cfg80211_bcn_rcv_start()
|
||||
* Wrapper function of __wlan_hdd_cfg80211_bcn_rcv_op()
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure
|
||||
*/
|
||||
int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len);
|
||||
int wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len);
|
||||
|
||||
/**
|
||||
* hdd_beacon_recv_pause_indication()- Send vendor event to user space
|
||||
@@ -64,7 +64,7 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | \
|
||||
WIPHY_VENDOR_CMD_NEED_NETDEV | \
|
||||
WIPHY_VENDOR_CMD_NEED_RUNNING, \
|
||||
.doit = wlan_hdd_cfg80211_bcn_rcv_start \
|
||||
.doit = wlan_hdd_cfg80211_bcn_rcv_op\
|
||||
},
|
||||
|
||||
#define BCN_RECV_FEATURE_VENDOR_EVENTS \
|
||||
|
@@ -45,6 +45,8 @@ beacon_reporting_params[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1] = {
|
||||
[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING] = {.type =
|
||||
NLA_FLAG},
|
||||
[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD] = {.type = NLA_U8},
|
||||
[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME] = {.type =
|
||||
NLA_FLAG},
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -173,13 +175,15 @@ static void hdd_send_bcn_recv_info(hdd_handle_t hdd_handle,
|
||||
* @adapter: Pointer to network adapter
|
||||
* @active_report: Active reporting flag
|
||||
* @nth_value: Beacon report period
|
||||
* @do_not_resume: beacon reporting resume after a pause is completed
|
||||
*
|
||||
* This function process beacon reporting start operation.
|
||||
*/
|
||||
static int hdd_handle_beacon_reporting_start_op(struct hdd_context *hdd_ctx,
|
||||
struct hdd_adapter *adapter,
|
||||
bool active_report,
|
||||
uint32_t nth_value)
|
||||
uint32_t nth_value,
|
||||
bool do_not_resume)
|
||||
{
|
||||
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
|
||||
int errno;
|
||||
@@ -216,9 +220,15 @@ static int hdd_handle_beacon_reporting_start_op(struct hdd_context *hdd_ctx,
|
||||
}
|
||||
/* Handle beacon receive start indication */
|
||||
qdf_status = sme_handle_bcn_recv_start(hdd_ctx->mac_handle,
|
||||
adapter->vdev_id, nth_value);
|
||||
adapter->vdev_id, nth_value,
|
||||
do_not_resume);
|
||||
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
||||
hdd_err("bcn rcv start failed with status=%d", qdf_status);
|
||||
if (sme_register_bcn_report_pe_cb(hdd_ctx->mac_handle, NULL))
|
||||
hdd_err("bcn report cb deregistration failed");
|
||||
if (sme_register_bcn_recv_pause_ind_cb(hdd_ctx->mac_handle,
|
||||
NULL))
|
||||
hdd_err("bcn pause ind cb deregistration failed");
|
||||
errno = qdf_status_to_os_return(qdf_status);
|
||||
return errno;
|
||||
}
|
||||
@@ -274,7 +284,7 @@ static int hdd_handle_beacon_reporting_stop_op(struct hdd_context *hdd_ctx,
|
||||
}
|
||||
|
||||
/**
|
||||
* __wlan_hdd_cfg80211_bcn_rcv_start() - enable/disable beacon reporting
|
||||
* __wlan_hdd_cfg80211_bcn_rcv_op() - enable/disable beacon reporting
|
||||
* indication
|
||||
* @wiphy: Pointer to wireless phy
|
||||
* @wdev: Pointer to wireless device
|
||||
@@ -286,9 +296,9 @@ static int hdd_handle_beacon_reporting_stop_op(struct hdd_context *hdd_ctx,
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure
|
||||
*/
|
||||
static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
static int __wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
|
||||
struct net_device *dev = wdev->netdev;
|
||||
@@ -296,7 +306,7 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1];
|
||||
uint32_t bcn_report, nth_value = 1;
|
||||
int errno;
|
||||
bool active_report;
|
||||
bool active_report, do_not_resume;
|
||||
|
||||
hdd_enter_dev(dev);
|
||||
|
||||
@@ -319,8 +329,9 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX,
|
||||
data, data_len, beacon_reporting_params);
|
||||
if (errno) {
|
||||
hdd_err("Invalid ATTR");
|
||||
return -EINVAL;
|
||||
hdd_err("Failed to parse the beacon reporting params %d",
|
||||
errno);
|
||||
return errno;
|
||||
}
|
||||
|
||||
/* Parse and fetch OP Type */
|
||||
@@ -328,38 +339,56 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
hdd_err("attr beacon report OP type failed");
|
||||
return -EINVAL;
|
||||
}
|
||||
active_report =
|
||||
!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING];
|
||||
hdd_debug("attr active_report %d", active_report);
|
||||
|
||||
bcn_report =
|
||||
nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE]);
|
||||
hdd_debug("Bcn Report: OP type:%d", bcn_report);
|
||||
|
||||
if (tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD])
|
||||
nth_value =
|
||||
nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD]);
|
||||
hdd_debug("Beacon Report: Period: %d", nth_value);
|
||||
|
||||
switch (bcn_report) {
|
||||
case QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START:
|
||||
active_report =
|
||||
!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING];
|
||||
hdd_debug("attr active_report %d", active_report);
|
||||
|
||||
do_not_resume =
|
||||
!!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME];
|
||||
hdd_debug("Attr beacon report do not resume %d", do_not_resume);
|
||||
|
||||
if (tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD])
|
||||
nth_value =
|
||||
nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD]);
|
||||
hdd_debug("Beacon Report: Period: %d", nth_value);
|
||||
|
||||
if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
|
||||
adapter->vdev_id)) {
|
||||
hdd_debug("Start cmd already in progress");
|
||||
return errno;
|
||||
hdd_debug("Start cmd already in progress, issue the stop to FW, before new start");
|
||||
if (hdd_handle_beacon_reporting_stop_op(hdd_ctx,
|
||||
adapter)) {
|
||||
hdd_err("Failed to stop the beacon reporting before starting new start");
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
errno = hdd_handle_beacon_reporting_start_op(hdd_ctx,
|
||||
adapter,
|
||||
active_report,
|
||||
nth_value);
|
||||
nth_value,
|
||||
do_not_resume);
|
||||
if (errno) {
|
||||
hdd_err("Failed to start beacon reporting %d,", errno);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case QCA_WLAN_VENDOR_BEACON_REPORTING_OP_STOP:
|
||||
if (sme_is_beacon_report_started(hdd_ctx->mac_handle,
|
||||
adapter->vdev_id)) {
|
||||
errno = hdd_handle_beacon_reporting_stop_op(hdd_ctx,
|
||||
adapter);
|
||||
if (errno) {
|
||||
hdd_err("Failed to stop the beacon report, %d",
|
||||
errno);
|
||||
}
|
||||
} else {
|
||||
hdd_err_rl("BCN_RCV_STOP rej as no START CMD active");
|
||||
errno = -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -380,6 +409,7 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
uint32_t data_len;
|
||||
int flags;
|
||||
uint32_t abort_reason;
|
||||
bool do_not_resume;
|
||||
|
||||
if (wlan_hdd_validate_context(hdd_ctx))
|
||||
return;
|
||||
@@ -402,6 +432,10 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
return;
|
||||
}
|
||||
|
||||
do_not_resume =
|
||||
sme_is_beacon_reporting_do_not_resume(hdd_ctx->mac_handle,
|
||||
adapter->vdev_id);
|
||||
|
||||
if (is_disconnected) {
|
||||
abort_reason =
|
||||
QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_DISCONNECTED;
|
||||
@@ -411,8 +445,23 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
hdd_handle_beacon_reporting_stop_op(hdd_ctx,
|
||||
adapter);
|
||||
} else {
|
||||
/*
|
||||
* In case of scan, Check that auto resume of beacon reporting
|
||||
* is allowed or not.
|
||||
* If not allowed:
|
||||
* Deregister callbacks and Reset bcn recv start flag in order
|
||||
* to make sure host should not send beacon report to userspace
|
||||
* further.
|
||||
* If Auto resume allowed:
|
||||
* Send pause indication to userspace and continue sending
|
||||
* connected AP's beacon to userspace.
|
||||
*/
|
||||
if (do_not_resume)
|
||||
hdd_handle_beacon_reporting_stop_op(hdd_ctx,
|
||||
adapter);
|
||||
|
||||
switch (type) {
|
||||
case SCAN_EVENT_TYPE_STARTED:
|
||||
case SCAN_EVENT_TYPE_FOREIGN_CHANNEL:
|
||||
abort_reason =
|
||||
QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_SCAN_STARTED;
|
||||
break;
|
||||
@@ -437,8 +486,13 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
* Send auto resume flag to user space to specify the driver will
|
||||
* automatically resume reporting beacon events only in case of
|
||||
* pause indication due to scan started.
|
||||
* If do_not_resume flag is set in the recent
|
||||
* QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command, then in the
|
||||
* subsequent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE event (if any)
|
||||
* the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be
|
||||
* set by the driver.
|
||||
*/
|
||||
if (!is_disconnected)
|
||||
if (!is_disconnected || !do_not_resume)
|
||||
if (nla_put_flag(vendor_event,
|
||||
QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES)) {
|
||||
hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
|
||||
@@ -449,9 +503,9 @@ void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
cfg80211_vendor_event(vendor_event, flags);
|
||||
}
|
||||
|
||||
int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
int wlan_hdd_cfg80211_bcn_rcv_op(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
{
|
||||
int errno;
|
||||
struct osif_vdev_sync *vdev_sync;
|
||||
@@ -460,8 +514,8 @@ int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
if (errno)
|
||||
return errno;
|
||||
|
||||
errno = __wlan_hdd_cfg80211_bcn_rcv_start(wiphy, wdev,
|
||||
data, data_len);
|
||||
errno = __wlan_hdd_cfg80211_bcn_rcv_op(wiphy, wdev,
|
||||
data, data_len);
|
||||
|
||||
osif_vdev_sync_op_stop(vdev_sync);
|
||||
|
||||
|
@@ -567,6 +567,7 @@ struct csr_disconnect_stats {
|
||||
* struct csr_roam_session - CSR per-vdev context
|
||||
* @vdev_id: ID of the vdev for which this entry is applicable
|
||||
* @is_bcn_recv_start: Allow to process bcn recv indication
|
||||
* @beacon_report_do_not_resume: Do not resume the beacon reporting after scan
|
||||
*/
|
||||
struct csr_roam_session {
|
||||
union {
|
||||
@@ -642,6 +643,7 @@ struct csr_roam_session {
|
||||
qdf_mc_timer_t hTimerRoaming;
|
||||
#ifdef WLAN_BCN_RECV_FEATURE
|
||||
bool is_bcn_recv_start;
|
||||
bool beacon_report_do_not_resume;
|
||||
#endif
|
||||
/* the roamResult that is used when the roaming timer fires */
|
||||
eCsrRoamResult roamResult;
|
||||
|
@@ -1585,6 +1585,7 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle,
|
||||
* @mac_handle: Opaque handle to the global MAC context
|
||||
* @vdev_id: SME session id
|
||||
* @nth_value: Beacon report period
|
||||
* @do_not_resume: beacon reporting resume after a pause is completed
|
||||
*
|
||||
* This function remove beacon filter. It allow fw to send
|
||||
* all beacons from connected peer to driver.
|
||||
@@ -1593,7 +1594,8 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle,
|
||||
*/
|
||||
QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
|
||||
uint32_t vdev_id,
|
||||
uint32_t nth_value);
|
||||
uint32_t nth_value,
|
||||
bool do_not_resume);
|
||||
|
||||
/**
|
||||
* sme_is_beacon_report_started() - Check bcn recv started
|
||||
@@ -1607,6 +1609,18 @@ QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
|
||||
bool sme_is_beacon_report_started(mac_handle_t mac_handle,
|
||||
uint32_t session_id);
|
||||
|
||||
/**
|
||||
* sme_is_beacon_reporting_do_not_resume() - Check auto resume allowed or not
|
||||
* @mac_handle: Opaque handle to the global MAC context
|
||||
* @session_id: SME session id
|
||||
*
|
||||
* This function is to check auto resume of beacon reporting is allowed or not.
|
||||
*
|
||||
* Return: true on success
|
||||
*/
|
||||
bool sme_is_beacon_reporting_do_not_resume(mac_handle_t mac_handle,
|
||||
uint32_t session_id);
|
||||
|
||||
/**
|
||||
* stop_beacon_report() - To stop beacon report
|
||||
* @mac_handle: Opaque handle to the global MAC context
|
||||
@@ -1625,6 +1639,13 @@ bool sme_is_beacon_report_started(mac_handle_t mac_handle,
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool sme_is_beacon_reporting_do_not_resume(mac_handle_t mac_handle,
|
||||
uint32_t session_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
void sme_stop_beacon_report(mac_handle_t mac_handle,
|
||||
uint32_t session_id)
|
||||
|
@@ -12634,7 +12634,8 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle,
|
||||
|
||||
#ifdef WLAN_BCN_RECV_FEATURE
|
||||
QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
|
||||
uint32_t vdev_id, uint32_t nth_value)
|
||||
uint32_t vdev_id, uint32_t nth_value,
|
||||
bool do_not_resume)
|
||||
{
|
||||
struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
|
||||
struct csr_roam_session *session;
|
||||
@@ -12660,6 +12661,7 @@ QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
session->is_bcn_recv_start = true;
|
||||
session->beacon_report_do_not_resume = do_not_resume;
|
||||
sme_release_global_lock(&mac_ctx->sme);
|
||||
}
|
||||
|
||||
@@ -12676,6 +12678,7 @@ QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle,
|
||||
status = sme_acquire_global_lock(&mac_ctx->sme);
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
session->is_bcn_recv_start = false;
|
||||
session->beacon_report_do_not_resume = false;
|
||||
sme_release_global_lock(&mac_ctx->sme);
|
||||
}
|
||||
sme_err("WMI_VDEV_PARAM_NTH_BEACON_TO_HOST %d", ret);
|
||||
@@ -12692,16 +12695,12 @@ void sme_stop_beacon_report(mac_handle_t mac_handle, uint32_t session_id)
|
||||
QDF_STATUS status;
|
||||
int ret;
|
||||
|
||||
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
|
||||
sme_err("CSR session not valid: %d", session_id);
|
||||
return;
|
||||
}
|
||||
|
||||
session = CSR_GET_SESSION(mac_ctx, session_id);
|
||||
if (!session) {
|
||||
sme_err("vdev_id %d not found", session_id);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = sme_cli_set_command(session_id,
|
||||
WMI_VDEV_PARAM_NTH_BEACON_TO_HOST, 0,
|
||||
VDEV_CMD);
|
||||
@@ -12710,6 +12709,7 @@ void sme_stop_beacon_report(mac_handle_t mac_handle, uint32_t session_id)
|
||||
status = sme_acquire_global_lock(&mac_ctx->sme);
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
session->is_bcn_recv_start = false;
|
||||
session->beacon_report_do_not_resume = false;
|
||||
sme_release_global_lock(&mac_ctx->sme);
|
||||
}
|
||||
}
|
||||
@@ -12719,18 +12719,38 @@ bool sme_is_beacon_report_started(mac_handle_t mac_handle, uint32_t session_id)
|
||||
struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
|
||||
struct csr_roam_session *session;
|
||||
|
||||
session = CSR_GET_SESSION(mac_ctx, session_id);
|
||||
if (!session) {
|
||||
sme_err("vdev_id %d not found", session_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
|
||||
sme_err("CSR session not valid: %d", session_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return session->is_bcn_recv_start;
|
||||
}
|
||||
|
||||
bool sme_is_beacon_reporting_do_not_resume(mac_handle_t mac_handle,
|
||||
uint32_t session_id)
|
||||
{
|
||||
struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
|
||||
struct csr_roam_session *session;
|
||||
|
||||
session = CSR_GET_SESSION(mac_ctx, session_id);
|
||||
if (!session) {
|
||||
sme_err("vdev_id %d not found", session_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return session->is_bcn_recv_start;
|
||||
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
|
||||
sme_err("CSR session not valid: %d", session_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return session->beacon_report_do_not_resume;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Fai riferimento in un nuovo problema
Block a user