blob: bab578225e3a051c490b0e146bf06e250c1e4c44 [file] [log] [blame]
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -08001/*
Houston Hoffmancceec342015-11-11 11:37:20 -08002 * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -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 <osdep.h>
29#include "a_types.h"
30#include "athdefs.h"
31#include "osapi_linux.h"
32#include "targcfg.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053033#include "qdf_lock.h"
34#include "qdf_status.h"
35#include "qdf_status.h"
36#include <qdf_atomic.h> /* qdf_atomic_read */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080037#include <targaddrs.h>
38#include <bmi_msg.h>
39#include "hif_io32.h"
40#include <hif.h>
41#include <htc_services.h>
42#include "regtable.h"
43#define ATH_MODULE_NAME hif
44#include <a_debug.h>
45#include "hif_main.h"
46#include "hif_hw_version.h"
47#include "ce_api.h"
48#include "ce_tasklet.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053049#include "qdf_trace.h"
50#include "qdf_status.h"
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080051#ifdef CONFIG_CNSS
52#include <net/cnss.h>
53#endif
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080054#include "epping_main.h"
55#include "hif_debug.h"
56#include "mp_dev.h"
Houston Hoffmanbc693492016-03-14 21:11:41 -070057#include "platform_icnss.h"
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080058
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080059#define AGC_DUMP 1
60#define CHANINFO_DUMP 2
61#define BB_WATCHDOG_DUMP 3
62#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
63#define PCIE_ACCESS_DUMP 4
64#endif
65
Komal Seelam5584a7c2016-02-24 19:22:48 +053066void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080067{
Komal Seelam644263d2016-02-22 20:45:49 +053068 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080069 switch (cmd_id) {
70 case AGC_DUMP:
71 if (start)
72 priv_start_agc(scn);
73 else
74 priv_dump_agc(scn);
75 break;
76
77 case CHANINFO_DUMP:
78 if (start)
79 priv_start_cap_chaninfo(scn);
80 else
81 priv_dump_chaninfo(scn);
82 break;
83
84 case BB_WATCHDOG_DUMP:
85 priv_dump_bbwatchdog(scn);
86 break;
87
88#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
89 case PCIE_ACCESS_DUMP:
90 hif_target_dump_access_log();
91 break;
92#endif
93 default:
94 HIF_ERROR("%s: Invalid htc dump command", __func__);
95 break;
96 }
97}
98
99/**
100 * hif_shut_down_device() - hif_shut_down_device
101 *
102 * SThis fucntion shuts down the device
103 *
Komal Seelam5584a7c2016-02-24 19:22:48 +0530104 * @scn: hif_opaque_softc
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800105 *
106 * Return: void
107 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530108void hif_shut_down_device(struct hif_opaque_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800109{
Komal Seelam02cf2f82016-02-22 20:44:25 +0530110 hif_stop(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800111}
112
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800113/**
114 * hif_get_target_id(): hif_get_target_id
115 *
116 * Return the virtual memory base address to the caller
117 *
Komal Seelam644263d2016-02-22 20:45:49 +0530118 * @scn: hif_softc
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800119 *
120 * Return: A_target_id_t
121 */
Komal Seelam644263d2016-02-22 20:45:49 +0530122A_target_id_t hif_get_target_id(struct hif_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800123{
124 return scn->mem;
125}
126
Houston Hoffman0dad5092015-09-28 16:25:51 -0700127static inline void hif_fw_event_handler(struct HIF_CE_state *hif_state)
128{
129 struct hif_msg_callbacks *msg_callbacks =
130 &hif_state->msg_callbacks_current;
131
132 if (!msg_callbacks->fwEventHandler)
133 return;
134
135 msg_callbacks->fwEventHandler(msg_callbacks->Context,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530136 QDF_STATUS_E_FAILURE);
Houston Hoffman0dad5092015-09-28 16:25:51 -0700137}
138
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800139/**
140 * hif_fw_interrupt_handler(): FW interrupt handler
141 *
142 * This function is the FW interrupt handlder
143 *
144 * @irq: irq number
145 * @arg: the user pointer
146 *
147 * Return: bool
148 */
149#ifndef QCA_WIFI_3_0
150irqreturn_t hif_fw_interrupt_handler(int irq, void *arg)
151{
Komal Seelam644263d2016-02-22 20:45:49 +0530152 struct hif_softc *scn = arg;
Komal Seelam02cf2f82016-02-22 20:44:25 +0530153 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800154 uint32_t fw_indicator_address, fw_indicator;
155
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700156 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
157 return ATH_ISR_NOSCHED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800158
159 fw_indicator_address = hif_state->fw_indicator_address;
160 /* For sudden unplug this will return ~0 */
161 fw_indicator = A_TARGET_READ(scn, fw_indicator_address);
162
163 if ((fw_indicator != ~0) && (fw_indicator & FW_IND_EVENT_PENDING)) {
164 /* ACK: clear Target-side pending event */
165 A_TARGET_WRITE(scn, fw_indicator_address,
166 fw_indicator & ~FW_IND_EVENT_PENDING);
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700167 if (Q_TARGET_ACCESS_END(scn) < 0)
168 return ATH_ISR_SCHED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800169
170 if (hif_state->started) {
Houston Hoffman0dad5092015-09-28 16:25:51 -0700171 hif_fw_event_handler(hif_state);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800172 } else {
173 /*
174 * Probable Target failure before we're prepared
175 * to handle it. Generally unexpected.
176 */
177 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
178 ("%s: Early firmware event indicated\n",
179 __func__));
180 }
181 } else {
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700182 if (Q_TARGET_ACCESS_END(scn) < 0)
183 return ATH_ISR_SCHED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800184 }
185
186 return ATH_ISR_SCHED;
187}
188#else
189irqreturn_t hif_fw_interrupt_handler(int irq, void *arg)
190{
191 return ATH_ISR_SCHED;
192}
193#endif /* #ifdef QCA_WIFI_3_0 */
194
195/**
196 * hif_get_targetdef(): hif_get_targetdef
197 * @scn: scn
198 *
199 * Return: void *
200 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530201void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800202{
Komal Seelam644263d2016-02-22 20:45:49 +0530203 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
204
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800205 return scn->targetdef;
206}
207
208/**
209 * hif_vote_link_down(): unvote for link up
210 *
211 * Call hif_vote_link_down to release a previous request made using
212 * hif_vote_link_up. A hif_vote_link_down call should only be made
213 * after a corresponding hif_vote_link_up, otherwise you could be
214 * negating a vote from another source. When no votes are present
215 * hif will not guarantee the linkstate after hif_bus_suspend.
216 *
217 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
218 * and initialization deinitialization sequencences.
219 *
220 * Return: n/a
221 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530222void hif_vote_link_down(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800223{
Komal Seelam644263d2016-02-22 20:45:49 +0530224 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530225 QDF_BUG(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800226
227 scn->linkstate_vote--;
228 if (scn->linkstate_vote == 0)
Houston Hoffmancceec342015-11-11 11:37:20 -0800229 hif_bus_prevent_linkdown(scn, false);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800230}
231
232/**
233 * hif_vote_link_up(): vote to prevent bus from suspending
234 *
235 * Makes hif guarantee that fw can message the host normally
236 * durring suspend.
237 *
238 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
239 * and initialization deinitialization sequencences.
240 *
241 * Return: n/a
242 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530243void hif_vote_link_up(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800244{
Komal Seelam644263d2016-02-22 20:45:49 +0530245 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530246 QDF_BUG(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800247
248 scn->linkstate_vote++;
249 if (scn->linkstate_vote == 1)
Houston Hoffmancceec342015-11-11 11:37:20 -0800250 hif_bus_prevent_linkdown(scn, true);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800251}
252
253/**
254 * hif_can_suspend_link(): query if hif is permitted to suspend the link
255 *
256 * Hif will ensure that the link won't be suspended if the upperlayers
257 * don't want it to.
258 *
259 * SYNCHRONIZATION: MC thread is stopped before bus suspend thus
260 * we don't need extra locking to ensure votes dont change while
261 * we are in the process of suspending or resuming.
262 *
263 * Return: false if hif will guarantee link up durring suspend.
264 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530265bool hif_can_suspend_link(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800266{
Komal Seelam644263d2016-02-22 20:45:49 +0530267 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530268 QDF_BUG(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800269
270 return scn->linkstate_vote == 0;
271}
272
273/**
274 * hif_hia_item_address(): hif_hia_item_address
275 * @target_type: target_type
276 * @item_offset: item_offset
277 *
278 * Return: n/a
279 */
280uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset)
281{
282 switch (target_type) {
283 case TARGET_TYPE_AR6002:
284 return AR6002_HOST_INTEREST_ADDRESS + item_offset;
285 case TARGET_TYPE_AR6003:
286 return AR6003_HOST_INTEREST_ADDRESS + item_offset;
287 case TARGET_TYPE_AR6004:
288 return AR6004_HOST_INTEREST_ADDRESS + item_offset;
289 case TARGET_TYPE_AR6006:
290 return AR6006_HOST_INTEREST_ADDRESS + item_offset;
291 case TARGET_TYPE_AR9888:
292 return AR9888_HOST_INTEREST_ADDRESS + item_offset;
293 case TARGET_TYPE_AR6320:
294 case TARGET_TYPE_AR6320V2:
295 return AR6320_HOST_INTEREST_ADDRESS + item_offset;
296 case TARGET_TYPE_QCA6180:
297 return QCA6180_HOST_INTEREST_ADDRESS + item_offset;
298 case TARGET_TYPE_ADRASTEA:
299 /* ADRASTEA doesn't have a host interest address */
300 ASSERT(0);
301 return 0;
302 default:
303 ASSERT(0);
304 return 0;
305 }
306}
307
308/**
309 * hif_max_num_receives_reached() - check max receive is reached
Komal Seelambd7c51d2016-02-24 10:27:30 +0530310 * @scn: HIF Context
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800311 * @count: unsigned int.
312 *
313 * Output check status as bool
314 *
315 * Return: bool
316 */
Komal Seelambd7c51d2016-02-24 10:27:30 +0530317bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800318{
Komal Seelambd7c51d2016-02-24 10:27:30 +0530319 if (WLAN_IS_EPPING_ENABLED(hif_get_conparam(scn)))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800320 return count > 120;
321 else
322 return count > MAX_NUM_OF_RECEIVES;
323}
324
325/**
326 * init_buffer_count() - initial buffer count
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530327 * @maxSize: qdf_size_t
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800328 *
329 * routine to modify the initial buffer count to be allocated on an os
330 * platform basis. Platform owner will need to modify this as needed
331 *
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530332 * Return: qdf_size_t
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800333 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530334qdf_size_t init_buffer_count(qdf_size_t maxSize)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800335{
336 return maxSize;
337}
338
339/**
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800340 * hif_save_htc_htt_config_endpoint():
341 * hif_save_htc_htt_config_endpoint
342 * @htc_endpoint: htc_endpoint
343 *
344 * Return: void
345 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530346void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx,
347 int htc_endpoint)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800348{
Komal Seelam644263d2016-02-22 20:45:49 +0530349 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800350
351 if (!scn) {
352 HIF_ERROR("%s: error: scn or scn->hif_sc is NULL!",
353 __func__);
354 return;
355 }
356
357 scn->htc_endpoint = htc_endpoint;
358}
359
360/**
361 * hif_get_hw_name(): get a human readable name for the hardware
Komal Seelam91553ce2016-01-27 18:57:10 +0530362 * @info: Target Info
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800363 *
Komal Seelam91553ce2016-01-27 18:57:10 +0530364 * Return: human readable name for the underlying wifi hardware.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800365 */
Komal Seelam91553ce2016-01-27 18:57:10 +0530366static const char *hif_get_hw_name(struct hif_target_info *info)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800367{
368 int i;
Komal Seelam91553ce2016-01-27 18:57:10 +0530369
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800370 for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) {
Komal Seelam91553ce2016-01-27 18:57:10 +0530371 if (info->target_version == qwlan_hw_list[i].id &&
372 info->target_revision == qwlan_hw_list[i].subid) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800373 return qwlan_hw_list[i].name;
374 }
375 }
376
377 return "Unknown Device";
378}
379
380/**
381 * hif_get_hw_info(): hif_get_hw_info
382 * @scn: scn
383 * @version: version
384 * @revision: revision
385 *
386 * Return: n/a
387 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530388void hif_get_hw_info(struct hif_opaque_softc *scn, u32 *version, u32 *revision,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800389 const char **target_name)
390{
Komal Seelam91553ce2016-01-27 18:57:10 +0530391 struct hif_target_info *info = hif_get_target_info_handle(scn);
392 *version = info->target_version;
393 *revision = info->target_revision;
394 *target_name = hif_get_hw_name(info);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800395}
396
397/**
398 * hif_open(): hif_open
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530399 * @qdf_ctx: QDF Context
Komal Seelambd7c51d2016-02-24 10:27:30 +0530400 * @mode: Driver Mode
401 * @bus_type: Bus Type
402 * @cbk: CDS Callbacks
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800403 *
Komal Seelambd7c51d2016-02-24 10:27:30 +0530404 * API to open HIF Context
405 *
406 * Return: HIF Opaque Pointer
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800407 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530408struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode,
409 enum qdf_bus_type bus_type,
Komal Seelambd7c51d2016-02-24 10:27:30 +0530410 struct hif_callbacks *cbk)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800411{
Komal Seelam644263d2016-02-22 20:45:49 +0530412 struct hif_softc *scn;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530413 QDF_STATUS status = QDF_STATUS_SUCCESS;
Houston Hoffman162164c2016-03-14 21:12:10 -0700414 int bus_context_size = hif_bus_get_context_size(bus_type);
415
416 if (bus_context_size == 0) {
417 HIF_ERROR("%s: context size 0 not allowed", __func__);
418 return NULL;
419 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800420
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530421 scn = (struct hif_softc *)qdf_mem_malloc(bus_context_size);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530422 if (!scn) {
423 HIF_ERROR("%s: cannot alloc memory for HIF context of size:%d",
424 __func__, bus_context_size);
425 return GET_HIF_OPAQUE_HDL(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800426 }
427
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530428 qdf_mem_zero(scn, bus_context_size);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530429
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530430 scn->qdf_dev = qdf_ctx;
Komal Seelambd7c51d2016-02-24 10:27:30 +0530431 scn->hif_con_param = mode;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530432 qdf_atomic_init(&scn->active_tasklet_cnt);
433 qdf_atomic_init(&scn->link_suspended);
434 qdf_atomic_init(&scn->tasklet_from_intr);
435 qdf_mem_copy(&scn->callbacks, cbk, sizeof(struct hif_callbacks));
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800436
437 status = hif_bus_open(scn, bus_type);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530438 if (status != QDF_STATUS_SUCCESS) {
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800439 HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d",
440 __func__, status, bus_type);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530441 qdf_mem_free(scn);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530442 scn = NULL;
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800443 }
444
Komal Seelambd7c51d2016-02-24 10:27:30 +0530445 return GET_HIF_OPAQUE_HDL(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800446}
447
448/**
449 * hif_close(): hif_close
450 * @hif_ctx: hif_ctx
451 *
452 * Return: n/a
453 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530454void hif_close(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800455{
Komal Seelam644263d2016-02-22 20:45:49 +0530456 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800457
458 if (scn == NULL) {
Komal Seelam5584a7c2016-02-24 19:22:48 +0530459 HIF_ERROR("%s: hif_opaque_softc is NULL", __func__);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800460 return;
461 }
462
463 if (scn->athdiag_procfs_inited) {
464 athdiag_procfs_remove();
465 scn->athdiag_procfs_inited = false;
466 }
467
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800468 hif_bus_close(scn);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530469 qdf_mem_free(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800470}
471
472/**
473 * hif_enable(): hif_enable
474 * @hif_ctx: hif_ctx
475 * @dev: dev
476 * @bdev: bus dev
477 * @bid: bus ID
478 * @bus_type: bus type
479 * @type: enable type
480 *
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530481 * Return: QDF_STATUS
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800482 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530483QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800484 void *bdev, const hif_bus_id *bid,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530485 enum qdf_bus_type bus_type,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800486 enum hif_enable_type type)
487{
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530488 QDF_STATUS status;
Komal Seelam644263d2016-02-22 20:45:49 +0530489 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800490
491 if (scn == NULL) {
492 HIF_ERROR("%s: hif_ctx = NULL", __func__);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530493 return QDF_STATUS_E_NULL_VALUE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800494 }
495
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800496 status = hif_enable_bus(scn, dev, bdev, bid, type);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530497 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800498 HIF_ERROR("%s: hif_enable_bus error = %d",
499 __func__, status);
500 return status;
501 }
502
503 if (ADRASTEA_BU)
Komal Seelamf8600682016-02-02 18:17:13 +0530504 hif_vote_link_up(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800505
Houston Hoffman108da402016-03-14 21:11:24 -0700506 if (hif_bus_configure(scn)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800507 HIF_ERROR("%s: Target probe failed.", __func__);
Vishwajith Upendra3f78aa62016-02-09 17:53:02 +0530508 hif_disable_bus(scn);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530509 status = QDF_STATUS_E_FAILURE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800510 return status;
511 }
Houston Hoffman108da402016-03-14 21:11:24 -0700512
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800513 /*
514 * Flag to avoid potential unallocated memory access from MSI
515 * interrupt handler which could get scheduled as soon as MSI
516 * is enabled, i.e to take care of the race due to the order
517 * in where MSI is enabled before the memory, that will be
518 * in interrupt handlers, is allocated.
519 */
520
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800521 scn->hif_init_done = true;
522
523 HIF_TRACE("%s: X OK", __func__);
524
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530525 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800526}
527
528/**
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800529 * hif_wlan_disable(): call the platform driver to disable wlan
Komal Seelambd7c51d2016-02-24 10:27:30 +0530530 * @scn: HIF Context
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800531 *
532 * This function passes the con_mode to platform driver to disable
533 * wlan.
534 *
535 * Return: void
536 */
Komal Seelambd7c51d2016-02-24 10:27:30 +0530537void hif_wlan_disable(struct hif_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800538{
539 enum icnss_driver_mode mode;
Komal Seelambd7c51d2016-02-24 10:27:30 +0530540 uint32_t con_mode = hif_get_conparam(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800541
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530542 if (QDF_GLOBAL_FTM_MODE == con_mode)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800543 mode = ICNSS_FTM;
Komal Seelambd7c51d2016-02-24 10:27:30 +0530544 else if (WLAN_IS_EPPING_ENABLED(con_mode))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800545 mode = ICNSS_EPPING;
Peng Xu7b962532015-10-02 17:17:03 -0700546 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800547 mode = ICNSS_MISSION;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800548
549 icnss_wlan_disable(mode);
550}
551
Komal Seelam5584a7c2016-02-24 19:22:48 +0530552void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800553{
Komal Seelam644263d2016-02-22 20:45:49 +0530554 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800555
556 if (!scn)
557 return;
558
559 hif_nointrs(scn);
560 if (scn->hif_init_done == false)
Komal Seelam644263d2016-02-22 20:45:49 +0530561 hif_shut_down_device(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800562 else
Komal Seelam644263d2016-02-22 20:45:49 +0530563 hif_stop(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800564
565 if (ADRASTEA_BU)
Komal Seelamf8600682016-02-02 18:17:13 +0530566 hif_vote_link_down(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800567
Vishwajith Upendra3f78aa62016-02-09 17:53:02 +0530568 hif_disable_bus(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800569
Komal Seelambd7c51d2016-02-24 10:27:30 +0530570 hif_wlan_disable(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800571
572 scn->notice_send = false;
573
574 HIF_INFO("%s: X", __func__);
575}
576
577
578/**
Govind Singh2443fb32016-01-13 17:44:48 +0530579 * hif_crash_shutdown_dump_bus_register() - dump bus registers
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800580 * @hif_ctx: hif_ctx
581 *
582 * Return: n/a
583 */
584#if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) \
Houston Hoffmanbc693492016-03-14 21:11:41 -0700585&& defined(DEBUG)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800586
Govind Singh2443fb32016-01-13 17:44:48 +0530587static void hif_crash_shutdown_dump_bus_register(void *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800588{
Komal Seelam5584a7c2016-02-24 19:22:48 +0530589 struct hif_opaque_softc *scn = hif_ctx;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800590
Govind Singh2443fb32016-01-13 17:44:48 +0530591 if (hif_check_soc_status(scn))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800592 return;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800593
Govind Singh2443fb32016-01-13 17:44:48 +0530594 if (hif_dump_registers(scn))
595 HIF_ERROR("Failed to dump bus registers!");
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800596}
597
598/**
599 * hif_crash_shutdown(): hif_crash_shutdown
600 *
601 * This function is called by the platform driver to dump CE registers
602 *
603 * @hif_ctx: hif_ctx
604 *
605 * Return: n/a
606 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530607void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800608{
Komal Seelam644263d2016-02-22 20:45:49 +0530609 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800610
Houston Hoffmanbc693492016-03-14 21:11:41 -0700611 if (!hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800612 return;
613
Houston Hoffmanbc693492016-03-14 21:11:41 -0700614 if (scn->bus_type == QDF_BUS_TYPE_SNOC) {
615 HIF_INFO_MED("%s: RAM dump disabled for bustype %d",
616 __func__, scn->bus_type);
617 return;
618 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800619
620 if (OL_TRGET_STATUS_RESET == scn->target_status) {
621 HIF_INFO_MED("%s: Target is already asserted, ignore!",
622 __func__);
623 return;
624 }
625
Komal Seelambd7c51d2016-02-24 10:27:30 +0530626 if (hif_is_load_or_unload_in_progress(scn)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800627 HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__);
628 return;
629 }
630
Govind Singh2443fb32016-01-13 17:44:48 +0530631 hif_crash_shutdown_dump_bus_register(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800632
Komal Seelam644263d2016-02-22 20:45:49 +0530633 if (ol_copy_ramdump(hif_ctx))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800634 goto out;
635
636 HIF_INFO_MED("%s: RAM dump collecting completed!", __func__);
637
638out:
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800639 return;
640}
641#else
Komal Seelam5584a7c2016-02-24 19:22:48 +0530642void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800643{
644 HIF_INFO_MED("%s: Collecting target RAM dump disabled",
645 __func__);
646 return;
647}
648#endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */
649
650#ifdef QCA_WIFI_3_0
651/**
652 * hif_check_fw_reg(): hif_check_fw_reg
653 * @scn: scn
654 * @state:
655 *
656 * Return: int
657 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530658int hif_check_fw_reg(struct hif_opaque_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800659{
660 return 0;
661}
662#endif
663
664#ifdef IPA_OFFLOAD
665/**
666 * hif_read_phy_mem_base(): hif_read_phy_mem_base
667 * @scn: scn
668 * @phy_mem_base: physical mem base
669 *
670 * Return: n/a
671 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530672void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800673{
674 *phy_mem_base = scn->mem_pa;
675}
676#endif /* IPA_OFFLOAD */
677
678/**
679 * hif_get_device_type(): hif_get_device_type
680 * @device_id: device_id
681 * @revision_id: revision_id
682 * @hif_type: returned hif_type
683 * @target_type: returned target_type
684 *
685 * Return: int
686 */
687int hif_get_device_type(uint32_t device_id,
688 uint32_t revision_id,
689 uint32_t *hif_type, uint32_t *target_type)
690{
691 int ret = 0;
692
693 switch (device_id) {
694#ifdef QCA_WIFI_3_0_ADRASTEA
695 case ADRASTEA_DEVICE_ID:
696 case ADRASTEA_DEVICE_ID_P2_E12:
697
698 *hif_type = HIF_TYPE_ADRASTEA;
699 *target_type = TARGET_TYPE_ADRASTEA;
700 break;
701#else
702 case QCA6180_DEVICE_ID:
703 *hif_type = HIF_TYPE_QCA6180;
704 *target_type = TARGET_TYPE_QCA6180;
705 break;
706#endif
707
708 case AR9888_DEVICE_ID:
709 *hif_type = HIF_TYPE_AR9888;
710 *target_type = TARGET_TYPE_AR9888;
711 break;
712
713 case AR6320_DEVICE_ID:
714 switch (revision_id) {
715 case AR6320_FW_1_1:
716 case AR6320_FW_1_3:
717 *hif_type = HIF_TYPE_AR6320;
718 *target_type = TARGET_TYPE_AR6320;
719 break;
720
721 case AR6320_FW_2_0:
722 case AR6320_FW_3_0:
723 case AR6320_FW_3_2:
724 *hif_type = HIF_TYPE_AR6320V2;
725 *target_type = TARGET_TYPE_AR6320V2;
726 break;
727
728 default:
729 HIF_ERROR("%s: error - dev_id = 0x%x, rev_id = 0x%x",
730 __func__, device_id, revision_id);
731 ret = -ENODEV;
732 goto end;
733 }
734 break;
735
736 default:
737 HIF_ERROR("%s: Unsupported device ID!", __func__);
738 ret = -ENODEV;
739 break;
740 }
741end:
742 return ret;
743}
Komal Seelam91553ce2016-01-27 18:57:10 +0530744
745/**
Houston Hoffman26352592016-03-14 21:11:43 -0700746 * hif_needs_bmi() - return true if the soc needs bmi through the driver
747 * @hif_ctx: hif context
748 *
749 * Return: true if the soc needs driver bmi otherwise false
750 */
751bool hif_needs_bmi(struct hif_opaque_softc *hif_ctx)
752{
753 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
754 return hif_sc->bus_type != QDF_BUS_TYPE_SNOC;
755}
756
757/**
Houston Hoffman60a1eeb2016-03-14 21:11:44 -0700758 * hif_get_bus_type() - return the bus type
759 *
760 * Return: enum qdf_bus_type
761 */
762enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl)
763{
764 struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl);
765 return scn->bus_type;
766}
767
768/**
Komal Seelam91553ce2016-01-27 18:57:10 +0530769 * Target info and ini parameters are global to the driver
770 * Hence these structures are exposed to all the modules in
771 * the driver and they don't need to maintains multiple copies
772 * of the same info, instead get the handle from hif and
773 * modify them in hif
774 */
775
776/**
777 * hif_get_ini_handle() - API to get hif_config_param handle
Komal Seelam644263d2016-02-22 20:45:49 +0530778 * @hif_ctx: HIF Context
Komal Seelam91553ce2016-01-27 18:57:10 +0530779 *
780 * Return: pointer to hif_config_info
781 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530782struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx)
Komal Seelam91553ce2016-01-27 18:57:10 +0530783{
Komal Seelam644263d2016-02-22 20:45:49 +0530784 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
785
786 return &sc->hif_config;
Komal Seelam91553ce2016-01-27 18:57:10 +0530787}
788
789/**
790 * hif_get_target_info_handle() - API to get hif_target_info handle
Komal Seelam644263d2016-02-22 20:45:49 +0530791 * @hif_ctx: HIF context
Komal Seelam91553ce2016-01-27 18:57:10 +0530792 *
793 * Return: Pointer to hif_target_info
794 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530795struct hif_target_info *hif_get_target_info_handle(
796 struct hif_opaque_softc *hif_ctx)
Komal Seelam91553ce2016-01-27 18:57:10 +0530797{
Komal Seelam644263d2016-02-22 20:45:49 +0530798 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
799
800 return &sc->target_info;
801
Komal Seelam91553ce2016-01-27 18:57:10 +0530802}
Komal Seelamc92a0cf2016-02-22 20:43:52 +0530803
804#if defined(FEATURE_LRO)
805/**
806 * hif_lro_flush_cb_register - API to register for LRO Flush Callback
807 * @scn: HIF Context
808 * @handler: Function pointer to be called by HIF
809 * @data: Private data to be used by the module registering to HIF
810 *
811 * Return: void
812 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530813void hif_lro_flush_cb_register(struct hif_opaque_softc *scn,
814 void (handler)(void *), void *data)
Komal Seelamc92a0cf2016-02-22 20:43:52 +0530815{
816 ce_lro_flush_cb_register(scn, handler, data);
817}
818
819/**
820 * hif_lro_flush_cb_deregister - API to deregister for LRO Flush Callbacks
821 * @scn: HIF Context
822 *
823 * Return: void
824 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530825void hif_lro_flush_cb_deregister(struct hif_opaque_softc *scn)
Komal Seelamc92a0cf2016-02-22 20:43:52 +0530826{
827 ce_lro_flush_cb_deregister(scn);
828}
829#endif
Komal Seelam644263d2016-02-22 20:45:49 +0530830
831/**
832 * hif_get_target_status - API to get target status
833 * @hif_ctx: HIF Context
834 *
835 * Return: enum ol_target_status
836 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530837ol_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx)
Komal Seelam644263d2016-02-22 20:45:49 +0530838{
839 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
840
841 return scn->target_status;
842}
843
844/**
Komal Seelama5911d32016-02-24 19:21:59 +0530845 * hif_set_target_status() - API to set target status
Komal Seelam644263d2016-02-22 20:45:49 +0530846 * @hif_ctx: HIF Context
847 * @status: Target Status
848 *
849 * Return: void
850 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530851void hif_set_target_status(struct hif_opaque_softc *hif_ctx,
852 ol_target_status status)
Komal Seelam644263d2016-02-22 20:45:49 +0530853{
854 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
855
856 scn->target_status = status;
857}
Komal Seelama5911d32016-02-24 19:21:59 +0530858
859/**
860 * hif_init_ini_config() - API to initialize HIF configuration parameters
861 * @hif_ctx: HIF Context
862 * @cfg: HIF Configuration
863 *
864 * Return: void
865 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530866void hif_init_ini_config(struct hif_opaque_softc *hif_ctx,
867 struct hif_config_info *cfg)
Komal Seelama5911d32016-02-24 19:21:59 +0530868{
869 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
870
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530871 qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info));
Komal Seelama5911d32016-02-24 19:21:59 +0530872}
Komal Seelambd7c51d2016-02-24 10:27:30 +0530873
874/**
875 * hif_get_conparam() - API to get driver mode in HIF
876 * @scn: HIF Context
877 *
878 * Return: driver mode of operation
879 */
880uint32_t hif_get_conparam(struct hif_softc *scn)
881{
882 if (!scn)
883 return 0;
884
885 return scn->hif_con_param;
886}
887
888/**
889 * hif_get_callbacks_handle() - API to get callbacks Handle
890 * @scn: HIF Context
891 *
892 * Return: pointer to HIF Callbacks
893 */
894struct hif_callbacks *hif_get_callbacks_handle(struct hif_softc *scn)
895{
896 return &scn->callbacks;
897}
898
899/**
900 * hif_is_driver_unloading() - API to query upper layers if driver is unloading
901 * @scn: HIF Context
902 *
903 * Return: True/False
904 */
905bool hif_is_driver_unloading(struct hif_softc *scn)
906{
907 struct hif_callbacks *cbk = hif_get_callbacks_handle(scn);
908
909 if (cbk && cbk->is_driver_unloading)
910 return cbk->is_driver_unloading(cbk->context);
911
912 return false;
913}
914
915/**
916 * hif_is_load_or_unload_in_progress() - API to query upper layers if
917 * load/unload in progress
918 * @scn: HIF Context
919 *
920 * Return: True/False
921 */
922bool hif_is_load_or_unload_in_progress(struct hif_softc *scn)
923{
924 struct hif_callbacks *cbk = hif_get_callbacks_handle(scn);
925
926 if (cbk && cbk->is_load_unload_in_progress)
927 return cbk->is_load_unload_in_progress(cbk->context);
928
929 return false;
930}
931
932/**
933 * hif_is_recovery_in_progress() - API to query upper layers if recovery in
934 * progress
935 * @scn: HIF Context
936 *
937 * Return: True/False
938 */
939bool hif_is_recovery_in_progress(struct hif_softc *scn)
940{
941 struct hif_callbacks *cbk = hif_get_callbacks_handle(scn);
942
943 if (cbk && cbk->is_recovery_in_progress)
944 return cbk->is_recovery_in_progress(cbk->context);
945
946 return false;
947}