blob: d27a31f355381c23d8b1f323b7dfba4dcdc0e825 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Sarada Prasanna Garnayake1722632017-01-05 15:27:15 +05302 * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28#include <linux/platform_device.h>
29#include <linux/pci.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080030#include "cds_api.h"
Anurag Chouhance0dc992016-02-16 18:18:03 +053031#include "qdf_status.h"
Anurag Chouhana37b5b72016-02-21 14:53:42 +053032#include "qdf_lock.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033#include "cds_sched.h"
34#include "osdep.h"
35#include "hif.h"
Houston Hoffmane8937082015-11-10 16:49:12 -080036#include "htc.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080037#include "epping_main.h"
38#include "wlan_hdd_main.h"
39#include "wlan_hdd_power.h"
40#include "wlan_logging_sock_svc.h"
41#include "wma_api.h"
42#include "wlan_hdd_napi.h"
Tushnim Bhattacharyya9028cc72017-03-09 13:10:49 -080043#include "wlan_policy_mgr_api.h"
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080044#include "qwlan_version.h"
Komal Seelamd9106492016-02-15 10:31:44 +053045#include "bmi.h"
Dhanashri Atreb08959a2016-03-01 17:28:03 -080046#include "cdp_txrx_bus.h"
Sarada Prasanna Garnayake1722632017-01-05 15:27:15 +053047#include "cdp_txrx_misc.h"
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070048#include "pld_common.h"
Jeff Johnson7782cb92016-10-05 14:22:40 -070049#include "wlan_hdd_driver_ops.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050
51#ifdef MODULE
52#define WLAN_MODULE_NAME module_name(THIS_MODULE)
53#else
54#define WLAN_MODULE_NAME "wlan"
55#endif
56
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -070057#define DISABLE_KRAIT_IDLE_PS_VAL 1
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080058
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +053059#define SSR_MAX_FAIL_CNT 2
60static uint8_t re_init_fail_cnt, probe_fail_cnt;
61
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080062/*
63 * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at
64 * a time, and wait for the completion interrupt to start the next transfer.
65 * During this phase, the KRAIT is entering IDLE/StandAlone(SA) Power Save(PS).
66 * The delay incurred for resuming from IDLE/SA PS is huge during driver load.
67 * So prevent APPS IDLE/SA PS durint driver load for reducing interrupt latency.
68 */
Yuanyuan Liu13738502016-04-06 17:41:37 -070069
70static inline void hdd_request_pm_qos(struct device *dev, int val)
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080071{
Yuanyuan Liu13738502016-04-06 17:41:37 -070072 pld_request_pm_qos(dev, val);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080073}
74
Yuanyuan Liu13738502016-04-06 17:41:37 -070075static inline void hdd_remove_pm_qos(struct device *dev)
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080076{
Yuanyuan Liu13738502016-04-06 17:41:37 -070077 pld_remove_pm_qos(dev);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080078}
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080079
80/**
Komal Seelamad5a90d2016-02-16 13:50:03 +053081 * hdd_set_recovery_in_progress() - API to set recovery in progress
82 * @data: Context
83 * @val: Value to set
84 *
85 * Return: None
86 */
87static void hdd_set_recovery_in_progress(void *data, uint8_t val)
88{
89 cds_set_recovery_in_progress(val);
90}
91
92/**
93 * hdd_is_driver_unloading() - API to query if driver is unloading
94 * @data: Private Data
95 *
96 * Return: True/False
97 */
98static bool hdd_is_driver_unloading(void *data)
99{
100 return cds_is_driver_unloading();
101}
102
103/**
104 * hdd_is_load_or_unload_in_progress() - API to query if driver is
105 * loading/unloading
106 * @data: Private Data
107 *
108 * Return: bool
109 */
110static bool hdd_is_load_or_unload_in_progress(void *data)
111{
112 return cds_is_load_or_unload_in_progress();
113}
114
115/**
Komal Seelam1aac1982016-03-02 15:57:26 +0530116 * hdd_is_recovery_in_progress() - API to query if recovery in progress
Komal Seelamad5a90d2016-02-16 13:50:03 +0530117 * @data: Private Data
118 *
119 * Return: bool
120 */
Komal Seelam1aac1982016-03-02 15:57:26 +0530121static bool hdd_is_recovery_in_progress(void *data)
Komal Seelamad5a90d2016-02-16 13:50:03 +0530122{
123 return cds_is_driver_recovering();
124}
125
126/**
Komal Seelam1aac1982016-03-02 15:57:26 +0530127 * hdd_hif_init_driver_state_callbacks() - API to initialize HIF callbacks
Komal Seelamad5a90d2016-02-16 13:50:03 +0530128 * @data: Private Data
Komal Seelam1aac1982016-03-02 15:57:26 +0530129 * @cbk: HIF Driver State callbacks
Komal Seelamad5a90d2016-02-16 13:50:03 +0530130 *
131 * HIF should be independent of CDS calls. Pass CDS Callbacks to HIF, HIF will
132 * call the callbacks.
133 *
134 * Return: void
135 */
Komal Seelam1aac1982016-03-02 15:57:26 +0530136static void hdd_hif_init_driver_state_callbacks(void *data,
137 struct hif_driver_state_callbacks *cbk)
Komal Seelamad5a90d2016-02-16 13:50:03 +0530138{
139 cbk->context = data;
140 cbk->set_recovery_in_progress = hdd_set_recovery_in_progress;
Komal Seelam1aac1982016-03-02 15:57:26 +0530141 cbk->is_recovery_in_progress = hdd_is_recovery_in_progress;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530142 cbk->is_load_unload_in_progress = hdd_is_load_or_unload_in_progress;
143 cbk->is_driver_unloading = hdd_is_driver_unloading;
144}
145
146/**
147 * hdd_init_cds_hif_context() - API to set CDS HIF Context
148 * @hif: HIF Context
149 *
150 * Return: success/failure
151 */
152static int hdd_init_cds_hif_context(void *hif)
153{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530154 QDF_STATUS status;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530155
Anurag Chouhan6d760662016-02-20 16:05:43 +0530156 status = cds_set_context(QDF_MODULE_ID_HIF, hif);
Komal Seelamad5a90d2016-02-16 13:50:03 +0530157
158 if (status)
159 return -ENOENT;
160
161 return 0;
162}
163
164/**
165 * hdd_deinit_cds_hif_context() - API to clear CDS HIF COntext
166 *
167 * Return: None
168 */
169static void hdd_deinit_cds_hif_context(void)
170{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530171 QDF_STATUS status;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530172
Anurag Chouhan6d760662016-02-20 16:05:43 +0530173 status = cds_set_context(QDF_MODULE_ID_HIF, NULL);
Komal Seelamad5a90d2016-02-16 13:50:03 +0530174
175 if (status)
176 hdd_err("Failed to reset CDS HIF Context");
Komal Seelamad5a90d2016-02-16 13:50:03 +0530177}
178
179/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -0700180 * to_bus_type() - Map PLD bus type to low level bus type
181 * @bus_type: PLD bus type
182 *
183 * Map PLD bus type to low level bus type.
184 *
185 * Return: low level bus type.
186 */
187static enum qdf_bus_type to_bus_type(enum pld_bus_type bus_type)
188{
189 switch (bus_type) {
190 case PLD_BUS_TYPE_PCIE:
191 return QDF_BUS_TYPE_PCI;
192 case PLD_BUS_TYPE_SNOC:
193 return QDF_BUS_TYPE_SNOC;
Poddar, Siddarth3e9fa5c2016-05-13 14:25:05 +0530194 case PLD_BUS_TYPE_SDIO:
195 return QDF_BUS_TYPE_SDIO;
Mohit Khannafa99aea2016-05-12 21:43:13 -0700196 case PLD_BUS_TYPE_USB:
197 return QDF_BUS_TYPE_USB;
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -0700198 default:
199 return QDF_BUS_TYPE_NONE;
200 }
201}
202
Manikandan Mohan617a5162017-04-10 13:14:40 -0700203int hdd_hif_open(struct device *dev, void *bdev, const struct hif_bus_id *bid,
Anurag Chouhan2ed1fce2016-02-22 15:07:01 +0530204 enum qdf_bus_type bus_type, bool reinit)
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800205{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530206 QDF_STATUS status;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800207 int ret = 0;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530208 struct hif_opaque_softc *hif_ctx;
Anurag Chouhandf2b2682016-02-29 14:15:27 +0530209 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Komal Seelam1aac1982016-03-02 15:57:26 +0530210 struct hif_driver_state_callbacks cbk;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530211 uint32_t mode = cds_get_conparam();
Jeff Johnson6bc79d82017-08-28 12:02:36 -0700212 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Govind Singh068c4b02016-08-17 16:37:13 +0530213
214 if (!hdd_ctx) {
215 hdd_err("hdd_ctx error");
216 return -EFAULT;
217 }
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800218
Komal Seelam1aac1982016-03-02 15:57:26 +0530219 hdd_hif_init_driver_state_callbacks(dev, &cbk);
Komal Seelamad5a90d2016-02-16 13:50:03 +0530220
Anurag Chouhandf2b2682016-02-29 14:15:27 +0530221 hif_ctx = hif_open(qdf_ctx, mode, bus_type, &cbk);
Komal Seelamad5a90d2016-02-16 13:50:03 +0530222 if (!hif_ctx) {
223 hdd_err("hif_open error");
224 return -ENOMEM;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800225 }
226
Komal Seelamad5a90d2016-02-16 13:50:03 +0530227 ret = hdd_init_cds_hif_context(hif_ctx);
228 if (ret) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800229 hdd_err("Failed to set global HIF CDS Context err: %d", ret);
Komal Seelamad5a90d2016-02-16 13:50:03 +0530230 goto err_hif_close;
231 }
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800232
Dustin Brownfe7aa872017-06-26 10:52:08 -0700233 if (hdd_ctx->config->prevent_link_down)
234 hif_vote_link_up(hif_ctx);
235
Houston Hoffmanc1f962e2016-04-13 16:35:44 -0700236 status = hif_enable(hif_ctx, dev, bdev, bid, bus_type,
237 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
238 HIF_ENABLE_TYPE_PROBE);
239 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800240 hdd_err("hif_enable failed status: %d, reinit: %d",
Houston Hoffmanc1f962e2016-04-13 16:35:44 -0700241 status, reinit);
Nachiket Kukade8003d252017-03-30 15:55:58 +0530242
Houston Hoffmanc1f962e2016-04-13 16:35:44 -0700243 ret = qdf_status_to_os_return(status);
244 goto err_hif_close;
245 } else {
246 ret = hdd_napi_create();
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800247 hdd_debug("hdd_napi_create returned: %d", ret);
Manjunathappa Prakash9dd19132016-04-21 16:27:04 -0700248 if (ret == 0)
249 hdd_warn("NAPI: no instances are created");
250 else if (ret < 0) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800251 hdd_err("NAPI creation error, rc: 0x%x, reinit: %d",
Komal Seelamad5a90d2016-02-16 13:50:03 +0530252 ret, reinit);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800253 ret = -EFAULT;
254 goto err_hif_close;
Govind Singh068c4b02016-08-17 16:37:13 +0530255 } else {
256 hdd_napi_event(NAPI_EVT_INI_FILE,
257 (void *)hdd_ctx->napi_enable);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800258 }
259 }
260
Sravan Kumar Kairam27296782017-04-21 22:04:18 +0530261 pmo_ucfg_psoc_set_hif_handle(hdd_ctx->hdd_psoc, hif_ctx);
262
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800263 return 0;
264
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800265err_hif_close:
Komal Seelamad5a90d2016-02-16 13:50:03 +0530266 hdd_deinit_cds_hif_context();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800267 hif_close(hif_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800268 return ret;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800269}
270
Jeff Johnson6bc79d82017-08-28 12:02:36 -0700271void hdd_hif_close(struct hdd_context *hdd_ctx, void *hif_ctx)
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800272{
Sravan Kumar Kairam27296782017-04-21 22:04:18 +0530273 if (!hdd_ctx) {
274 hdd_err("hdd_ctx error");
275 return;
276 }
277
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800278 if (hif_ctx == NULL)
279 return;
280
281 hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE);
282
283 hdd_napi_destroy(true);
284
Komal Seelamad5a90d2016-02-16 13:50:03 +0530285 hdd_deinit_cds_hif_context();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800286 hif_close(hif_ctx);
Sravan Kumar Kairam27296782017-04-21 22:04:18 +0530287
288 pmo_ucfg_psoc_set_hif_handle(hdd_ctx->hdd_psoc, NULL);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800289}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290
291/**
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530292 * hdd_init_qdf_ctx() - API to initialize global QDF Device structure
Komal Seelam48152e12016-02-09 17:50:33 +0530293 * @dev: Device Pointer
294 * @bdev: Bus Device pointer
Arun Khandavallifae92942016-08-01 13:31:08 +0530295 * @bus_type: Underlying bus type
296 * @bid: Bus id passed by platform driver
Komal Seelam48152e12016-02-09 17:50:33 +0530297 *
298 * Return: void
299 */
Jeff Johnson7782cb92016-10-05 14:22:40 -0700300static void hdd_init_qdf_ctx(struct device *dev, void *bdev,
301 enum qdf_bus_type bus_type,
302 const struct hif_bus_id *bid)
Komal Seelam48152e12016-02-09 17:50:33 +0530303{
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530304 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Komal Seelam48152e12016-02-09 17:50:33 +0530305
Jeff Johnson615d4bb2016-07-20 11:03:04 -0700306 if (!qdf_dev) {
307 hdd_err("Invalid QDF device");
308 return;
309 }
310
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530311 qdf_dev->dev = dev;
312 qdf_dev->drv_hdl = bdev;
Govind Singh9db91ba2016-04-29 14:15:47 +0530313 qdf_dev->bus_type = bus_type;
Arun Khandavallifae92942016-08-01 13:31:08 +0530314 qdf_dev->bid = bid;
Komal Seelam48152e12016-02-09 17:50:33 +0530315}
316
317/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318 * wlan_hdd_probe() - handles probe request
319 *
320 * This function is called to probe the wlan driver
321 *
322 * @dev: wlan device structure
323 * @bdev: bus device structure
324 * @bid: bus identifier for shared busses
325 * @bus_type: underlying bus type
326 * @reinit: true if we are reinitiallizing the driver after a subsystem restart
327 *
328 * Return: 0 on successfull probe
329 */
Manikandan Mohan617a5162017-04-10 13:14:40 -0700330static int wlan_hdd_probe(struct device *dev, void *bdev,
331 const struct hif_bus_id *bid,
332 enum qdf_bus_type bus_type, bool reinit)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800333{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800334 int ret = 0;
335
336 pr_info("%s: %sprobing driver v%s\n", WLAN_MODULE_NAME,
337 reinit ? "re-" : "", QWLAN_VERSIONSTR);
338
339 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
340
341 /*
Jeff Johnson0a9da592017-01-12 09:48:36 -0800342 * The Krait is going to Idle/Stand Alone Power Save more
343 * aggressively which is resulting in the longer driver load
344 * time. The Fix is to not allow Krait to enter Idle Power
345 * Save during driver load.
346 */
Yuanyuan Liu13738502016-04-06 17:41:37 -0700347 hdd_request_pm_qos(dev, DISABLE_KRAIT_IDLE_PS_VAL);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800348
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +0530349 if (reinit)
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800350 cds_set_recovery_in_progress(true);
Arunk Khandavalli2dc0c962016-10-20 12:37:26 +0530351 else
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800352 cds_set_load_in_progress(true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353
Arun Khandavallifae92942016-08-01 13:31:08 +0530354 hdd_init_qdf_ctx(dev, bdev, bus_type, (const struct hif_bus_id *)bid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530356 if (reinit) {
Arun Khandavallifae92942016-08-01 13:31:08 +0530357 ret = hdd_wlan_re_init();
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530358 if (ret)
359 re_init_fail_cnt++;
360 } else {
Arun Khandavallifae92942016-08-01 13:31:08 +0530361 ret = hdd_wlan_startup(dev);
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530362 if (ret)
363 probe_fail_cnt++;
364 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800366 if (ret)
Arun Khandavallifae92942016-08-01 13:31:08 +0530367 goto err_hdd_deinit;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800370 if (reinit) {
371 cds_set_recovery_in_progress(false);
372 } else {
373 cds_set_load_in_progress(false);
374 cds_set_driver_loaded(true);
375 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800377 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Yuanyuan Liu13738502016-04-06 17:41:37 -0700378 hdd_remove_pm_qos(dev);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800379
Nachiket Kukade8003d252017-03-30 15:55:58 +0530380 cds_set_fw_down(false);
381
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530382 cds_set_driver_in_bad_state(false);
383 probe_fail_cnt = 0;
384 re_init_fail_cnt = 0;
385
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800386 return 0;
387
Arun Khandavallifae92942016-08-01 13:31:08 +0530388
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800389err_hdd_deinit:
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530390 pr_err("probe/reinit failure counts %hhu/%hhu",
391 probe_fail_cnt, re_init_fail_cnt);
392 if (probe_fail_cnt >= SSR_MAX_FAIL_CNT ||
393 re_init_fail_cnt >= SSR_MAX_FAIL_CNT)
394 QDF_BUG(0);
395
396 if (reinit) {
397 cds_set_driver_in_bad_state(true);
Arun Khandavallifae92942016-08-01 13:31:08 +0530398 cds_set_recovery_in_progress(false);
Srinivas Girigowda576b2352017-08-25 14:44:26 -0700399 } else
Arun Khandavallifae92942016-08-01 13:31:08 +0530400 cds_set_load_in_progress(false);
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530401
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800402 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
Yuanyuan Liu13738502016-04-06 17:41:37 -0700403 hdd_remove_pm_qos(dev);
Nachiket Kukade8003d252017-03-30 15:55:58 +0530404
405 cds_set_fw_down(false);
406
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800407 return ret;
408}
409
Yuanyuan Liu13738502016-04-06 17:41:37 -0700410static inline void hdd_pld_driver_unloading(struct device *dev)
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800411{
Yuanyuan Liu13738502016-04-06 17:41:37 -0700412 pld_set_driver_status(dev, PLD_LOAD_UNLOAD);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800413}
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800414
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415/**
416 * wlan_hdd_remove() - wlan_hdd_remove
417 *
418 * This function is called by the platform driver to remove the
419 * driver
420 *
421 * Return: void
422 */
Yuanyuan Liu13738502016-04-06 17:41:37 -0700423static void wlan_hdd_remove(struct device *dev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424{
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800425 pr_info("%s: Removing driver v%s\n", WLAN_MODULE_NAME,
426 QWLAN_VERSIONSTR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800427
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800428 cds_set_driver_loaded(false);
429 cds_set_unload_in_progress(true);
430
Rajeev Kumardbc886e2016-01-19 12:56:04 -0800431 if (!cds_wait_for_external_threads_completion(__func__))
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800432 hdd_warn("External threads are still active attempting driver unload anyway");
Rajeev Kumardbc886e2016-01-19 12:56:04 -0800433
Yuanyuan Liu13738502016-04-06 17:41:37 -0700434 hdd_pld_driver_unloading(dev);
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800435
Houston Hoffman371d4a92016-04-14 17:02:37 -0700436 if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800437 epping_disable();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800438 epping_close();
439 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800440 __hdd_wlan_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 }
442
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530443 cds_set_driver_in_bad_state(false);
Hanumanth Reddy Pothulafc70ea32017-01-18 18:19:08 +0530444 cds_set_unload_in_progress(false);
445
Mohit Khannafa99aea2016-05-12 21:43:13 -0700446 pr_info("%s: Driver De-initialized\n", WLAN_MODULE_NAME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800447}
448
Sen, Devendra154b3c42017-02-13 20:44:15 +0530449#ifdef FEATURE_WLAN_DIAG_SUPPORT
450/**
451 * hdd_wlan_ssr_shutdown_event()- send ssr shutdown state
452 *
453 * This Function send send ssr shutdown state diag event
454 *
455 * Return: void.
456 */
457static void hdd_wlan_ssr_shutdown_event(void)
458{
459 WLAN_HOST_DIAG_EVENT_DEF(ssr_shutdown,
460 struct host_event_wlan_ssr_shutdown);
461 qdf_mem_zero(&ssr_shutdown, sizeof(ssr_shutdown));
462 ssr_shutdown.status = SSR_SUB_SYSTEM_SHUTDOWN;
463 WLAN_HOST_DIAG_EVENT_REPORT(&ssr_shutdown,
464 EVENT_WLAN_SSR_SHUTDOWN_SUBSYSTEM);
465}
466#else
467static inline void hdd_wlan_ssr_shutdown_event(void)
468{
469
470};
471#endif
472
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473/**
474 * wlan_hdd_shutdown() - wlan_hdd_shutdown
475 *
476 * This is routine is called by platform driver to shutdown the
477 * driver
478 *
479 * Return: void
480 */
481static void wlan_hdd_shutdown(void)
482{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530483 void *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484
Dustin Browncd601322017-03-28 14:18:46 -0700485 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
486 hdd_err("Crash recovery is not allowed in FTM mode");
487 QDF_BUG(0);
488 return;
489 }
490
bings5f0ae142017-07-14 17:52:45 +0800491 if (!hif_ctx) {
492 hdd_err("Failed to get HIF context, ignore SSR shutdown");
493 return;
494 }
495 /* mask the host controller interrupts */
496 hif_mask_interrupt_call(hif_ctx);
497
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800498 if (cds_is_load_or_unload_in_progress()) {
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800499 hdd_err("Load/unload in progress, ignore SSR shutdown");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 return;
501 }
Yuanyuan Liu13738502016-04-06 17:41:37 -0700502 /* this is for cases, where shutdown invoked from platform */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800503 cds_set_recovery_in_progress(true);
Sen, Devendra154b3c42017-02-13 20:44:15 +0530504 hdd_wlan_ssr_shutdown_event();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505
Rajeev Kumardbc886e2016-01-19 12:56:04 -0800506 if (!cds_wait_for_external_threads_completion(__func__))
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800507 hdd_err("Host is not ready for SSR, attempting anyway");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508
Houston Hoffman371d4a92016-04-14 17:02:37 -0700509 if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
bings5f0ae142017-07-14 17:52:45 +0800510 hif_disable_isr(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800511 hdd_wlan_shutdown();
Yue Macd961442015-10-20 16:15:31 -0700512 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800513}
514
515/**
516 * wlan_hdd_crash_shutdown() - wlan_hdd_crash_shutdown
517 *
518 * HDD crash shutdown funtion: This function is called by
519 * platfrom driver's crash shutdown routine
520 *
521 * Return: void
522 */
Jeff Johnson7782cb92016-10-05 14:22:40 -0700523static void wlan_hdd_crash_shutdown(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800524{
Anurag Chouhan6d760662016-02-20 16:05:43 +0530525 hif_crash_shutdown(cds_get_context(QDF_MODULE_ID_HIF));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526}
527
528/**
529 * wlan_hdd_notify_handler() - wlan_hdd_notify_handler
530 *
531 * This function is called by the platform driver to notify the
532 * COEX
533 *
534 * @state: state
535 *
536 * Return: void
537 */
Jeff Johnson7782cb92016-10-05 14:22:40 -0700538static void wlan_hdd_notify_handler(int state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539{
Houston Hoffman371d4a92016-04-14 17:02:37 -0700540 if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
Jeff Johnson10251bc2017-03-24 15:30:52 -0700541 int ret;
542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543 ret = hdd_wlan_notify_modem_power_state(state);
544 if (ret < 0)
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800545 hdd_err("Fail to send notify");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546 }
547}
548
Dustin Brown9ef609b2017-03-15 12:19:37 -0700549static int hdd_to_pmo_interface_pause(enum wow_interface_pause hdd_pause,
550 enum pmo_wow_interface_pause *pmo_pause)
551{
552 switch (hdd_pause) {
553 case WOW_INTERFACE_PAUSE_DEFAULT:
554 *pmo_pause = PMO_WOW_INTERFACE_PAUSE_DEFAULT;
555 break;
556 case WOW_INTERFACE_PAUSE_ENABLE:
557 *pmo_pause = PMO_WOW_INTERFACE_PAUSE_ENABLE;
558 break;
559 case WOW_INTERFACE_PAUSE_DISABLE:
560 *pmo_pause = PMO_WOW_INTERFACE_PAUSE_DISABLE;
561 break;
562 default:
563 hdd_err("Invalid interface pause: %d", hdd_pause);
564 return -EINVAL;
565 }
566
567 return 0;
568}
569
570static int hdd_to_pmo_resume_trigger(enum wow_resume_trigger hdd_trigger,
571 enum pmo_wow_resume_trigger *pmo_trigger)
572{
573 switch (hdd_trigger) {
574 case WOW_RESUME_TRIGGER_DEFAULT:
575 *pmo_trigger = PMO_WOW_RESUME_TRIGGER_DEFAULT;
576 break;
577 case WOW_RESUME_TRIGGER_HTC_WAKEUP:
578 *pmo_trigger = PMO_WOW_RESUME_TRIGGER_HTC_WAKEUP;
579 break;
580 case WOW_RESUME_TRIGGER_GPIO:
581 *pmo_trigger = PMO_WOW_RESUME_TRIGGER_GPIO;
582 break;
583 default:
584 hdd_err("Invalid resume trigger: %d", hdd_trigger);
585 return -EINVAL;
586 }
587
588 return 0;
589}
590
591static int
592hdd_to_pmo_wow_enable_params(struct wow_enable_params *in_params,
593 struct pmo_wow_enable_params *out_params)
594{
595 int err;
596
597 /* unit-test suspend */
598 out_params->is_unit_test = in_params->is_unit_test;
599
600 /* interface pause */
601 err = hdd_to_pmo_interface_pause(in_params->interface_pause,
602 &out_params->interface_pause);
603 if (err)
604 return err;
605
606 /* resume trigger */
607 err = hdd_to_pmo_resume_trigger(in_params->resume_trigger,
608 &out_params->resume_trigger);
609 if (err)
610 return err;
611
612 return 0;
613}
614
Yuanyuan Liu06a342f2017-01-12 16:48:19 -0800615/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616 * __wlan_hdd_bus_suspend() - handles platform supsend
Dustin Brown54096432017-02-23 13:00:44 -0800617 * @wow_params: collection of wow enable override parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 *
619 * Does precondtion validation. Ensures that a subsystem restart isn't in
Dustin Brown9ef609b2017-03-15 12:19:37 -0700620 * progress. Ensures that no load or unload is in progress. Does:
621 * data path suspend
622 * component (pmo) suspend
623 * hif (bus) suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 *
625 * Return: 0 for success, -EFAULT for null pointers,
626 * -EBUSY or -EAGAIN if another opperation is in progress and
627 * wlan will not be ready to suspend in time.
628 */
Dustin Brown9ef609b2017-03-15 12:19:37 -0700629static int __wlan_hdd_bus_suspend(struct wow_enable_params wow_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630{
Dustin Brown562b9672016-12-22 15:25:33 -0800631 int err;
Dustin Brown9ef609b2017-03-15 12:19:37 -0700632 QDF_STATUS status;
Jeff Johnson6bc79d82017-08-28 12:02:36 -0700633 struct hdd_context *hdd_ctx;
Dustin Brown9ef609b2017-03-15 12:19:37 -0700634 void *hif_ctx;
Dustin Brown7ff24dd2017-05-10 15:49:59 -0700635 void *dp_soc;
636 void *dp_pdev;
Dustin Brown9ef609b2017-03-15 12:19:37 -0700637 struct pmo_wow_enable_params pmo_params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800639 hdd_debug("starting bus suspend");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640
Dustin Brown9ef609b2017-03-15 12:19:37 -0700641 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Dustin Brown562b9672016-12-22 15:25:33 -0800642 err = wlan_hdd_validate_context(hdd_ctx);
643 if (err) {
Dustin Brown9ef609b2017-03-15 12:19:37 -0700644 hdd_err("Invalid hdd context: %d", err);
645 return err;
Dustin Brown562b9672016-12-22 15:25:33 -0800646 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647
Rajeev Kumar99805a72016-08-29 13:53:52 -0700648 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800649 hdd_debug("Driver Module closed; skipping suspend");
Rajeev Kumar99805a72016-08-29 13:53:52 -0700650 return 0;
651 }
652
SaidiReddy Yenugad8323662016-07-20 15:45:34 +0530653 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Dustin Brown9ef609b2017-03-15 12:19:37 -0700654 if (!hif_ctx) {
Dustin Brown562b9672016-12-22 15:25:33 -0800655 hdd_err("Failed to get hif context");
Dustin Brown9ef609b2017-03-15 12:19:37 -0700656 return -EINVAL;
SaidiReddy Yenugad8323662016-07-20 15:45:34 +0530657 }
Arun Khandavallifae92942016-08-01 13:31:08 +0530658
Dustin Brown9ef609b2017-03-15 12:19:37 -0700659 err = hdd_to_pmo_wow_enable_params(&wow_params, &pmo_params);
660 if (err) {
661 hdd_err("Invalid WoW enable parameters: %d", err);
662 return err;
663 }
664
Dustin Brown7ff24dd2017-05-10 15:49:59 -0700665 dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
666 dp_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
667 err = qdf_status_to_os_return(cdp_bus_suspend(dp_soc, dp_pdev));
Dustin Brown562b9672016-12-22 15:25:33 -0800668 if (err) {
Dustin Brown9ef609b2017-03-15 12:19:37 -0700669 hdd_err("Failed cdp bus suspend: %d", err);
670 return err;
Dustin Brown562b9672016-12-22 15:25:33 -0800671 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672
Dustin Brown9ef609b2017-03-15 12:19:37 -0700673 status = pmo_ucfg_psoc_bus_suspend_req(hdd_ctx->hdd_psoc,
674 QDF_SYSTEM_SUSPEND,
675 &pmo_params);
676 err = qdf_status_to_os_return(status);
Dustin Brown562b9672016-12-22 15:25:33 -0800677 if (err) {
Dustin Brown9ef609b2017-03-15 12:19:37 -0700678 hdd_err("Failed pmo bus suspend: %d", status);
679 goto resume_cdp;
Dustin Brown562b9672016-12-22 15:25:33 -0800680 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681
Komal Seelamc12e6752016-02-02 18:17:13 +0530682 err = hif_bus_suspend(hif_ctx);
Dustin Brown562b9672016-12-22 15:25:33 -0800683 if (err) {
Dustin Brown9ef609b2017-03-15 12:19:37 -0700684 hdd_err("Failed hif bus suspend: %d", err);
685 goto resume_pmo;
Dustin Brown562b9672016-12-22 15:25:33 -0800686 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800688 hdd_debug("bus suspend succeeded");
Dustin Brown2d228232016-09-22 15:06:19 -0700689 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690
Dustin Brown9ef609b2017-03-15 12:19:37 -0700691resume_pmo:
692 status = pmo_ucfg_psoc_bus_resume_req(hdd_ctx->hdd_psoc,
693 QDF_SYSTEM_SUSPEND);
694 QDF_BUG(QDF_IS_STATUS_SUCCESS(status));
695
696resume_cdp:
Dustin Brown7ff24dd2017-05-10 15:49:59 -0700697 status = cdp_bus_resume(dp_soc, dp_pdev);
Dustin Brown9ef609b2017-03-15 12:19:37 -0700698 QDF_BUG(QDF_IS_STATUS_SUCCESS(status));
699
700 /* return suspend related error code */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800701 return err;
702}
703
Dustin Brown9ef609b2017-03-15 12:19:37 -0700704int wlan_hdd_bus_suspend(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705{
706 int ret;
Dustin Brown54096432017-02-23 13:00:44 -0800707 struct wow_enable_params default_params = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708
709 cds_ssr_protect(__func__);
Dustin Brown9ef609b2017-03-15 12:19:37 -0700710 ret = __wlan_hdd_bus_suspend(default_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 cds_ssr_unprotect(__func__);
712
713 return ret;
714}
715
Dustin Browne70fd972016-11-10 11:17:40 -0800716#ifdef WLAN_SUSPEND_RESUME_TEST
Dustin Brown9ef609b2017-03-15 12:19:37 -0700717int wlan_hdd_unit_test_bus_suspend(struct wow_enable_params wow_params)
Dustin Browne70fd972016-11-10 11:17:40 -0800718{
719 int ret;
720
721 cds_ssr_protect(__func__);
Dustin Brown9ef609b2017-03-15 12:19:37 -0700722 ret = __wlan_hdd_bus_suspend(wow_params);
Dustin Browne70fd972016-11-10 11:17:40 -0800723 cds_ssr_unprotect(__func__);
724
725 return ret;
726}
727#endif
728
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729/**
Rajeev Kumar99805a72016-08-29 13:53:52 -0700730 * __wlan_hdd_bus_suspend_noirq() - handle .suspend_noirq callback
731 *
732 * This function is called by the platform driver to complete the
733 * bus suspend callback when device interrupts are disabled by kernel.
734 * Call HIF and WMA suspend_noirq callbacks to make sure there is no
735 * wake up pending from FW before allowing suspend.
736 *
737 * Return: 0 for success and -EBUSY if FW is requesting wake up
738 */
Jeff Johnson7782cb92016-10-05 14:22:40 -0700739static int __wlan_hdd_bus_suspend_noirq(void)
Rajeev Kumar99805a72016-08-29 13:53:52 -0700740{
Jeff Johnson6bc79d82017-08-28 12:02:36 -0700741 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Rajeev Kumar99805a72016-08-29 13:53:52 -0700742 void *hif_ctx;
Dustin Brown1079f272016-09-01 15:58:23 -0700743 int err;
Rajeev Kumar99805a72016-08-29 13:53:52 -0700744 int status;
745
Dustin Brown1079f272016-09-01 15:58:23 -0700746 err = wlan_hdd_validate_context(hdd_ctx);
Rajeev Kumar99805a72016-08-29 13:53:52 -0700747 if (err) {
748 hdd_err("Invalid HDD context: %d", err);
749 return err;
750 }
751
752 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800753 hdd_debug("Driver Module closed return success");
Rajeev Kumar99805a72016-08-29 13:53:52 -0700754 return 0;
755 }
756
757 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
758 if (NULL == hif_ctx) {
759 err = -EINVAL;
760 goto done;
761 }
762
763 err = hif_bus_suspend_noirq(hif_ctx);
764 if (err)
765 goto done;
766
Mukul Sharma4c60a7e2017-03-06 19:42:18 +0530767 err = pmo_ucfg_psoc_is_target_wake_up_received(
768 hdd_ctx->hdd_psoc);
Rajeev Kumar99805a72016-08-29 13:53:52 -0700769 if (err)
770 goto resume_hif_noirq;
771
Dustin Brownd9322482017-01-09 12:46:03 -0800772 hdd_ctx->suspend_resume_stats.suspends++;
773
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800774 hdd_debug("suspend_noirq done");
Dustin Brown2d228232016-09-22 15:06:19 -0700775 return 0;
Rajeev Kumar99805a72016-08-29 13:53:52 -0700776
777resume_hif_noirq:
778 status = hif_bus_resume_noirq(hif_ctx);
779 QDF_BUG(!status);
780done:
Dustin Brown105d7902016-10-03 16:27:59 -0700781 if (err == -EAGAIN) {
Dustin Brown2d228232016-09-22 15:06:19 -0700782 hdd_err("Firmware attempting wakeup, try again");
Dustin Brown105d7902016-10-03 16:27:59 -0700783 wlan_hdd_inc_suspend_stats(hdd_ctx,
784 SUSPEND_FAIL_INITIAL_WAKEUP);
785 } else {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800786 hdd_err("suspend_noirq failed, status: %d", err);
Dustin Brown105d7902016-10-03 16:27:59 -0700787 }
788
Rajeev Kumar99805a72016-08-29 13:53:52 -0700789 return err;
790}
791
Rajeev Kumar99805a72016-08-29 13:53:52 -0700792int wlan_hdd_bus_suspend_noirq(void)
793{
794 int ret;
795
796 cds_ssr_protect(__func__);
797 ret = __wlan_hdd_bus_suspend_noirq();
798 cds_ssr_unprotect(__func__);
799
800 return ret;
801}
802
803/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 * __wlan_hdd_bus_resume() - handles platform resume
805 *
806 * Does precondtion validation. Ensures that a subsystem restart isn't in
807 * progress. Ensures that no load or unload is in progress. Ensures that
808 * it has valid pointers for the required contexts.
809 * Calls into hif to resume the bus opperation.
810 * Calls into wma to handshake with firmware and notify it that the bus is up.
811 * Calls into ol_txrx for symetry.
812 * Failures are treated as catastrophic.
813 *
814 * return: error code or 0 for success
815 */
816static int __wlan_hdd_bus_resume(void)
817{
Jeff Johnson6bc79d82017-08-28 12:02:36 -0700818 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
SaidiReddy Yenugad8323662016-07-20 15:45:34 +0530819 void *hif_ctx;
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700820 int status;
821 QDF_STATUS qdf_status;
Dustin Brown7ff24dd2017-05-10 15:49:59 -0700822 void *dp_soc;
823 void *dp_pdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800824
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700825 if (cds_is_driver_recovering())
826 return 0;
827
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800828 hdd_debug("starting bus resume");
Dustin Brown562b9672016-12-22 15:25:33 -0800829
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700830 status = wlan_hdd_validate_context(hdd_ctx);
Dustin Brown562b9672016-12-22 15:25:33 -0800831 if (status) {
832 hdd_err("Invalid hdd context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 return status;
Dustin Brown562b9672016-12-22 15:25:33 -0800834 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835
Arun Khandavallifae92942016-08-01 13:31:08 +0530836 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800837 hdd_debug("Driver Module closed; return success");
Arun Khandavallifae92942016-08-01 13:31:08 +0530838 return 0;
839 }
840
SaidiReddy Yenugad8323662016-07-20 15:45:34 +0530841 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
Dustin Brown562b9672016-12-22 15:25:33 -0800842 if (NULL == hif_ctx) {
843 hdd_err("Failed to get hif context");
SaidiReddy Yenugad8323662016-07-20 15:45:34 +0530844 return -EINVAL;
Dustin Brown562b9672016-12-22 15:25:33 -0800845 }
SaidiReddy Yenugad8323662016-07-20 15:45:34 +0530846
Komal Seelamc12e6752016-02-02 18:17:13 +0530847 status = hif_bus_resume(hif_ctx);
Dustin Brown562b9672016-12-22 15:25:33 -0800848 if (status) {
849 hdd_err("Failed hif bus resume");
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700850 goto out;
Dustin Brown562b9672016-12-22 15:25:33 -0800851 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800852
Mukul Sharma4c60a7e2017-03-06 19:42:18 +0530853 qdf_status = pmo_ucfg_psoc_bus_resume_req(hdd_ctx->hdd_psoc,
854 QDF_SYSTEM_SUSPEND);
855 status = qdf_status_to_os_return(qdf_status);
Dustin Brown562b9672016-12-22 15:25:33 -0800856 if (status) {
857 hdd_err("Failed wma bus resume");
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700858 goto out;
Dustin Brown562b9672016-12-22 15:25:33 -0800859 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860
Dustin Brown7ff24dd2017-05-10 15:49:59 -0700861 dp_soc = cds_get_context(QDF_MODULE_ID_SOC);
862 dp_pdev = cds_get_context(QDF_MODULE_ID_TXRX);
863 qdf_status = cdp_bus_resume(dp_soc, dp_pdev);
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700864 status = qdf_status_to_os_return(qdf_status);
Dustin Brown562b9672016-12-22 15:25:33 -0800865 if (status) {
866 hdd_err("Failed cdp bus resume");
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700867 goto out;
Dustin Brown562b9672016-12-22 15:25:33 -0800868 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800869
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800870 hdd_debug("bus resume succeeded");
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700871 return 0;
872
873out:
Hanumanth Reddy Pothula2a8a7402017-07-03 14:06:11 +0530874 if (cds_is_driver_recovering() || cds_is_driver_in_bad_state())
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700875 return 0;
876
877 QDF_BUG(false);
878
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 return status;
880}
881
Rajeev Kumara78a0a42016-07-13 19:28:20 -0700882int wlan_hdd_bus_resume(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883{
884 int ret;
885
886 cds_ssr_protect(__func__);
887 ret = __wlan_hdd_bus_resume();
888 cds_ssr_unprotect(__func__);
889
890 return ret;
891}
892
Mohit Khannafa99aea2016-05-12 21:43:13 -0700893/**
Rajeev Kumar99805a72016-08-29 13:53:52 -0700894 * __wlan_hdd_bus_resume_noirq(): handle bus resume no irq
895 *
896 * This function is called by the platform driver to do bus
897 * resume no IRQ before calling resume callback. Call WMA and HIF
898 * layers to complete the resume_noirq.
899 *
900 * Return: 0 for success and negative error code for failure
901 */
Jeff Johnson7782cb92016-10-05 14:22:40 -0700902static int __wlan_hdd_bus_resume_noirq(void)
Rajeev Kumar99805a72016-08-29 13:53:52 -0700903{
Jeff Johnson6bc79d82017-08-28 12:02:36 -0700904 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Rajeev Kumar99805a72016-08-29 13:53:52 -0700905 void *hif_ctx;
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700906 int status;
Mukul Sharma4c60a7e2017-03-06 19:42:18 +0530907 QDF_STATUS qdf_status;
Rajeev Kumar99805a72016-08-29 13:53:52 -0700908
Prashanth Bhatta697dd0c2016-10-20 18:42:41 -0700909 if (cds_is_driver_recovering())
910 return 0;
911
912 status = wlan_hdd_validate_context(hdd_ctx);
Rajeev Kumar99805a72016-08-29 13:53:52 -0700913 if (status) {
914 hdd_err("Invalid HDD context: %d", status);
915 return status;
916 }
917
918 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800919 hdd_debug("Driver Module closed return success");
Rajeev Kumar99805a72016-08-29 13:53:52 -0700920 return 0;
921 }
922
923 hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
924 if (NULL == hif_ctx)
925 return -EINVAL;
926
Mukul Sharma4c60a7e2017-03-06 19:42:18 +0530927 qdf_status = pmo_ucfg_psoc_clear_target_wake_up(hdd_ctx->hdd_psoc);
928 QDF_BUG(!qdf_status);
Rajeev Kumar99805a72016-08-29 13:53:52 -0700929
930 status = hif_bus_resume_noirq(hif_ctx);
931 QDF_BUG(!status);
932
Srinivas Girigowda852c2542017-03-06 16:18:21 -0800933 hdd_debug("resume_noirq done");
Rajeev Kumar99805a72016-08-29 13:53:52 -0700934 return status;
935}
936
Rajeev Kumar99805a72016-08-29 13:53:52 -0700937int wlan_hdd_bus_resume_noirq(void)
938{
939 int ret;
940
941 cds_ssr_protect(__func__);
942 ret = __wlan_hdd_bus_resume_noirq();
943 cds_ssr_unprotect(__func__);
944
945 return ret;
946}
947
948/**
Mohit Khannafa99aea2016-05-12 21:43:13 -0700949 * wlan_hdd_bus_reset_resume() - resume wlan bus after reset
950 *
951 * This function is called to tell the driver that the device has been resumed
952 * and it has also been reset. The driver should redo any necessary
953 * initialization. It is mainly used by the USB bus
954 *
955 * Return: int 0 for success, non zero for failure
956 */
957static int wlan_hdd_bus_reset_resume(void)
958{
959 int ret;
Anurag Chouhance6a4052016-09-14 18:20:42 +0530960 struct hif_opaque_softc *scn = NULL;
961
962 scn = cds_get_context(QDF_MODULE_ID_HIF);
963 if (!scn) {
964 hdd_err("Failed to get HIF context");
965 return -EFAULT;
966 }
Mohit Khannafa99aea2016-05-12 21:43:13 -0700967
968 cds_ssr_protect(__func__);
Anurag Chouhance6a4052016-09-14 18:20:42 +0530969 ret = hif_bus_reset_resume(scn);
Mohit Khannafa99aea2016-05-12 21:43:13 -0700970 cds_ssr_unprotect(__func__);
971 return ret;
972}
973
Houston Hoffmane8937082015-11-10 16:49:12 -0800974#ifdef FEATURE_RUNTIME_PM
Houston Hoffmane8937082015-11-10 16:49:12 -0800975/**
Sravan Kumar Kairam27296782017-04-21 22:04:18 +0530976 * hdd_pld_runtime_suspend_cb() - Runtime suspend callback from PMO
977 *
978 * Return: 0 on success or error value otherwise
979 */
980static int hdd_pld_runtime_suspend_cb(void)
981{
982 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
983
984 if (!qdf_dev) {
985 hdd_err("Invalid context");
986 return -EINVAL;
987 }
988
989 return pld_auto_suspend(qdf_dev->dev);
990}
991
992/**
Houston Hoffmane8937082015-11-10 16:49:12 -0800993 * __wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend
994 *
995 * Each layer is responsible for its own suspend actions. wma_runtime_suspend
996 * takes care of the parts of the 802.11 suspend that we want to do for runtime
997 * suspend.
998 *
999 * Return: 0 or errno
1000 */
Yuanyuan Liu13738502016-04-06 17:41:37 -07001001static int __wlan_hdd_runtime_suspend(struct device *dev)
Houston Hoffmane8937082015-11-10 16:49:12 -08001002{
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301003 int err;
1004 QDF_STATUS status;
Jeff Johnson6bc79d82017-08-28 12:02:36 -07001005 struct hdd_context *hdd_ctx;
Houston Hoffmane8937082015-11-10 16:49:12 -08001006
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301007 hdd_debug("Starting runtime suspend");
Houston Hoffmane8937082015-11-10 16:49:12 -08001008
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301009 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1010 err = wlan_hdd_validate_context(hdd_ctx);
1011 if (err)
1012 return err;
Houston Hoffmane8937082015-11-10 16:49:12 -08001013
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301014 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1015 hdd_debug("Driver module closed skipping runtime suspend");
1016 return 0;
1017 }
Houston Hoffmane8937082015-11-10 16:49:12 -08001018
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301019 if (ucfg_scan_get_pdev_status(hdd_ctx->hdd_pdev) !=
1020 SCAN_NOT_IN_PROGRESS) {
1021 hdd_debug("Scan in progress, ignore runtime suspend");
1022 return -EBUSY;
1023 }
Yue Ma1e11d792016-02-26 18:58:44 -08001024
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301025 status = pmo_ucfg_psoc_bus_runtime_suspend(hdd_ctx->hdd_psoc,
1026 hdd_pld_runtime_suspend_cb);
1027 err = qdf_status_to_os_return(status);
Houston Hoffmane8937082015-11-10 16:49:12 -08001028
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301029 hdd_debug("Runtime suspend done result: %d", err);
Houston Hoffmane8937082015-11-10 16:49:12 -08001030
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301031 return err;
Houston Hoffmane8937082015-11-10 16:49:12 -08001032}
1033
Houston Hoffmane8937082015-11-10 16:49:12 -08001034/**
1035 * wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend
1036 *
1037 * This function is called by the platform driver to suspend the
1038 * wlan bus separately from system suspend
1039 *
1040 * Return: 0 or errno
1041 */
Yuanyuan Liu13738502016-04-06 17:41:37 -07001042static int wlan_hdd_runtime_suspend(struct device *dev)
Houston Hoffmane8937082015-11-10 16:49:12 -08001043{
1044 int ret;
1045
1046 cds_ssr_protect(__func__);
Yuanyuan Liu13738502016-04-06 17:41:37 -07001047 ret = __wlan_hdd_runtime_suspend(dev);
Houston Hoffmane8937082015-11-10 16:49:12 -08001048 cds_ssr_unprotect(__func__);
1049
1050 return ret;
1051}
1052
1053/**
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301054 * hdd_pld_runtime_resume_cb() - Runtime resume callback from PMO
1055 *
1056 * Return: 0 on success or error value otherwise
1057 */
1058static int hdd_pld_runtime_resume_cb(void)
1059{
1060 qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1061
1062 if (!qdf_dev) {
1063 hdd_err("Invalid context");
1064 return -EINVAL;
1065 }
1066
1067 return pld_auto_resume(qdf_dev->dev);
1068}
1069
1070/**
Houston Hoffmane8937082015-11-10 16:49:12 -08001071 * __wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend
1072 *
1073 * Sets the runtime pm state and coordinates resume between hif wma and
1074 * ol_txrx.
1075 *
1076 * Return: success since failure is a bug
1077 */
Yuanyuan Liu13738502016-04-06 17:41:37 -07001078static int __wlan_hdd_runtime_resume(struct device *dev)
Houston Hoffmane8937082015-11-10 16:49:12 -08001079{
Jeff Johnson6bc79d82017-08-28 12:02:36 -07001080 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301081 QDF_STATUS status;
Komal Seelamc12e6752016-02-02 18:17:13 +05301082
Sravan Kumar Kairam27296782017-04-21 22:04:18 +05301083 hdd_debug("Starting runtime resume");
1084
1085 if (wlan_hdd_validate_context(hdd_ctx))
1086 return 0;
1087
1088 if (hdd_ctx->driver_status != DRIVER_MODULES_ENABLED) {
1089 hdd_debug("Driver module closed skipping runtime resume");
1090 return 0;
1091 }
1092
1093 status = pmo_ucfg_psoc_bus_runtime_resume(hdd_ctx->hdd_psoc,
1094 hdd_pld_runtime_resume_cb);
1095 if (status != QDF_STATUS_SUCCESS)
1096 hdd_err("PMO Runtime resume failed: %d", status);
1097
1098 hdd_debug("Runtime resume done");
1099
Houston Hoffmane8937082015-11-10 16:49:12 -08001100 return 0;
1101}
1102
1103/**
1104 * wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend
1105 *
1106 * This function is called by the platform driver to resume the
1107 * wlan bus separately from system suspend
1108 *
1109 * Return: success since failure is a bug
1110 */
Yuanyuan Liu13738502016-04-06 17:41:37 -07001111static int wlan_hdd_runtime_resume(struct device *dev)
Houston Hoffmane8937082015-11-10 16:49:12 -08001112{
1113 int ret;
1114
1115 cds_ssr_protect(__func__);
Yuanyuan Liu13738502016-04-06 17:41:37 -07001116 ret = __wlan_hdd_runtime_resume(dev);
Houston Hoffmane8937082015-11-10 16:49:12 -08001117 cds_ssr_unprotect(__func__);
1118
1119 return ret;
1120}
1121#endif
1122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001123/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001124 * wlan_hdd_pld_probe() - probe function registered to PLD
1125 * @dev: device
1126 * @pld_bus_type: PLD bus type
1127 * @bdev: bus device structure
1128 * @id: bus identifier for shared busses
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 *
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001130 * Return: 0 on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001132static int wlan_hdd_pld_probe(struct device *dev,
1133 enum pld_bus_type pld_bus_type,
1134 void *bdev, void *id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001135{
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001136 enum qdf_bus_type bus_type;
1137
1138 bus_type = to_bus_type(pld_bus_type);
1139 if (bus_type == QDF_BUS_TYPE_NONE) {
1140 hdd_err("Invalid bus type %d->%d",
1141 pld_bus_type, bus_type);
1142 return -EINVAL;
1143 }
1144
1145 return wlan_hdd_probe(dev, bdev, id, bus_type, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146}
1147
1148/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001149 * wlan_hdd_pld_remove() - remove function registered to PLD
1150 * @dev: device
1151 * @pld_bus_type: PLD bus type
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 *
1153 * Return: void
1154 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001155static void wlan_hdd_pld_remove(struct device *dev,
1156 enum pld_bus_type bus_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157{
Yuanyuan Liu13738502016-04-06 17:41:37 -07001158 wlan_hdd_remove(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001159}
1160
1161/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001162 * wlan_hdd_pld_shutdown() - shutdown function registered to PLD
1163 * @dev: device
1164 * @pld_bus_type: PLD bus type
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 *
1166 * Return: void
1167 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001168static void wlan_hdd_pld_shutdown(struct device *dev,
1169 enum pld_bus_type bus_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170{
1171 wlan_hdd_shutdown();
1172}
1173
1174/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001175 * wlan_hdd_pld_reinit() - reinit function registered to PLD
1176 * @dev: device
1177 * @pld_bus_type: PLD bus type
1178 * @bdev: bus device structure
1179 * @id: bus identifier for shared busses
1180 *
1181 * Return: 0 on success
1182 */
1183static int wlan_hdd_pld_reinit(struct device *dev,
1184 enum pld_bus_type pld_bus_type,
1185 void *bdev, void *id)
1186{
1187 enum qdf_bus_type bus_type;
1188
1189 bus_type = to_bus_type(pld_bus_type);
1190 if (bus_type == QDF_BUS_TYPE_NONE) {
1191 hdd_err("Invalid bus type %d->%d",
1192 pld_bus_type, bus_type);
1193 return -EINVAL;
1194 }
1195
1196 return wlan_hdd_probe(dev, bdev, id, bus_type, true);
1197}
1198
1199/**
1200 * wlan_hdd_pld_crash_shutdown() - crash_shutdown function registered to PLD
1201 * @dev: device
1202 * @pld_bus_type: PLD bus type
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001203 *
1204 * Return: void
1205 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001206static void wlan_hdd_pld_crash_shutdown(struct device *dev,
1207 enum pld_bus_type bus_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001208{
1209 wlan_hdd_crash_shutdown();
1210}
1211
1212/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001213 * wlan_hdd_pld_suspend() - suspend function registered to PLD
1214 * @dev: device
1215 * @pld_bus_type: PLD bus type
1216 * @state: PM state
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 *
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001218 * Return: 0 on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001220static int wlan_hdd_pld_suspend(struct device *dev,
Dustin Brown9ef609b2017-03-15 12:19:37 -07001221 enum pld_bus_type bus_type,
1222 pm_message_t state)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001224{
Dustin Brown9ef609b2017-03-15 12:19:37 -07001225 return wlan_hdd_bus_suspend();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226}
1227
1228/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001229 * wlan_hdd_pld_resume() - resume function registered to PLD
1230 * @dev: device
1231 * @pld_bus_type: PLD bus type
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 *
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001233 * Return: 0 on success
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001235static int wlan_hdd_pld_resume(struct device *dev,
1236 enum pld_bus_type bus_type)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237{
1238 return wlan_hdd_bus_resume();
1239}
Houston Hoffmane8937082015-11-10 16:49:12 -08001240
Rajeev Kumar99805a72016-08-29 13:53:52 -07001241
1242/**
1243 * wlan_hdd_pld_suspend_noirq() - handle suspend no irq
1244 * @dev: device
1245 * @pld_bus_type: PLD bus type
1246 *
1247 * Complete the actions started by suspend(). Carry out any
1248 * additional operations required for suspending the device that might be
1249 * racing with its driver's interrupt handler, which is guaranteed not to
1250 * run while suspend_noirq() is being executed. Make sure to resume device
1251 * if FW has sent initial wake up message and expecting APPS to wake up.
1252 *
1253 * Return: 0 on success
1254 */
1255static int wlan_hdd_pld_suspend_noirq(struct device *dev,
1256 enum pld_bus_type bus_type)
1257{
1258 return wlan_hdd_bus_suspend_noirq();
1259}
1260
1261/**
1262 * wlan_hdd_pld_resume_noirq() - handle resume no irq
1263 * @dev: device
1264 * @pld_bus_type: PLD bus type
1265 *
1266 * Prepare for the execution of resume() by carrying out any
1267 * operations required for resuming the device that might be racing with
1268 * its driver's interrupt handler, which is guaranteed not to run while
1269 * resume_noirq() is being executed. Make sure to clear target initial
1270 * wake up request such that next suspend can happen cleanly.
1271 *
1272 * Return: 0 on success
1273 */
1274static int wlan_hdd_pld_resume_noirq(struct device *dev,
1275 enum pld_bus_type bus_type)
1276{
1277 return wlan_hdd_bus_resume_noirq();
1278}
1279
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001280/**
Mohit Khannafa99aea2016-05-12 21:43:13 -07001281 * wlan_hdd_pld_reset_resume() - reset resume function registered to PLD
1282 * @dev: device
1283 * @pld_bus_type: PLD bus type
1284 *
1285 * Return: 0 on success
1286 */
1287static int wlan_hdd_pld_reset_resume(struct device *dev,
1288 enum pld_bus_type bus_type)
1289{
1290 return wlan_hdd_bus_reset_resume();
1291}
1292
1293/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001294 * wlan_hdd_pld_notify_handler() - notify_handler function registered to PLD
1295 * @dev: device
1296 * @pld_bus_type: PLD bus type
1297 * @state: Modem power state
1298 *
1299 * Return: void
1300 */
1301static void wlan_hdd_pld_notify_handler(struct device *dev,
1302 enum pld_bus_type bus_type,
1303 int state)
1304{
1305 wlan_hdd_notify_handler(state);
1306}
1307
Yuanyuan Liu06a342f2017-01-12 16:48:19 -08001308/**
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +05301309 * wlan_hdd_pld_uevent() - update driver status
Yuanyuan Liu06a342f2017-01-12 16:48:19 -08001310 * @dev: device
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +05301311 * @uevent: uevent status
Yuanyuan Liu06a342f2017-01-12 16:48:19 -08001312 *
1313 * Return: void
1314 */
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +05301315static void wlan_hdd_pld_uevent(struct device *dev,
1316 struct pld_uevent_data *uevent)
Yuanyuan Liu06a342f2017-01-12 16:48:19 -08001317{
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +05301318 if (uevent->uevent == PLD_RECOVERY)
1319 cds_set_recovery_in_progress(true);
Nachiket Kukade8003d252017-03-30 15:55:58 +05301320 else if (uevent->uevent == PLD_FW_DOWN)
1321 cds_set_fw_state(CDS_FW_STATE_DOWN);
Yuanyuan Liu06a342f2017-01-12 16:48:19 -08001322}
1323
Houston Hoffmane8937082015-11-10 16:49:12 -08001324#ifdef FEATURE_RUNTIME_PM
1325/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001326 * wlan_hdd_pld_runtime_suspend() - runtime suspend function registered to PLD
1327 * @dev: device
1328 * @pld_bus_type: PLD bus type
Houston Hoffmane8937082015-11-10 16:49:12 -08001329 *
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001330 * Return: 0 on success
Houston Hoffmane8937082015-11-10 16:49:12 -08001331 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001332static int wlan_hdd_pld_runtime_suspend(struct device *dev,
1333 enum pld_bus_type bus_type)
Houston Hoffmane8937082015-11-10 16:49:12 -08001334{
Yuanyuan Liu13738502016-04-06 17:41:37 -07001335 return wlan_hdd_runtime_suspend(dev);
Houston Hoffmane8937082015-11-10 16:49:12 -08001336}
1337
1338/**
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001339 * wlan_hdd_pld_runtime_resume() - runtime resume function registered to PLD
1340 * @dev: device
1341 * @pld_bus_type: PLD bus type
Houston Hoffmane8937082015-11-10 16:49:12 -08001342 *
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001343 * Return: 0 on success
Houston Hoffmane8937082015-11-10 16:49:12 -08001344 */
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001345static int wlan_hdd_pld_runtime_resume(struct device *dev,
1346 enum pld_bus_type bus_type)
Houston Hoffmane8937082015-11-10 16:49:12 -08001347{
Yuanyuan Liu13738502016-04-06 17:41:37 -07001348 return wlan_hdd_runtime_resume(dev);
Houston Hoffmane8937082015-11-10 16:49:12 -08001349}
1350#endif
1351
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001352struct pld_driver_ops wlan_drv_ops = {
1353 .probe = wlan_hdd_pld_probe,
1354 .remove = wlan_hdd_pld_remove,
1355 .shutdown = wlan_hdd_pld_shutdown,
1356 .reinit = wlan_hdd_pld_reinit,
1357 .crash_shutdown = wlan_hdd_pld_crash_shutdown,
1358 .suspend = wlan_hdd_pld_suspend,
1359 .resume = wlan_hdd_pld_resume,
Rajeev Kumar99805a72016-08-29 13:53:52 -07001360 .suspend_noirq = wlan_hdd_pld_suspend_noirq,
1361 .resume_noirq = wlan_hdd_pld_resume_noirq,
Mohit Khannafa99aea2016-05-12 21:43:13 -07001362 .reset_resume = wlan_hdd_pld_reset_resume,
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001363 .modem_status = wlan_hdd_pld_notify_handler,
Anurag Chouhan1ddb9b32017-04-13 13:57:09 +05301364 .uevent = wlan_hdd_pld_uevent,
Houston Hoffmane8937082015-11-10 16:49:12 -08001365#ifdef FEATURE_RUNTIME_PM
Jeff Johnson330292a2016-05-16 16:09:49 -07001366 .runtime_suspend = wlan_hdd_pld_runtime_suspend,
1367 .runtime_resume = wlan_hdd_pld_runtime_resume,
Houston Hoffmane8937082015-11-10 16:49:12 -08001368#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001369};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371int wlan_hdd_register_driver(void)
1372{
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001373 return pld_register_driver(&wlan_drv_ops);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374}
1375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376void wlan_hdd_unregister_driver(void)
1377{
Yuanyuan Liu1d8045c2016-04-06 16:40:49 -07001378 pld_unregister_driver();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379}