blob: f09f1bad5d93b6c7e931a595386d41c41b340cf3 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Prashanth Bhatta9e143052015-12-04 11:56:47 -08002 * Copyright (c) 2015-2016 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
Jeff Johnsonbd561a92016-01-07 18:31:35 -080028/* denote that this file does not allow legacy hddLog */
29#define HDD_DISALLOW_LEGACY_HDDLOG 1
30
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080031#include <linux/platform_device.h>
32#include <linux/pci.h>
33#ifdef HIF_PCI
34#ifdef CONFIG_CNSS
35#include <net/cnss.h>
36#endif /* CONFIG_CNSS */
37#else
38#include <soc/qcom/icnss.h>
39#endif /* HIF_PCI */
40#include "cds_api.h"
Anurag Chouhance0dc992016-02-16 18:18:03 +053041#include "qdf_status.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080042#include "cdf_lock.h"
43#include "cds_sched.h"
44#include "osdep.h"
45#include "hif.h"
Houston Hoffmane8937082015-11-10 16:49:12 -080046#include "htc.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080047#include "epping_main.h"
48#include "wlan_hdd_main.h"
49#include "wlan_hdd_power.h"
50#include "wlan_logging_sock_svc.h"
51#include "wma_api.h"
52#include "wlan_hdd_napi.h"
Chandrasekaran, Manishekar0d814c72015-11-05 10:42:48 +053053#include "cds_concurrency.h"
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080054#include "qwlan_version.h"
Komal Seelamd9106492016-02-15 10:31:44 +053055#include "bmi.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056
57#ifdef MODULE
58#define WLAN_MODULE_NAME module_name(THIS_MODULE)
59#else
60#define WLAN_MODULE_NAME "wlan"
61#endif
62
63#ifdef HIF_PCI
64#ifdef CONFIG_CNSS
65#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \
66 cnss_wlan_register_driver(wlan_drv_ops)
67#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \
68 cnss_wlan_unregister_driver(wlan_drv_ops)
69#else
70#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \
71 pci_register_driver(wlan_drv_ops)
72#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \
73 pci_unregister_driver(wlan_drv_ops)
74#endif /* CONFIG_CNSS */
75#else
76#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \
77 icnss_register_driver(wlan_drv_ops)
78#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \
79 icnss_unregister_driver(wlan_drv_ops)
80#endif /* HIF_PCI */
Prashanth Bhatta9e143052015-12-04 11:56:47 -080081#define DISABLE_KRAIT_IDLE_PS_VAL 1
Prashanth Bhatta5da711e2015-11-30 14:28:52 -080082
83/*
84 * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at
85 * a time, and wait for the completion interrupt to start the next transfer.
86 * During this phase, the KRAIT is entering IDLE/StandAlone(SA) Power Save(PS).
87 * The delay incurred for resuming from IDLE/SA PS is huge during driver load.
88 * So prevent APPS IDLE/SA PS durint driver load for reducing interrupt latency.
89 */
90#ifdef CONFIG_CNSS
91static inline void hdd_request_pm_qos(int val)
92{
93 cnss_request_pm_qos(val);
94}
95
96static inline void hdd_remove_pm_qos(void)
97{
98 cnss_remove_pm_qos();
99}
100#else
101static inline void hdd_request_pm_qos(int val)
102{
103}
104
105static inline void hdd_remove_pm_qos(void)
106{
107}
108#endif
109
110/**
Komal Seelamad5a90d2016-02-16 13:50:03 +0530111 * hdd_set_recovery_in_progress() - API to set recovery in progress
112 * @data: Context
113 * @val: Value to set
114 *
115 * Return: None
116 */
117static void hdd_set_recovery_in_progress(void *data, uint8_t val)
118{
119 cds_set_recovery_in_progress(val);
120}
121
122/**
123 * hdd_is_driver_unloading() - API to query if driver is unloading
124 * @data: Private Data
125 *
126 * Return: True/False
127 */
128static bool hdd_is_driver_unloading(void *data)
129{
130 return cds_is_driver_unloading();
131}
132
133/**
134 * hdd_is_load_or_unload_in_progress() - API to query if driver is
135 * loading/unloading
136 * @data: Private Data
137 *
138 * Return: bool
139 */
140static bool hdd_is_load_or_unload_in_progress(void *data)
141{
142 return cds_is_load_or_unload_in_progress();
143}
144
145/**
146 * hdd_is_recovery_in_prgress() - API to query if recovery in progress
147 * @data: Private Data
148 *
149 * Return: bool
150 */
151static bool hdd_is_recovery_in_prgress(void *data)
152{
153 return cds_is_driver_recovering();
154}
155
156/**
157 * hdd_hif_init_cds_callbacks() - API to initialize HIF callbacks
158 * @data: Private Data
159 * @cbk: callbacks
160 *
161 * HIF should be independent of CDS calls. Pass CDS Callbacks to HIF, HIF will
162 * call the callbacks.
163 *
164 * Return: void
165 */
166static void hdd_hif_init_cds_callbacks(void *data, struct hif_callbacks *cbk)
167{
168 cbk->context = data;
169 cbk->set_recovery_in_progress = hdd_set_recovery_in_progress;
170 cbk->get_monotonic_boottime = cds_get_monotonic_boottime;
171 cbk->is_recovery_in_progress = hdd_is_recovery_in_prgress;
172 cbk->is_load_unload_in_progress = hdd_is_load_or_unload_in_progress;
173 cbk->is_driver_unloading = hdd_is_driver_unloading;
174}
175
176/**
177 * hdd_init_cds_hif_context() - API to set CDS HIF Context
178 * @hif: HIF Context
179 *
180 * Return: success/failure
181 */
182static int hdd_init_cds_hif_context(void *hif)
183{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530184 QDF_STATUS status;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530185
186 status = cds_set_context(CDF_MODULE_ID_HIF, hif);
187
188 if (status)
189 return -ENOENT;
190
191 return 0;
192}
193
194/**
195 * hdd_deinit_cds_hif_context() - API to clear CDS HIF COntext
196 *
197 * Return: None
198 */
199static void hdd_deinit_cds_hif_context(void)
200{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530201 QDF_STATUS status;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530202
203 status = cds_set_context(CDF_MODULE_ID_HIF, NULL);
204
205 if (status)
206 hdd_err("Failed to reset CDS HIF Context");
207
208 return;
209}
210
211/**
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800212 * hdd_hif_open() - HIF open helper
213 * @dev: wlan device structure
214 * @bdev: bus device structure
215 * @bid: bus identifier for shared busses
216 * @bus_type: underlying bus type
217 * @reinit: true if we are reinitializing the driver during recovery phase
218 *
219 * This function brings-up HIF layer during load/recovery phase.
220 *
221 * Return: 0 on success and errno on failure.
222 */
223static int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid,
224 enum ath_hal_bus_type bus_type, bool reinit)
225{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530226 QDF_STATUS status;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800227 int ret = 0;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530228 struct hif_opaque_softc *hif_ctx;
Komal Seelamc12e6752016-02-02 18:17:13 +0530229 cdf_device_t cdf_ctx = cds_get_context(CDF_MODULE_ID_CDF_DEVICE);
Komal Seelamad5a90d2016-02-16 13:50:03 +0530230 struct hif_callbacks cbk;
231 uint32_t mode = cds_get_conparam();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800232
Komal Seelamad5a90d2016-02-16 13:50:03 +0530233 hdd_hif_init_cds_callbacks(dev, &cbk);
234
235 hif_ctx = hif_open(cdf_ctx, mode, bus_type, &cbk);
236 if (!hif_ctx) {
237 hdd_err("hif_open error");
238 return -ENOMEM;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800239 }
240
Komal Seelamad5a90d2016-02-16 13:50:03 +0530241 ret = hdd_init_cds_hif_context(hif_ctx);
242 if (ret) {
243 hdd_err("Failed to set global HIF CDS Context err:%d", ret);
244 goto err_hif_close;
245 }
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800246
247 ret = hdd_napi_create();
248 if (hdd_napi_enabled(HDD_NAPI_ANY)) {
Komal Seelamad5a90d2016-02-16 13:50:03 +0530249 hdd_info("hdd_napi_create returned: %d", ret);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800250 if (ret <= 0) {
251 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;
255 }
256 }
257
258 status = hif_enable(hif_ctx, dev, bdev, bid, bus_type,
259 (reinit == true) ? HIF_ENABLE_TYPE_REINIT :
260 HIF_ENABLE_TYPE_PROBE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530261 if (!QDF_IS_STATUS_SUCCESS(status)) {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800262 hdd_err("hif_enable error = %d, reinit = %d",
263 status, reinit);
264 ret = cdf_status_to_os_return(status);
265 goto err_napi_destroy;
266 }
267
268 return 0;
269
270err_napi_destroy:
271 hdd_napi_destroy(true);
272
273err_hif_close:
Komal Seelamad5a90d2016-02-16 13:50:03 +0530274 hdd_deinit_cds_hif_context();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800275 hif_close(hif_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800276 return ret;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800277}
278
279/**
280 * hdd_hif_close() - HIF close helper
281 * @hif_ctx: HIF context
282 *
283 * Helper function to close HIF
284 */
285static void hdd_hif_close(void *hif_ctx)
286{
287 if (hif_ctx == NULL)
288 return;
289
290 hif_disable(hif_ctx, HIF_DISABLE_TYPE_REMOVE);
291
292 hdd_napi_destroy(true);
293
Komal Seelamad5a90d2016-02-16 13:50:03 +0530294 hdd_deinit_cds_hif_context();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800295 hif_close(hif_ctx);
296}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297
298/**
Komal Seelam48152e12016-02-09 17:50:33 +0530299 * hdd_init_cdf_ctx() - API to initialize global CDF Device structure
300 * @dev: Device Pointer
301 * @bdev: Bus Device pointer
302 *
303 * Return: void
304 */
305void hdd_init_cdf_ctx(struct device *dev, void *bdev)
306{
307 cdf_device_t cdf_dev = cds_get_context(CDF_MODULE_ID_CDF_DEVICE);
308
309 cdf_dev->dev = dev;
310 cdf_dev->drv_hdl = bdev;
311}
312
313/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800314 * wlan_hdd_probe() - handles probe request
315 *
316 * This function is called to probe the wlan driver
317 *
318 * @dev: wlan device structure
319 * @bdev: bus device structure
320 * @bid: bus identifier for shared busses
321 * @bus_type: underlying bus type
322 * @reinit: true if we are reinitiallizing the driver after a subsystem restart
323 *
324 * Return: 0 on successfull probe
325 */
326static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid,
327 enum ath_hal_bus_type bus_type, bool reinit)
328{
329 void *hif_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530330 QDF_STATUS status;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800331 int ret = 0;
Komal Seelamd9106492016-02-15 10:31:44 +0530332 cdf_device_t cdf_dev;
Komal Seelamad5a90d2016-02-16 13:50:03 +0530333 uint32_t mode = cds_get_conparam();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800334
335 pr_info("%s: %sprobing driver v%s\n", WLAN_MODULE_NAME,
336 reinit ? "re-" : "", QWLAN_VERSIONSTR);
337
338 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
339
340 /*
341 * The Krait is going to Idle/Stand Alone Power Save
342 * more aggressively which is resulting in the longer driver load time.
343 * The Fix is to not allow Krait to enter Idle Power Save during driver
344 * load.
345 */
346 hdd_request_pm_qos(DISABLE_KRAIT_IDLE_PS_VAL);
347
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800348 if (reinit) {
349 cds_set_recovery_in_progress(true);
350 } else {
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800351 ret = hdd_init();
352
353 if (ret)
354 goto out;
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800355 cds_set_load_in_progress(true);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800356 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357
Komal Seelamad5a90d2016-02-16 13:50:03 +0530358 if (WLAN_IS_EPPING_ENABLED(mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359 status = epping_open();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530360 if (status != QDF_STATUS_SUCCESS)
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800361 goto err_hdd_deinit;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362 }
363
Komal Seelam48152e12016-02-09 17:50:33 +0530364 hdd_init_cdf_ctx(dev, bdev);
365
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800366 ret = hdd_hif_open(dev, bdev, bid, bus_type, reinit);
367
368 if (ret)
369 goto err_epping_close;
370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
Komal Seelamd9106492016-02-15 10:31:44 +0530372 cdf_dev = cds_get_context(CDF_MODULE_ID_CDF_DEVICE);
373
374 status = ol_cds_init(cdf_dev, hif_ctx);
375
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530376 if (status != QDF_STATUS_SUCCESS) {
Komal Seelamd9106492016-02-15 10:31:44 +0530377 pr_err("%s No Memory to Create BMI Context\n", __func__);
378 goto err_hif_close;
379 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380
381 if (reinit)
382 ret = hdd_wlan_re_init(hif_ctx);
383 else
384 ret = hdd_wlan_startup(dev, hif_ctx);
385
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800386 if (ret)
Komal Seelamd9106492016-02-15 10:31:44 +0530387 goto err_bmi_close;
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800388
Houston Hoffman8eb73ed2015-11-02 21:14:55 -0800389 hif_enable_power_management(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800391 if (reinit) {
392 cds_set_recovery_in_progress(false);
393 } else {
394 cds_set_load_in_progress(false);
395 cds_set_driver_loaded(true);
396 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800398 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
399 hdd_remove_pm_qos();
400
401 return 0;
402
Komal Seelamd9106492016-02-15 10:31:44 +0530403err_bmi_close:
404 ol_cds_free();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800405err_hif_close:
406 hdd_hif_close(hif_ctx);
407err_epping_close:
Komal Seelamad5a90d2016-02-16 13:50:03 +0530408 if (WLAN_IS_EPPING_ENABLED(mode))
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800409 epping_close();
410err_hdd_deinit:
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800411 cds_set_load_in_progress(false);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800412 hdd_deinit();
413out:
414 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DRIVER_INIT);
415 hdd_remove_pm_qos();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416 return ret;
417}
418
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800419#ifdef CONFIG_CNSS
420static inline void hdd_cnss_driver_unloading(void)
421{
422 cnss_set_driver_status(CNSS_LOAD_UNLOAD);
423}
424#else
425static inline void hdd_cnss_driver_unloading(void) { }
426#endif
427
428
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800429/**
430 * wlan_hdd_remove() - wlan_hdd_remove
431 *
432 * This function is called by the platform driver to remove the
433 * driver
434 *
435 * Return: void
436 */
437static void wlan_hdd_remove(void)
438{
439 void *hif_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800440
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800441 pr_info("%s: Removing driver v%s\n", WLAN_MODULE_NAME,
442 QWLAN_VERSIONSTR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800444 /* Wait for recovery to complete */
445 while (cds_is_driver_recovering()) {
446 hdd_alert("Recovery in progress; wait here!!!");
447 msleep(1000);
448 }
449
450 cds_set_driver_loaded(false);
451 cds_set_unload_in_progress(true);
452
Rajeev Kumardbc886e2016-01-19 12:56:04 -0800453 if (!cds_wait_for_external_threads_completion(__func__))
454 hdd_err("External threads are still active attempting driver unload anyway");
455
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800456 hdd_cnss_driver_unloading();
457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
459
Houston Hoffmana0e71062015-11-18 15:51:32 -0800460 hif_disable_power_management(hif_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462 if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463 epping_disable();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800464 epping_close();
465 } else {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 __hdd_wlan_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467 }
468
Komal Seelamd9106492016-02-15 10:31:44 +0530469 ol_cds_free();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800470 hdd_hif_close(hif_ctx);
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800471 hdd_deinit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800473 pr_info("%s: Driver Removed\n", WLAN_MODULE_NAME);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474}
475
476/**
477 * wlan_hdd_shutdown() - wlan_hdd_shutdown
478 *
479 * This is routine is called by platform driver to shutdown the
480 * driver
481 *
482 * Return: void
483 */
484static void wlan_hdd_shutdown(void)
485{
486 void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
487
Rajeev Kumarfec3dbe2016-01-19 15:23:52 -0800488 if (cds_is_load_or_unload_in_progress()) {
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800489 hdd_err("Load/unload in progress, ignore SSR shutdown");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490 return;
491 }
492 /* this is for cases, where shutdown invoked from CNSS */
Prashanth Bhatta9e143052015-12-04 11:56:47 -0800493 cds_set_recovery_in_progress(true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494
Rajeev Kumardbc886e2016-01-19 12:56:04 -0800495 if (!cds_wait_for_external_threads_completion(__func__))
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800496 hdd_err("Host is not ready for SSR, attempting anyway");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497
Yue Macd961442015-10-20 16:15:31 -0700498 if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) {
499 hif_disable_isr(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 hdd_wlan_shutdown();
Yue Macd961442015-10-20 16:15:31 -0700501 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502
Komal Seelamd9106492016-02-15 10:31:44 +0530503 ol_cds_free();
Prashanth Bhatta5da711e2015-11-30 14:28:52 -0800504 hdd_hif_close(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505}
506
507/**
508 * wlan_hdd_crash_shutdown() - wlan_hdd_crash_shutdown
509 *
510 * HDD crash shutdown funtion: This function is called by
511 * platfrom driver's crash shutdown routine
512 *
513 * Return: void
514 */
515void wlan_hdd_crash_shutdown(void)
516{
517 hif_crash_shutdown(cds_get_context(CDF_MODULE_ID_HIF));
518}
519
520/**
521 * wlan_hdd_notify_handler() - wlan_hdd_notify_handler
522 *
523 * This function is called by the platform driver to notify the
524 * COEX
525 *
526 * @state: state
527 *
528 * Return: void
529 */
530void wlan_hdd_notify_handler(int state)
531{
532 if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) {
533 int ret = 0;
534 ret = hdd_wlan_notify_modem_power_state(state);
535 if (ret < 0)
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800536 hdd_err("Fail to send notify");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537 }
538}
539
540/**
541 * __wlan_hdd_bus_suspend() - handles platform supsend
542 * @state: suspend message from the kernel
543 *
544 * Does precondtion validation. Ensures that a subsystem restart isn't in
545 * progress. Ensures that no load or unload is in progress.
546 * Calls ol_txrx_bus_suspend to ensure the layer is ready for a bus suspend.
547 * Calls wma_suspend to configure offloads.
548 * Calls hif_suspend to suspend the bus.
549 *
550 * Return: 0 for success, -EFAULT for null pointers,
551 * -EBUSY or -EAGAIN if another opperation is in progress and
552 * wlan will not be ready to suspend in time.
553 */
554static int __wlan_hdd_bus_suspend(pm_message_t state)
555{
556 void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
Komal Seelamc12e6752016-02-02 18:17:13 +0530557 void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 int err = wlan_hdd_validate_context(hdd_ctx);
559 int status;
560
561 hdd_info("event %d", state.event);
562
563 if (err)
564 goto done;
565
566 err = cdf_status_to_os_return(
567 ol_txrx_bus_suspend());
568 if (err)
569 goto done;
570
571 err = wma_bus_suspend();
572 if (err)
573 goto resume_oltxrx;
574
Komal Seelamc12e6752016-02-02 18:17:13 +0530575 err = hif_bus_suspend(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 if (err)
577 goto resume_wma;
578
579 hdd_info("suspend done, status = %d", err);
580 return err;
581
582resume_wma:
583 status = wma_bus_resume();
584 CDF_BUG(!status);
585resume_oltxrx:
586 status = ol_txrx_bus_resume();
587 CDF_BUG(!status);
588done:
589 hdd_err("suspend done, status = %d", err);
590 return err;
591}
592
593/**
594 * wlan_hdd_bus_suspend() - suspend the wlan bus
595 *
596 * This function is called by the platform driver to suspend the
597 * wlan bus
598 *
599 * @state: state
600 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530601 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800602 */
603int wlan_hdd_bus_suspend(pm_message_t state)
604{
605 int ret;
606
607 cds_ssr_protect(__func__);
608 ret = __wlan_hdd_bus_suspend(state);
609 cds_ssr_unprotect(__func__);
610
611 return ret;
612}
613
614/**
615 * __wlan_hdd_bus_resume() - handles platform resume
616 *
617 * Does precondtion validation. Ensures that a subsystem restart isn't in
618 * progress. Ensures that no load or unload is in progress. Ensures that
619 * it has valid pointers for the required contexts.
620 * Calls into hif to resume the bus opperation.
621 * Calls into wma to handshake with firmware and notify it that the bus is up.
622 * Calls into ol_txrx for symetry.
623 * Failures are treated as catastrophic.
624 *
625 * return: error code or 0 for success
626 */
627static int __wlan_hdd_bus_resume(void)
628{
629 void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
Komal Seelamc12e6752016-02-02 18:17:13 +0530630 void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631 int status = wlan_hdd_validate_context(hdd_ctx);
632
633 if (0 != status) {
Jeff Johnsonbd561a92016-01-07 18:31:35 -0800634 hdd_err("HDD context is not valid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 return status;
636 }
637
Komal Seelamc12e6752016-02-02 18:17:13 +0530638 status = hif_bus_resume(hif_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 CDF_BUG(!status);
640
641 status = wma_bus_resume();
642 CDF_BUG(!status);
643
644 status = ol_txrx_bus_resume();
645 CDF_BUG(!status);
646
647 hdd_info("resume done");
648 return status;
649}
650
651/**
652 * wlan_hdd_bus_resume(): wake up the bus
653 *
654 * This function is called by the platform driver to resume wlan
655 * bus
656 *
657 * Return: void
658 */
659static int wlan_hdd_bus_resume(void)
660{
661 int ret;
662
663 cds_ssr_protect(__func__);
664 ret = __wlan_hdd_bus_resume();
665 cds_ssr_unprotect(__func__);
666
667 return ret;
668}
669
Houston Hoffmane8937082015-11-10 16:49:12 -0800670#ifdef FEATURE_RUNTIME_PM
Houston Hoffmane8937082015-11-10 16:49:12 -0800671/**
672 * __wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend
673 *
674 * Each layer is responsible for its own suspend actions. wma_runtime_suspend
675 * takes care of the parts of the 802.11 suspend that we want to do for runtime
676 * suspend.
677 *
678 * Return: 0 or errno
679 */
680static int __wlan_hdd_runtime_suspend(void)
681{
682 void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
Komal Seelamc12e6752016-02-02 18:17:13 +0530683 void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
Houston Hoffmane8937082015-11-10 16:49:12 -0800684 int status = wlan_hdd_validate_context(hdd_ctx);
685
Houston Hoffman267723f2016-01-05 20:08:56 -0800686 if (0 != status)
687 goto process_failure;
Houston Hoffmane8937082015-11-10 16:49:12 -0800688
Komal Seelamc12e6752016-02-02 18:17:13 +0530689 status = hif_pre_runtime_suspend(hif_ctx);
Houston Hoffman267723f2016-01-05 20:08:56 -0800690 if (status)
691 goto process_failure;
Houston Hoffmane8937082015-11-10 16:49:12 -0800692
Houston Hoffmane8937082015-11-10 16:49:12 -0800693 status = htc_runtime_suspend();
694 if (status)
Houston Hoffman267723f2016-01-05 20:08:56 -0800695 goto process_failure;
Houston Hoffmane8937082015-11-10 16:49:12 -0800696
697 status = wma_runtime_suspend();
698 if (status)
699 goto resume_htc;
700
Komal Seelamc12e6752016-02-02 18:17:13 +0530701 status = hif_runtime_suspend(hif_ctx);
Houston Hoffmane8937082015-11-10 16:49:12 -0800702 if (status)
703 goto resume_wma;
704
705 status = cnss_auto_suspend();
706 if (status)
707 goto resume_hif;
708
Komal Seelamc12e6752016-02-02 18:17:13 +0530709 hif_process_runtime_suspend_success(hif_ctx);
Houston Hoffmane8937082015-11-10 16:49:12 -0800710 return status;
711
712resume_hif:
Komal Seelamc12e6752016-02-02 18:17:13 +0530713 CDF_BUG(!hif_runtime_resume(hif_ctx));
Houston Hoffmane8937082015-11-10 16:49:12 -0800714resume_wma:
715 CDF_BUG(!wma_runtime_resume());
716resume_htc:
717 CDF_BUG(!htc_runtime_resume());
Houston Hoffman267723f2016-01-05 20:08:56 -0800718process_failure:
Komal Seelamc12e6752016-02-02 18:17:13 +0530719 hif_process_runtime_suspend_failure(hif_ctx);
Houston Hoffmane8937082015-11-10 16:49:12 -0800720 return status;
721}
722
723
724/**
725 * wlan_hdd_runtime_suspend() - suspend the wlan bus without apps suspend
726 *
727 * This function is called by the platform driver to suspend the
728 * wlan bus separately from system suspend
729 *
730 * Return: 0 or errno
731 */
732static int wlan_hdd_runtime_suspend(void)
733{
734 int ret;
735
736 cds_ssr_protect(__func__);
737 ret = __wlan_hdd_runtime_suspend();
738 cds_ssr_unprotect(__func__);
739
740 return ret;
741}
742
743/**
744 * __wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend
745 *
746 * Sets the runtime pm state and coordinates resume between hif wma and
747 * ol_txrx.
748 *
749 * Return: success since failure is a bug
750 */
751static int __wlan_hdd_runtime_resume(void)
752{
Komal Seelamc12e6752016-02-02 18:17:13 +0530753 void *hif_ctx = cds_get_context(CDF_MODULE_ID_HIF);
754
755 hif_pre_runtime_resume(hif_ctx);
Houston Hoffmane8937082015-11-10 16:49:12 -0800756 CDF_BUG(!cnss_auto_resume());
Komal Seelamc12e6752016-02-02 18:17:13 +0530757 CDF_BUG(!hif_runtime_resume(hif_ctx));
Houston Hoffmane8937082015-11-10 16:49:12 -0800758 CDF_BUG(!wma_runtime_resume());
759 CDF_BUG(!htc_runtime_resume());
Komal Seelamc12e6752016-02-02 18:17:13 +0530760 hif_process_runtime_resume_success(hif_ctx);
Houston Hoffmane8937082015-11-10 16:49:12 -0800761 return 0;
762}
763
764/**
765 * wlan_hdd_runtime_resume() - resume the wlan bus from runtime suspend
766 *
767 * This function is called by the platform driver to resume the
768 * wlan bus separately from system suspend
769 *
770 * Return: success since failure is a bug
771 */
772static int wlan_hdd_runtime_resume(void)
773{
774 int ret;
775
776 cds_ssr_protect(__func__);
777 ret = __wlan_hdd_runtime_resume();
778 cds_ssr_unprotect(__func__);
779
780 return ret;
781}
782#endif
783
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784#ifdef HIF_PCI
785/**
786 * wlan_hdd_pci_probe() - probe callback for pci platform driver
787 * @pdev: bus dev
788 *
789 * Return: void
790 */
791static int wlan_hdd_pci_probe(struct pci_dev *pdev,
792 const struct pci_device_id *id)
793{
794 return wlan_hdd_probe(&pdev->dev, pdev, (void *)id,
795 HAL_BUS_TYPE_PCI, false);
796}
797
798/**
799 * wlan_hdd_pci_remove() - wlan_hdd_pci_remove
800 *
801 * Return: void
802 */
803void wlan_hdd_pci_remove(struct pci_dev *pdev)
804{
805 wlan_hdd_remove();
806}
807
808/**
809 * wlan_hdd_pci_reinit() - wlan_hdd_pci_reinit
810 * @pdev: bus dev
811 * @id: bus id
812 *
813 * Return: int
814 */
815int wlan_hdd_pci_reinit(struct pci_dev *pdev,
816 const struct pci_device_id *id)
817{
818 return wlan_hdd_probe(&pdev->dev, pdev, id,
819 HAL_BUS_TYPE_PCI, true);
820}
821
822/**
823 * wlan_hdd_pci_shutdown() - wlan_hdd_pci_shutdown
824 * @pdev: pdev
825 *
826 * Return: void
827 */
828void wlan_hdd_pci_shutdown(struct pci_dev *pdev)
829{
830 wlan_hdd_shutdown();
831}
832
833/**
834 * wlan_hdd_pci_crash_shutdown() - wlan_hdd_pci_crash_shutdown
835 * @pdev: pdev
836 *
837 * Return: void
838 */
839void wlan_hdd_pci_crash_shutdown(struct pci_dev *pdev)
840{
841 wlan_hdd_crash_shutdown();
842}
843
844/**
845 * wlan_hdd_pci_notify_handler() - wlan_hdd_pci_notify_handler
846 * @pdev: pdev
847 * @state: state
848 *
849 * Return: void
850 */
851void wlan_hdd_pci_notify_handler(struct pci_dev *pdev, int state)
852{
853 wlan_hdd_notify_handler(state);
854}
855
856/**
857 * wlan_hdd_pci_suspend() - wlan_hdd_pci_suspend
858 * @pdev: pdev
859 * @state: state
860 *
861 * Return: void
862 */
863static int wlan_hdd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
864{
865 return wlan_hdd_bus_suspend(state);
866}
867
868/**
869 * wlan_hdd_pci_resume() - wlan_hdd_pci_resume
870 * @pdev: pdev
871 *
872 * Return: void
873 */
874static int wlan_hdd_pci_resume(struct pci_dev *pdev)
875{
876 return wlan_hdd_bus_resume();
877}
Houston Hoffmane8937082015-11-10 16:49:12 -0800878
879#ifdef FEATURE_RUNTIME_PM
880/**
881 * wlan_hdd_pci_runtime_suspend() - wlan_hdd_pci_suspend
882 * @pdev: pdev
883 * @state: state
884 *
885 * Return: success or errno
886 */
887static int wlan_hdd_pci_runtime_suspend(struct pci_dev *pdev)
888{
889 return wlan_hdd_runtime_suspend();
890}
891
892/**
893 * wlan_hdd_pci_runtime_resume() - runtime resume callback to register with pci
894 * @pdev: pci device id
895 *
896 * Return: success or errno
897 */
898static int wlan_hdd_pci_runtime_resume(struct pci_dev *pdev)
899{
900 return wlan_hdd_runtime_resume();
901}
902#endif
903
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904#else
905/**
906 * wlan_hdd_snoc_probe() - wlan_hdd_snoc_probe
907 * @dev: dev
908 *
909 * Return: int
910 */
911static int wlan_hdd_snoc_probe(struct device *dev)
912{
913 return wlan_hdd_probe(dev, NULL, NULL, HAL_BUS_TYPE_SNOC, false);
914}
915
916/**
917 * wlan_hdd_snoc_remove() - wlan_hdd_snoc_remove
918 * @dev: dev
919 *
920 * Return: void
921 */
922void wlan_hdd_snoc_remove(struct device *dev)
923{
924 wlan_hdd_remove();
925}
926
927/**
928 * wlan_hdd_snoc_shutdown() - wlan_hdd_snoc_shutdown
929 * @dev: dev
930 *
931 * Return: void
932 */
933void wlan_hdd_snoc_shutdown(struct device *dev)
934{
935 wlan_hdd_shutdown();
936}
937
938/**
939 * wlan_hdd_snoc_reinit() - wlan_hdd_snoc_reinit
940 * @dev: dev
941 *
942 * Return: int
943 */
944int wlan_hdd_snoc_reinit(struct device *dev)
945{
946 return wlan_hdd_probe(dev, NULL, NULL, HAL_BUS_TYPE_SNOC, true);
947}
948
949/**
950 * wlan_hdd_snoc_crash_shutdown() - wlan_hdd_snoc_crash_shutdown
951 * @dev: dev
952 *
953 * Return: void
954 */
955void wlan_hdd_snoc_crash_shutdown(void *pdev)
956{
957 wlan_hdd_crash_shutdown();
958}
959
960/**
961 * wlan_hdd_snoc_suspend() - wlan_hdd_snoc_suspend
962 * @dev: dev
963 * @state: state
964 *
965 * Return: int
966 */
967static int wlan_hdd_snoc_suspend(struct device *dev, pm_message_t state)
968{
969 return wlan_hdd_bus_suspend(state);
970}
971
972/**
973 * wlan_hdd_snoc_resume() - wlan_hdd_snoc_resume
974 * @dev: dev
975 *
976 * Return: int
977 */
978static int wlan_hdd_snoc_resume(struct device *dev)
979{
980 return wlan_hdd_bus_resume();
981}
982#endif /* HIF_PCI */
983
984#ifdef HIF_PCI
985static struct pci_device_id wlan_hdd_pci_id_table[] = {
986 { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
987 { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
988 { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
989 { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
990 { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
991 { 0 }
992};
993
994#ifdef CONFIG_CNSS
Houston Hoffmane8937082015-11-10 16:49:12 -0800995
996#ifdef FEATURE_RUNTIME_PM
997struct cnss_wlan_runtime_ops runtime_pm_ops = {
998 .runtime_suspend = wlan_hdd_pci_runtime_suspend,
999 .runtime_resume = wlan_hdd_pci_runtime_resume,
1000};
1001#endif
1002
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001003struct cnss_wlan_driver wlan_drv_ops = {
1004 .name = "wlan_hdd_pci",
1005 .id_table = wlan_hdd_pci_id_table,
1006 .probe = wlan_hdd_pci_probe,
1007 .remove = wlan_hdd_pci_remove,
1008 .reinit = wlan_hdd_pci_reinit,
1009 .shutdown = wlan_hdd_pci_shutdown,
1010 .crash_shutdown = wlan_hdd_pci_crash_shutdown,
1011 .modem_status = wlan_hdd_pci_notify_handler,
1012#ifdef ATH_BUS_PM
1013 .suspend = wlan_hdd_pci_suspend,
1014 .resume = wlan_hdd_pci_resume,
1015#endif /* ATH_BUS_PM */
Houston Hoffmane8937082015-11-10 16:49:12 -08001016#ifdef FEATURE_RUNTIME_PM
1017 .runtime_ops = &runtime_pm_ops,
1018#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019};
1020#else
1021MODULE_DEVICE_TABLE(pci, wlan_hdd_pci_id_table);
1022struct pci_driver wlan_drv_ops = {
1023 .name = "wlan_hdd_pci",
1024 .id_table = wlan_hdd_pci_id_table,
1025 .probe = wlan_hdd_pci_probe,
1026 .remove = wlan_hdd_pci_remove,
1027#ifdef ATH_BUS_PM
1028 .suspend = wlan_hdd_pci_suspend,
1029 .resume = wlan_hdd_pci_resume,
1030#endif /* ATH_BUS_PM */
Houston Hoffmane8937082015-11-10 16:49:12 -08001031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001032};
1033#endif /* CONFIG_CNSS */
1034#else
1035struct icnss_driver_ops wlan_drv_ops = {
1036 .name = "wlan_hdd_drv",
1037 .probe = wlan_hdd_snoc_probe,
1038 .remove = wlan_hdd_snoc_remove,
1039 .shutdown = wlan_hdd_snoc_shutdown,
1040 .reinit = wlan_hdd_snoc_reinit,
1041 .crash_shutdown = wlan_hdd_snoc_crash_shutdown,
1042 .suspend = wlan_hdd_snoc_suspend,
1043 .resume = wlan_hdd_snoc_resume,
1044};
1045#endif
1046
1047/**
1048 * wlan_hdd_register_driver() - wlan_hdd_register_driver
1049 *
1050 * Return: int
1051 */
1052int wlan_hdd_register_driver(void)
1053{
1054 return WLAN_HDD_REGISTER_DRIVER(&wlan_drv_ops);
1055}
1056
1057/**
1058 * wlan_hdd_unregister_driver() - wlan_hdd_unregister_driver
1059 *
1060 * Return: void
1061 */
1062void wlan_hdd_unregister_driver(void)
1063{
1064 WLAN_HDD_UNREGISTER_DRIVER(&wlan_drv_ops);
1065}