From 9b56f5dc1ce033ca214a5bba916f7d857d62f176 Mon Sep 17 00:00:00 2001 From: Om Prakash Tripathi Date: Tue, 29 May 2018 11:42:19 +0530 Subject: [PATCH] qcacmn: Use atomic allocation for all scheduler context scan allocations In low memory environments using GFP_KERNEL flag may cause scheduler thread to sleep. Scheduler thread callback handlers are expected to be atomic in nature to ensure timely execution of different commands. Move all allocations done by scan module in scheduler thread context to atomic allocation. Change-Id: Iee3eafbc00a3afea0687ba67b3041ec0816094cc CRs-Fixed: 2232553 --- os_if/linux/scan/src/wlan_cfg80211_scan.c | 10 ++--- qdf/inc/qdf_mem.h | 8 +++- qdf/linux/src/qdf_mem.c | 38 ++++++++++++++++++- umac/scan/core/src/wlan_scan_11d.c | 2 +- umac/scan/core/src/wlan_scan_cache_db.c | 7 ++-- umac/scan/core/src/wlan_scan_main.c | 6 +-- umac/scan/core/src/wlan_scan_manager.c | 2 +- .../scan/dispatcher/inc/wlan_scan_utils_api.h | 6 +-- umac/scan/dispatcher/src/wlan_scan_tgt_api.c | 4 +- umac/scan/dispatcher/src/wlan_scan_ucfg_api.c | 7 ++-- .../scan/dispatcher/src/wlan_scan_utils_api.c | 8 ++-- 11 files changed, 69 insertions(+), 29 deletions(-) diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index b791636f50..8f6d757995 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -831,7 +831,7 @@ static void wlan_vendor_scan_callback(struct cfg80211_scan_request *req, skb = cfg80211_vendor_event_alloc(req->wdev->wiphy, req->wdev, SCAN_DONE_EVENT_BUF_SIZE + 4 + NLMSG_HDRLEN, QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX, - GFP_KERNEL); + GFP_ATOMIC); if (!skb) { cfg80211_err("skb alloc failed"); @@ -877,7 +877,7 @@ static void wlan_vendor_scan_callback(struct cfg80211_scan_request *req, if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, scan_status)) goto nla_put_failure; - cfg80211_vendor_event(skb, GFP_KERNEL); + cfg80211_vendor_event(skb, GFP_ATOMIC); qdf_mem_free(req); return; @@ -1737,7 +1737,7 @@ wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy, data.boottime_ns = bss->boottime_ns; data.signal = bss->rssi; return cfg80211_inform_bss_frame_data(wiphy, &data, bss->mgmt, - bss->frame_len, GFP_KERNEL); + bss->frame_len, GFP_ATOMIC); } #else struct cfg80211_bss * @@ -1747,7 +1747,7 @@ wlan_cfg80211_inform_bss_frame_data(struct wiphy *wiphy, { return cfg80211_inform_bss_frame(wiphy, bss->chan, bss->mgmt, bss->frame_len, - bss->rssi, GFP_KERNEL); + bss->rssi, GFP_ATOMIC); } #endif @@ -1781,7 +1781,7 @@ void wlan_cfg80211_inform_bss_frame(struct wlan_objmgr_pdev *pdev, wiphy = pdev_ospriv->wiphy; bss_data.frame_len = wlan_get_frame_len(scan_params); - bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len); + bss_data.mgmt = qdf_mem_malloc_atomic(bss_data.frame_len); if (!bss_data.mgmt) { cfg80211_err("mem alloc failed"); return; diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index 87d927dfbc..cbbc1891c9 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -93,6 +93,7 @@ void qdf_mem_exit(void); * @file: File name of the call site * @line: Line number of the call site * @caller: Address of the caller function + * @flag: GFP flag * * This function will dynamicallly allocate the specified number of bytes of * memory and add it to the qdf tracking list to check for memory leaks and @@ -101,11 +102,13 @@ void qdf_mem_exit(void); * Return: A valid memory location on success, or NULL on failure */ void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line, - void *caller); + void *caller, uint32_t flag); #define qdf_mem_malloc(size) \ - qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP) + qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP, 0) +#define qdf_mem_malloc_atomic(size) \ + qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP, GFP_ATOMIC) /** * qdf_mem_free_debug() - debug version of qdf_mem_free * @ptr: Pointer to the starting address of the memory to be freed. @@ -196,6 +199,7 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, __FILE__, __LINE__) #else void *qdf_mem_malloc(qdf_size_t size); +void *qdf_mem_malloc_atomic(qdf_size_t size); /** * qdf_mem_free() - free QDF memory diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index 7b2183f28e..a57c9de3b3 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -1061,7 +1061,7 @@ static void qdf_mem_debug_exit(void) } void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line, - void *caller) + void *caller, uint32_t flag) { QDF_STATUS status; enum qdf_debug_domain current_domain = qdf_debug_domain_get(); @@ -1079,8 +1079,11 @@ void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line, if (ptr) return ptr; + if (!flag) + flag = qdf_mem_malloc_flags(); + start = qdf_mc_timer_get_system_time(); - header = kzalloc(size + QDF_MEM_DEBUG_SIZE, qdf_mem_malloc_flags()); + header = kzalloc(size + QDF_MEM_DEBUG_SIZE, flag); duration = qdf_mc_timer_get_system_time() - start; if (duration > QDF_MEM_WARN_THRESHOLD) @@ -1193,6 +1196,37 @@ void *qdf_mem_malloc(size_t size) } qdf_export_symbol(qdf_mem_malloc); +/** + * qdf_mem_malloc_atomic() - allocation QDF memory atomically + * @size: Number of bytes of memory to allocate. + * + * This function will dynamicallly allocate the specified number of bytes of + * memory. + * + * Return: + * Upon successful allocate, returns a non-NULL pointer to the allocated + * memory. If this function is unable to allocate the amount of memory + * specified (for any reason) it returns NULL. + */ +void *qdf_mem_malloc_atomic(size_t size) +{ + void *ptr; + + ptr = qdf_mem_prealloc_get(size); + if (ptr) + return ptr; + + ptr = kzalloc(size, GFP_ATOMIC); + if (!ptr) + return NULL; + + qdf_mem_kmalloc_inc(ksize(ptr)); + + return ptr; +} + +qdf_export_symbol(qdf_mem_malloc_atomic); + /** * qdf_mem_free() - free QDF memory * @ptr: Pointer to the starting address of the memory to be free'd. diff --git a/umac/scan/core/src/wlan_scan_11d.c b/umac/scan/core/src/wlan_scan_11d.c index 3497be2634..dd1f48cb1c 100644 --- a/umac/scan/core/src/wlan_scan_11d.c +++ b/umac/scan/core/src/wlan_scan_11d.c @@ -236,7 +236,7 @@ QDF_STATUS scm_11d_cc_db_init(struct wlan_objmgr_psoc *psoc) return QDF_STATUS_E_INVAL; } - cc_db = (struct scan_country_code_db *)qdf_mem_malloc( + cc_db = (struct scan_country_code_db *)qdf_mem_malloc_atomic( sizeof(struct scan_country_code_db) * WLAN_UMAC_MAX_PDEVS); if (!cc_db) { scm_err("alloc country code db error"); diff --git a/umac/scan/core/src/wlan_scan_cache_db.c b/umac/scan/core/src/wlan_scan_cache_db.c index 3c66642167..9e1f4d65f7 100644 --- a/umac/scan/core/src/wlan_scan_cache_db.c +++ b/umac/scan/core/src/wlan_scan_cache_db.c @@ -442,7 +442,8 @@ static void scm_update_alt_wcn_ie(struct scan_cache_entry *from, if (!dst->alt_wcn_ie.ptr) { /* allocate this additional buffer for alternate WCN IE */ - dst->alt_wcn_ie.ptr = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2); + dst->alt_wcn_ie.ptr = + qdf_mem_malloc_atomic(WLAN_MAX_IE_LEN + 2); if (!dst->alt_wcn_ie.ptr) { scm_err("failed to allocate memory"); return; @@ -927,7 +928,7 @@ scm_scan_apply_filter_get_entry(struct wlan_objmgr_psoc *psoc, if (!match) return QDF_STATUS_SUCCESS; - scan_node = qdf_mem_malloc(sizeof(*scan_node)); + scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node)); if (!scan_node) return QDF_STATUS_E_NOMEM; @@ -1042,7 +1043,7 @@ qdf_list_t *scm_get_scan_result(struct wlan_objmgr_pdev *pdev, return NULL; } - tmp_list = qdf_mem_malloc(sizeof(*tmp_list)); + tmp_list = qdf_mem_malloc_atomic(sizeof(*tmp_list)); if (!tmp_list) { scm_err("failed tp allocate scan_result"); return NULL; diff --git a/umac/scan/core/src/wlan_scan_main.c b/umac/scan/core/src/wlan_scan_main.c index a4d2d3f960..e8fc4db6af 100644 --- a/umac/scan/core/src/wlan_scan_main.c +++ b/umac/scan/core/src/wlan_scan_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -29,7 +29,7 @@ QDF_STATUS wlan_scan_psoc_created_notification(struct wlan_objmgr_psoc *psoc, struct wlan_scan_obj *scan_obj; QDF_STATUS status = QDF_STATUS_SUCCESS; - scan_obj = qdf_mem_malloc(sizeof(struct wlan_scan_obj)); + scan_obj = qdf_mem_malloc_atomic(sizeof(struct wlan_scan_obj)); if (scan_obj == NULL) { scm_err("Failed to allocate memory"); return QDF_STATUS_E_NOMEM; @@ -78,7 +78,7 @@ QDF_STATUS wlan_scan_vdev_created_notification(struct wlan_objmgr_vdev *vdev, struct scan_vdev_obj *scan_vdev_obj; QDF_STATUS status = QDF_STATUS_SUCCESS; - scan_vdev_obj = qdf_mem_malloc(sizeof(struct scan_vdev_obj)); + scan_vdev_obj = qdf_mem_malloc_atomic(sizeof(struct scan_vdev_obj)); if (scan_vdev_obj == NULL) { scm_err("Failed to allocate memory"); return QDF_STATUS_E_NOMEM; diff --git a/umac/scan/core/src/wlan_scan_manager.c b/umac/scan/core/src/wlan_scan_manager.c index 6537782822..3bbe50564d 100644 --- a/umac/scan/core/src/wlan_scan_manager.c +++ b/umac/scan/core/src/wlan_scan_manager.c @@ -151,7 +151,7 @@ static void scm_scan_post_event(struct wlan_objmgr_vdev *vdev, event->vdev_id, event->type, event->reason, event->chan_freq, event->requester, event->scan_id); - listeners = qdf_mem_malloc(sizeof(*listeners)); + listeners = qdf_mem_malloc_atomic(sizeof(*listeners)); if (!listeners) { scm_warn("couldn't allocate listeners list"); return; diff --git a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h index 47ae06b779..394e4fbc50 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_utils_api.h +++ b/umac/scan/dispatcher/inc/wlan_scan_utils_api.h @@ -596,7 +596,7 @@ util_scan_copy_beacon_data(struct scan_cache_entry *new_entry, struct ie_list *ie_lst; new_entry->raw_frame.ptr = - qdf_mem_malloc(scan_entry->raw_frame.len); + qdf_mem_malloc_atomic(scan_entry->raw_frame.len); if (!new_entry->raw_frame.ptr) return QDF_STATUS_E_NOMEM; @@ -677,7 +677,7 @@ util_scan_copy_cache_entry(struct scan_cache_entry *scan_entry) return NULL; new_entry = - qdf_mem_malloc(sizeof(*scan_entry)); + qdf_mem_malloc_atomic(sizeof(*scan_entry)); if (!new_entry) return NULL; @@ -686,7 +686,7 @@ util_scan_copy_cache_entry(struct scan_cache_entry *scan_entry) if (scan_entry->alt_wcn_ie.ptr) { new_entry->alt_wcn_ie.ptr = - qdf_mem_malloc(scan_entry->alt_wcn_ie.len); + qdf_mem_malloc_atomic(scan_entry->alt_wcn_ie.len); if (!new_entry->alt_wcn_ie.ptr) { qdf_mem_free(new_entry); return NULL; diff --git a/umac/scan/dispatcher/src/wlan_scan_tgt_api.c b/umac/scan/dispatcher/src/wlan_scan_tgt_api.c index 4321f6ed27..5b18317862 100644 --- a/umac/scan/dispatcher/src/wlan_scan_tgt_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_tgt_api.c @@ -266,7 +266,7 @@ QDF_STATUS tgt_scan_bcn_probe_rx_callback(struct wlan_objmgr_psoc *psoc, qdf_nbuf_free(buf); return QDF_STATUS_E_INVAL; } - bcn = qdf_mem_malloc(sizeof(*bcn)); + bcn = qdf_mem_malloc_atomic(sizeof(*bcn)); if (!bcn) { scm_err("Failed to allocate memory for bcn"); @@ -274,7 +274,7 @@ QDF_STATUS tgt_scan_bcn_probe_rx_callback(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_NOMEM; } bcn->rx_data = - qdf_mem_malloc(sizeof(*rx_param)); + qdf_mem_malloc_atomic(sizeof(*rx_param)); if (!bcn->rx_data) { scm_err("Failed to allocate memory for rx_data"); qdf_mem_free(bcn); diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c index f7cd91e4c8..449ef02a1c 100644 --- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c @@ -1635,14 +1635,15 @@ ucfg_scan_init_chanlist_params(struct scan_start_request *req, * too much time to complete. */ if (pdev && !num_chans && ucfg_scan_get_wide_band_scan(pdev)) { - reg_chan_list = qdf_mem_malloc(NUM_CHANNELS * + reg_chan_list = qdf_mem_malloc_atomic(NUM_CHANNELS * sizeof(struct regulatory_channel)); if (!reg_chan_list) { scm_err("Couldn't allocate reg_chan_list memory"); status = QDF_STATUS_E_NOMEM; goto end; } - scan_freqs = qdf_mem_malloc(sizeof(uint32_t) * max_chans); + scan_freqs = + qdf_mem_malloc_atomic(sizeof(uint32_t) * max_chans); if (!scan_freqs) { scm_err("Couldn't allocate scan_freqs memory"); status = QDF_STATUS_E_NOMEM; @@ -1897,7 +1898,7 @@ ucfg_scan_cancel_pdev_scan(struct wlan_objmgr_pdev *pdev) QDF_STATUS status; struct wlan_objmgr_vdev *vdev; - req = qdf_mem_malloc(sizeof(*req)); + req = qdf_mem_malloc_atomic(sizeof(*req)); if (!req) { scm_err("Failed to allocate memory"); return QDF_STATUS_E_NOMEM; diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c index 79834820b0..4e129f11de 100644 --- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c +++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c @@ -831,21 +831,21 @@ util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame, qdf_list_t *scan_list; struct scan_cache_node *scan_node; - scan_list = qdf_mem_malloc(sizeof(*scan_list)); + scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list)); if (!scan_list) { scm_err("failed to allocate scan_list"); return NULL; } qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE); - scan_entry = qdf_mem_malloc(sizeof(*scan_entry)); + scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry)); if (!scan_entry) { scm_err("failed to allocate memory for scan_entry"); qdf_mem_free(scan_list); return NULL; } scan_entry->raw_frame.ptr = - qdf_mem_malloc(frame_len); + qdf_mem_malloc_atomic(frame_len); if (!scan_entry->raw_frame.ptr) { scm_err("failed to allocate memory for frame"); qdf_mem_free(scan_entry); @@ -960,7 +960,7 @@ util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame, if (qbss_load) scan_entry->qbss_chan_load = qbss_load->qbss_chan_load; - scan_node = qdf_mem_malloc(sizeof(*scan_node)); + scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node)); if (!scan_node) { qdf_mem_free(scan_entry->raw_frame.ptr); qdf_mem_free(scan_entry);