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:
Abhinav Kumar
2019-06-05 19:02:14 +05:30
committed by nshrivas
orang tua 8475bc3f61
melakukan e85ae55537
5 mengubah file dengan 139 tambahan dan 42 penghapusan

Melihat File

@@ -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 \

Melihat File

@@ -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);

Melihat File

@@ -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;

Melihat File

@@ -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)

Melihat File

@@ -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