summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Girigowda <sgirigow@qca.qualcomm.com>2015-08-28 17:07:20 -0700
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2015-09-02 11:16:37 +0530
commit8877d034d716fdf8c4f1dfdb9642f2d724f6c1fe (patch)
treef006c6953170cb5a44309da70c1b4d7726507f37
parentf46dcd99c481a9fc88a64fd268a08dea070c7b20 (diff)
qcacld-2.0: Process WOW wake up event in the tasklet context
Currently WOW wake up event is processed in work thread which may be delayed to schedule. Directly complete the event in tasklet in order to proceed it in time. Also make sure the WOW wake up event handler is in atomic context. Change-Id: Ie6015d39321c7759b35f05acc7833ef8974c0157 CRs-Fixed: 900629
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c121
-rw-r--r--CORE/SERVICES/WMI/wmi_unified.c3
-rw-r--r--CORE/VOSS/src/vos_sched.c16
-rw-r--r--CORE/VOSS/src/vos_sched.h1
4 files changed, 117 insertions, 24 deletions
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 7ab30beb1a56..21edc7fb17d0 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -9571,6 +9571,8 @@ wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
*
* This function reads the rssi breached event %data and fill in the skb with
* NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
*
* Return: none
*/
@@ -9579,6 +9581,7 @@ void hdd_rssi_threshold_breached(void *hddctx,
{
hdd_context_t *hdd_ctx = hddctx;
struct sk_buff *skb;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -9592,7 +9595,7 @@ void hdd_rssi_threshold_breached(void *hddctx,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
- GFP_KERNEL);
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -9614,7 +9617,7 @@ void hdd_rssi_threshold_breached(void *hddctx,
goto fail;
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
return;
fail:
@@ -21881,6 +21884,18 @@ fail:
return;
}
+/**
+ * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hotlist match callback
+ * @hddctx: HDD context
+ * @data: event data
+ *
+ * This function reads the hotlist matched event %data and fill in the skb with
+ * NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
static void
wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
struct extscan_hotlist_match *data)
@@ -21888,6 +21903,7 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
hdd_context_t *pHddCtx = ctx;
struct sk_buff *skb = NULL;
uint32_t i, index;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -21904,9 +21920,9 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
- NULL,
- EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
- index, GFP_KERNEL);
+ NULL,
+ EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
+ index, flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -21995,7 +22011,7 @@ wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
goto fail;
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
EXIT();
return;
@@ -22056,6 +22072,8 @@ wlan_hdd_cfg80211_extscan_generic_rsp
* This function will take an SSID match event that was generated by
* firmware and will convert it into a cfg80211 vendor event which is
* sent to userspace.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
*
* Return: none
*/
@@ -22067,6 +22085,7 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
struct sk_buff *skb;
unsigned i;
unsigned index;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22088,8 +22107,7 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
- index,
- GFP_KERNEL);
+ index, flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22182,15 +22200,26 @@ wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
}
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
return;
fail:
kfree_skb(skb);
return;
-
}
+/**
+ * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() - results callback
+ * @hddctx: HDD context
+ * @data: event data
+ *
+ * This function reads the event %data and fill in the skb with
+ * NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
static void
wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
void *ctx,
@@ -22201,6 +22230,7 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
tSirWifiSignificantChange *ap_info;
tANI_S32 *rssi;
tANI_U32 i, j;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22213,7 +22243,7 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
- GFP_KERNEL);
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22289,7 +22319,7 @@ wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
goto fail;
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
return;
fail:
@@ -22298,6 +22328,18 @@ fail:
}
+/**
+ * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan results event
+ * @hddctx: HDD context
+ * @data: event data
+ *
+ * This function reads the event %data and fill in the skb with
+ * NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
static void
wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
tpSirWifiFullScanResultEvent pData)
@@ -22307,6 +22349,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
#ifdef CONFIG_CNSS
struct timespec ts;
#endif
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22330,7 +22373,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
- GFP_KERNEL);
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22410,7 +22453,7 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
goto nla_put_failure;
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
EXIT();
return;
@@ -22426,6 +22469,8 @@ nla_put_failure:
*
* This function reads the matched network data and fills NL vendor attributes
* and send it to upper layer.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
*
* Return: 0 on success, error number otherwise
*/
@@ -22436,6 +22481,7 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
struct sk_buff *skb = NULL;
uint32_t len, i;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22462,8 +22508,8 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
- QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
- GFP_KERNEL);
+ QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22521,7 +22567,7 @@ wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
nla_nest_end(skb, nla_aps);
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
return;
fail:
@@ -22529,12 +22575,25 @@ fail:
return;
}
+/**
+ * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan available event
+ * @hddctx: HDD context
+ * @data: event data
+ *
+ * This function reads the event %data and fill in the skb with
+ * NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
static void
wlan_hdd_cfg80211_extscan_scan_res_available_event(void *ctx,
tpSirExtScanResultsAvailableIndParams pData)
{
hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
struct sk_buff *skb = NULL;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22549,7 +22608,7 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event(void *ctx,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
- GFP_KERNEL);
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22567,7 +22626,7 @@ wlan_hdd_cfg80211_extscan_scan_res_available_event(void *ctx,
goto nla_put_failure;
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
EXIT();
return;
@@ -22576,12 +22635,25 @@ nla_put_failure:
return;
}
+/**
+ * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
+ * @hddctx: HDD context
+ * @data: event data
+ *
+ * This function reads the event %data and fill in the skb with
+ * NL attributes and send up the NL event.
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
+ *
+ * Return: none
+ */
static void
wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
tpSirExtScanOnScanEventIndParams pData)
{
hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
struct sk_buff *skb = NULL;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22596,7 +22668,7 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
- GFP_KERNEL);
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22616,7 +22688,7 @@ wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
goto nla_put_failure;
}
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
EXIT();
return;
@@ -22632,6 +22704,8 @@ nla_put_failure:
*
* This function reads the match network %data and fill in the skb with
* NL attributes and send up the NL event
+ * This callback execute in atomic context and must not invoke any
+ * blocking calls.
*
* Return: none
*/
@@ -22644,6 +22718,7 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
uint32_t len, i, num_matches = 1, more_data = 0;
struct nlattr *nla_aps;
struct nlattr *nla_bss;
+ int flags = vos_get_gfp_flags();
ENTER();
@@ -22663,7 +22738,7 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
NULL,
EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
- GFP_KERNEL);
+ flags);
if (!skb) {
hddLog(LOGE, FL("cfg80211_vendor_event_alloc failed"));
@@ -22745,7 +22820,7 @@ wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
}
nla_nest_end(skb, nla_aps);
- cfg80211_vendor_event(skb, GFP_KERNEL);
+ cfg80211_vendor_event(skb, flags);
return;
fail:
diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c
index 521dff3fae9a..e90faa530fc1 100644
--- a/CORE/SERVICES/WMI/wmi_unified.c
+++ b/CORE/SERVICES/WMI/wmi_unified.c
@@ -892,7 +892,8 @@ void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
#ifndef QCA_CONFIG_SMP
id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
/* TX_PAUSE EVENT should be handled with tasklet context */
- if (WMI_TX_PAUSE_EVENTID == id) {
+ if ((WMI_TX_PAUSE_EVENTID == id) ||
+ (WMI_WOW_WAKEUP_HOST_EVENTID == id)) {
if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
return;
diff --git a/CORE/VOSS/src/vos_sched.c b/CORE/VOSS/src/vos_sched.c
index 083b455e97e0..834451cf1e04 100644
--- a/CORE/VOSS/src/vos_sched.c
+++ b/CORE/VOSS/src/vos_sched.c
@@ -2541,3 +2541,19 @@ bool vos_is_ssr_ready(const char *caller_func)
return true;
}
+
+/**
+ * vos_get_gfp_flags(): get GFP flags
+ *
+ * Based on the scheduled context, return GFP flags
+ * Return: gfp flags
+ */
+int vos_get_gfp_flags(void)
+{
+ int flags = GFP_KERNEL;
+
+ if (in_interrupt() || in_atomic() || irqs_disabled())
+ flags = GFP_ATOMIC;
+
+ return flags;
+}
diff --git a/CORE/VOSS/src/vos_sched.h b/CORE/VOSS/src/vos_sched.h
index 044ee62a21fc..19073cb8f9e5 100644
--- a/CORE/VOSS/src/vos_sched.h
+++ b/CORE/VOSS/src/vos_sched.h
@@ -672,6 +672,7 @@ void vos_ssr_protect_init(void);
void vos_ssr_protect(const char *caller_func);
void vos_ssr_unprotect(const char *caller_func);
bool vos_is_ssr_ready(const char *caller_func);
+int vos_get_gfp_flags(void);
#define vos_wait_for_work_thread_completion(func) vos_is_ssr_ready(func)