Prechádzať zdrojové kódy

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
Om Prakash Tripathi 6 rokov pred
rodič
commit
9b56f5dc1c

+ 5 - 5
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;

+ 6 - 2
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

+ 36 - 2
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.

+ 1 - 1
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");

+ 4 - 3
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;

+ 3 - 3
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;

+ 1 - 1
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;

+ 3 - 3
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;

+ 2 - 2
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);

+ 4 - 3
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;

+ 4 - 4
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);