qcacld-3.0: Send scan start indication to userspace
If firmware starts off-channel scan, driver does not receive beacons. In this case driver should send a pause event to userspace. Change-Id: I90ba5c586656486df110778b73b236e5877f8684 CRs-Fixed: 2431359
This commit is contained in:
parent
4d1f9f442d
commit
0ed614c1c9
@ -76,6 +76,92 @@ int get_beacon_report_data_len(struct wlan_beacon_report *report)
|
||||
return data_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_pause_ind_data_len() - Calculate skb buffer length
|
||||
* @report: Required beacon report
|
||||
*
|
||||
* Calculate length for pause indication to allocate skb buffer
|
||||
*
|
||||
* Return: skb buffer length
|
||||
*/
|
||||
static int get_pause_ind_data_len(void)
|
||||
{
|
||||
uint32_t data_len = NLMSG_HDRLEN;
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE */
|
||||
data_len += nla_total_size(sizeof(u32));
|
||||
|
||||
/* QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON */
|
||||
data_len += nla_total_size(sizeof(u32));
|
||||
|
||||
return data_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_beacon_recv_pause_indication()- Send vendor event to user space
|
||||
* to inform SCAN started indication
|
||||
* @hdd_handle: hdd handler
|
||||
* @vdev_id: vdev id
|
||||
* @type: scan event type
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_beacon_recv_pause_indication(hdd_handle_t hdd_handle,
|
||||
uint8_t vdev_id,
|
||||
enum scan_event_type type)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
|
||||
struct hdd_adapter *adapter;
|
||||
struct sk_buff *vendor_event;
|
||||
uint32_t data_len;
|
||||
int flags;
|
||||
uint32_t abort_reason;
|
||||
|
||||
if (wlan_hdd_validate_context(hdd_ctx))
|
||||
return;
|
||||
|
||||
adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
|
||||
if (hdd_validate_adapter(adapter))
|
||||
return;
|
||||
|
||||
data_len = get_pause_ind_data_len();
|
||||
flags = cds_get_gfp_flags();
|
||||
|
||||
vendor_event =
|
||||
cfg80211_vendor_event_alloc(
|
||||
hdd_ctx->wiphy, NULL,
|
||||
data_len,
|
||||
QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING_INDEX,
|
||||
flags);
|
||||
if (!vendor_event) {
|
||||
hdd_err("cfg80211_vendor_event_alloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SCAN_EVENT_TYPE_STARTED:
|
||||
abort_reason =
|
||||
QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_SCAN_STARTED;
|
||||
break;
|
||||
default:
|
||||
abort_reason =
|
||||
QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_UNSPECIFIED;
|
||||
}
|
||||
/* Send vendor event to user space to inform ABORT */
|
||||
if (nla_put_u32(vendor_event,
|
||||
QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE,
|
||||
QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE) ||
|
||||
nla_put_u32(vendor_event,
|
||||
QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON,
|
||||
abort_reason)) {
|
||||
hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
|
||||
kfree_skb(vendor_event);
|
||||
return;
|
||||
}
|
||||
|
||||
cfg80211_vendor_event(vendor_event, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_send_bcn_recv_info() - Send beacon info to userspace for
|
||||
* connected AP
|
||||
@ -211,6 +297,16 @@ static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy,
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
qdf_status =
|
||||
sme_register_bcn_recv_pause_ind_cb(hdd_ctx->mac_handle,
|
||||
hdd_beacon_recv_pause_indication);
|
||||
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
||||
hdd_err("bcn_recv_abort_ind cb reg failed = %d",
|
||||
qdf_status);
|
||||
errno = qdf_status_to_os_return(qdf_status);
|
||||
return errno;
|
||||
}
|
||||
|
||||
qdf_status =
|
||||
sme_handle_bcn_recv_start(hdd_ctx->mac_handle,
|
||||
adapter->vdev_id);
|
||||
|
@ -3455,4 +3455,27 @@ sme_get_mws_coex_info(mac_handle_t mac_handle, uint32_t vdev_id,
|
||||
void *context);
|
||||
#endif /* WLAN_MWS_INFO_DEBUGFS */
|
||||
|
||||
#ifdef WLAN_BCN_RECV_FEATURE
|
||||
/**
|
||||
* sme_register_bcn_recv_pause_ind_cb() - Register pause ind cb
|
||||
* mac_handle: man handler
|
||||
* cb: callback function to HDD
|
||||
*
|
||||
* This function register HDD callback in order to indicate beacon
|
||||
* receive pause indication to userspace.
|
||||
*
|
||||
* return QDF_STATUS of cb registration
|
||||
*/
|
||||
QDF_STATUS sme_register_bcn_recv_pause_ind_cb(mac_handle_t mac_handle,
|
||||
beacon_pause_cb cb);
|
||||
|
||||
#else
|
||||
static inline
|
||||
QDF_STATUS sme_register_bcn_recv_pause_ind_cb(mac_handle_t mac_handle,
|
||||
beacon_pause_cb cb)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if !defined( __SME_API_H ) */
|
||||
|
@ -265,6 +265,16 @@ typedef void (*hidden_ssid_cb)(hdd_handle_t hdd_handle,
|
||||
typedef void (*beacon_report_cb)(hdd_handle_t hdd_handle,
|
||||
struct wlan_beacon_report *beacon_report);
|
||||
|
||||
/**
|
||||
* beacon_pause_cb : scan start callback fun
|
||||
* @hdd_handler: HDD handler
|
||||
* @vdev_id: vdev id
|
||||
* @type: scan event type
|
||||
*/
|
||||
typedef void (*beacon_pause_cb)(hdd_handle_t hdd_handle,
|
||||
uint8_t vdev_id,
|
||||
enum scan_event_type type);
|
||||
|
||||
#ifdef WLAN_FEATURE_MOTION_DETECTION
|
||||
typedef QDF_STATUS (*md_host_evt_cb)(void *hdd_ctx, struct sir_md_evt *event);
|
||||
#endif /* WLAN_FEATURE_MOTION_DETECTION */
|
||||
@ -374,6 +384,7 @@ struct sme_context {
|
||||
|
||||
#ifdef WLAN_BCN_RECV_FEATURE
|
||||
beacon_report_cb beacon_report_cb;
|
||||
beacon_pause_cb beacon_pause_cb;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -15526,3 +15526,67 @@ sme_get_mws_coex_info(mac_handle_t mac_handle, uint32_t vdev_id,
|
||||
return status;
|
||||
}
|
||||
#endif /* WLAN_MWS_INFO_DEBUGFS */
|
||||
|
||||
#ifdef WLAN_BCN_RECV_FEATURE
|
||||
/**
|
||||
* sme_scan_event_handler() - Scan complete event handler
|
||||
* @vdev: vdev obj manager
|
||||
* @event: scan event
|
||||
* @arg: arg of scan event
|
||||
*
|
||||
* This function is getting called after Host receive scan start
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void sme_scan_event_handler(struct wlan_objmgr_vdev *vdev,
|
||||
struct scan_event *event,
|
||||
void *arg)
|
||||
{
|
||||
struct mac_context *mac = arg;
|
||||
struct csr_roam_session *session;
|
||||
|
||||
if (!mac) {
|
||||
sme_err("Invalid mac context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CSR_IS_SESSION_VALID(mac, vdev->vdev_objmgr.vdev_id)) {
|
||||
sme_err("Invalid vdev_id: %d", vdev->vdev_objmgr.vdev_id);
|
||||
return;
|
||||
}
|
||||
|
||||
session = CSR_GET_SESSION(mac, vdev->vdev_objmgr.vdev_id);
|
||||
|
||||
if (event->type == SCAN_EVENT_TYPE_STARTED) {
|
||||
if (mac->sme.beacon_pause_cb)
|
||||
mac->sme.beacon_pause_cb(mac->hdd_handle,
|
||||
vdev->vdev_objmgr.vdev_id, event->type);
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS sme_register_bcn_recv_pause_ind_cb(mac_handle_t mac_handle,
|
||||
beacon_pause_cb cb)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct mac_context *mac = MAC_CONTEXT(mac_handle);
|
||||
|
||||
if (!mac) {
|
||||
sme_err("Invalid mac context");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
status = sme_acquire_global_lock(&mac->sme);
|
||||
if (QDF_IS_STATUS_SUCCESS(status)) {
|
||||
mac->sme.beacon_pause_cb = cb;
|
||||
sme_release_global_lock(&mac->sme);
|
||||
}
|
||||
|
||||
/* scan event registration */
|
||||
status = ucfg_scan_register_event_handler(mac->pdev,
|
||||
sme_scan_event_handler, mac);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
sme_err("scan event register failed ");
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user