blob: acdd0f145b80be5345758e958d96c36a2477357e [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
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080028#include "targcfg.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053029#include "qdf_lock.h"
30#include "qdf_status.h"
31#include "qdf_status.h"
32#include <qdf_atomic.h> /* qdf_atomic_read */
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080033#include <targaddrs.h>
34#include <bmi_msg.h>
35#include "hif_io32.h"
36#include <hif.h>
37#include <htc_services.h>
38#include "regtable.h"
39#define ATH_MODULE_NAME hif
40#include <a_debug.h>
41#include "hif_main.h"
42#include "hif_hw_version.h"
43#include "ce_api.h"
44#include "ce_tasklet.h"
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +053045#include "qdf_trace.h"
46#include "qdf_status.h"
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080047#ifdef CONFIG_CNSS
48#include <net/cnss.h>
49#endif
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080050#include "hif_debug.h"
51#include "mp_dev.h"
Houston Hoffmanbc693492016-03-14 21:11:41 -070052#include "platform_icnss.h"
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080053
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080054#define AGC_DUMP 1
55#define CHANINFO_DUMP 2
56#define BB_WATCHDOG_DUMP 3
57#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
58#define PCIE_ACCESS_DUMP 4
59#endif
60
Komal Seelam5584a7c2016-02-24 19:22:48 +053061void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080062{
Komal Seelam644263d2016-02-22 20:45:49 +053063 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -080064 switch (cmd_id) {
65 case AGC_DUMP:
66 if (start)
67 priv_start_agc(scn);
68 else
69 priv_dump_agc(scn);
70 break;
71
72 case CHANINFO_DUMP:
73 if (start)
74 priv_start_cap_chaninfo(scn);
75 else
76 priv_dump_chaninfo(scn);
77 break;
78
79 case BB_WATCHDOG_DUMP:
80 priv_dump_bbwatchdog(scn);
81 break;
82
83#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
84 case PCIE_ACCESS_DUMP:
85 hif_target_dump_access_log();
86 break;
87#endif
88 default:
89 HIF_ERROR("%s: Invalid htc dump command", __func__);
90 break;
91 }
92}
93
94/**
95 * hif_shut_down_device() - hif_shut_down_device
96 *
97 * SThis fucntion shuts down the device
98 *
Komal Seelam5584a7c2016-02-24 19:22:48 +053099 * @scn: hif_opaque_softc
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800100 *
101 * Return: void
102 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530103void hif_shut_down_device(struct hif_opaque_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800104{
Komal Seelam02cf2f82016-02-22 20:44:25 +0530105 hif_stop(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800106}
107
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800108/**
109 * hif_get_target_id(): hif_get_target_id
110 *
111 * Return the virtual memory base address to the caller
112 *
Komal Seelam644263d2016-02-22 20:45:49 +0530113 * @scn: hif_softc
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800114 *
115 * Return: A_target_id_t
116 */
Komal Seelam644263d2016-02-22 20:45:49 +0530117A_target_id_t hif_get_target_id(struct hif_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800118{
119 return scn->mem;
120}
121
Houston Hoffman0dad5092015-09-28 16:25:51 -0700122static inline void hif_fw_event_handler(struct HIF_CE_state *hif_state)
123{
124 struct hif_msg_callbacks *msg_callbacks =
125 &hif_state->msg_callbacks_current;
126
127 if (!msg_callbacks->fwEventHandler)
128 return;
129
130 msg_callbacks->fwEventHandler(msg_callbacks->Context,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530131 QDF_STATUS_E_FAILURE);
Houston Hoffman0dad5092015-09-28 16:25:51 -0700132}
133
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800134/**
135 * hif_fw_interrupt_handler(): FW interrupt handler
136 *
137 * This function is the FW interrupt handlder
138 *
139 * @irq: irq number
140 * @arg: the user pointer
141 *
142 * Return: bool
143 */
144#ifndef QCA_WIFI_3_0
145irqreturn_t hif_fw_interrupt_handler(int irq, void *arg)
146{
Komal Seelam644263d2016-02-22 20:45:49 +0530147 struct hif_softc *scn = arg;
Komal Seelam02cf2f82016-02-22 20:44:25 +0530148 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800149 uint32_t fw_indicator_address, fw_indicator;
150
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700151 if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
152 return ATH_ISR_NOSCHED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800153
154 fw_indicator_address = hif_state->fw_indicator_address;
155 /* For sudden unplug this will return ~0 */
156 fw_indicator = A_TARGET_READ(scn, fw_indicator_address);
157
158 if ((fw_indicator != ~0) && (fw_indicator & FW_IND_EVENT_PENDING)) {
159 /* ACK: clear Target-side pending event */
160 A_TARGET_WRITE(scn, fw_indicator_address,
161 fw_indicator & ~FW_IND_EVENT_PENDING);
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700162 if (Q_TARGET_ACCESS_END(scn) < 0)
163 return ATH_ISR_SCHED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800164
165 if (hif_state->started) {
Houston Hoffman0dad5092015-09-28 16:25:51 -0700166 hif_fw_event_handler(hif_state);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800167 } else {
168 /*
169 * Probable Target failure before we're prepared
170 * to handle it. Generally unexpected.
171 */
172 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
173 ("%s: Early firmware event indicated\n",
174 __func__));
175 }
176 } else {
Houston Hoffman2c32cf62016-03-14 21:12:00 -0700177 if (Q_TARGET_ACCESS_END(scn) < 0)
178 return ATH_ISR_SCHED;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800179 }
180
181 return ATH_ISR_SCHED;
182}
183#else
184irqreturn_t hif_fw_interrupt_handler(int irq, void *arg)
185{
186 return ATH_ISR_SCHED;
187}
188#endif /* #ifdef QCA_WIFI_3_0 */
189
190/**
191 * hif_get_targetdef(): hif_get_targetdef
192 * @scn: scn
193 *
194 * Return: void *
195 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530196void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800197{
Komal Seelam644263d2016-02-22 20:45:49 +0530198 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
199
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800200 return scn->targetdef;
201}
202
203/**
204 * hif_vote_link_down(): unvote for link up
205 *
206 * Call hif_vote_link_down to release a previous request made using
207 * hif_vote_link_up. A hif_vote_link_down call should only be made
208 * after a corresponding hif_vote_link_up, otherwise you could be
209 * negating a vote from another source. When no votes are present
210 * hif will not guarantee the linkstate after hif_bus_suspend.
211 *
212 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
213 * and initialization deinitialization sequencences.
214 *
215 * Return: n/a
216 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530217void hif_vote_link_down(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800218{
Komal Seelam644263d2016-02-22 20:45:49 +0530219 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530220 QDF_BUG(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800221
222 scn->linkstate_vote--;
223 if (scn->linkstate_vote == 0)
Houston Hoffmancceec342015-11-11 11:37:20 -0800224 hif_bus_prevent_linkdown(scn, false);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800225}
226
227/**
228 * hif_vote_link_up(): vote to prevent bus from suspending
229 *
230 * Makes hif guarantee that fw can message the host normally
231 * durring suspend.
232 *
233 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
234 * and initialization deinitialization sequencences.
235 *
236 * Return: n/a
237 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530238void hif_vote_link_up(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800239{
Komal Seelam644263d2016-02-22 20:45:49 +0530240 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530241 QDF_BUG(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800242
243 scn->linkstate_vote++;
244 if (scn->linkstate_vote == 1)
Houston Hoffmancceec342015-11-11 11:37:20 -0800245 hif_bus_prevent_linkdown(scn, true);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800246}
247
248/**
249 * hif_can_suspend_link(): query if hif is permitted to suspend the link
250 *
251 * Hif will ensure that the link won't be suspended if the upperlayers
252 * don't want it to.
253 *
254 * SYNCHRONIZATION: MC thread is stopped before bus suspend thus
255 * we don't need extra locking to ensure votes dont change while
256 * we are in the process of suspending or resuming.
257 *
258 * Return: false if hif will guarantee link up durring suspend.
259 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530260bool hif_can_suspend_link(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800261{
Komal Seelam644263d2016-02-22 20:45:49 +0530262 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530263 QDF_BUG(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800264
265 return scn->linkstate_vote == 0;
266}
267
268/**
269 * hif_hia_item_address(): hif_hia_item_address
270 * @target_type: target_type
271 * @item_offset: item_offset
272 *
273 * Return: n/a
274 */
275uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset)
276{
277 switch (target_type) {
278 case TARGET_TYPE_AR6002:
279 return AR6002_HOST_INTEREST_ADDRESS + item_offset;
280 case TARGET_TYPE_AR6003:
281 return AR6003_HOST_INTEREST_ADDRESS + item_offset;
282 case TARGET_TYPE_AR6004:
283 return AR6004_HOST_INTEREST_ADDRESS + item_offset;
284 case TARGET_TYPE_AR6006:
285 return AR6006_HOST_INTEREST_ADDRESS + item_offset;
286 case TARGET_TYPE_AR9888:
287 return AR9888_HOST_INTEREST_ADDRESS + item_offset;
288 case TARGET_TYPE_AR6320:
289 case TARGET_TYPE_AR6320V2:
290 return AR6320_HOST_INTEREST_ADDRESS + item_offset;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800291 case TARGET_TYPE_ADRASTEA:
292 /* ADRASTEA doesn't have a host interest address */
293 ASSERT(0);
294 return 0;
295 default:
296 ASSERT(0);
297 return 0;
298 }
299}
300
301/**
302 * hif_max_num_receives_reached() - check max receive is reached
Komal Seelambd7c51d2016-02-24 10:27:30 +0530303 * @scn: HIF Context
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800304 * @count: unsigned int.
305 *
306 * Output check status as bool
307 *
308 * Return: bool
309 */
Komal Seelambd7c51d2016-02-24 10:27:30 +0530310bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800311{
Houston Hoffman75ef5a52016-04-14 17:15:49 -0700312 if (QDF_IS_EPPING_ENABLED(hif_get_conparam(scn)))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800313 return count > 120;
314 else
315 return count > MAX_NUM_OF_RECEIVES;
316}
317
318/**
319 * init_buffer_count() - initial buffer count
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530320 * @maxSize: qdf_size_t
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800321 *
322 * routine to modify the initial buffer count to be allocated on an os
323 * platform basis. Platform owner will need to modify this as needed
324 *
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530325 * Return: qdf_size_t
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800326 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530327qdf_size_t init_buffer_count(qdf_size_t maxSize)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800328{
329 return maxSize;
330}
331
332/**
Nirav Shahd7f91592016-04-21 14:18:43 +0530333 * hif_save_htc_htt_config_endpoint() - save htt_tx_endpoint
334 * @hif_ctx: hif context
335 * @htc_htt_tx_endpoint: htt_tx_endpoint
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800336 *
337 * Return: void
338 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530339void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx,
Nirav Shahd7f91592016-04-21 14:18:43 +0530340 int htc_htt_tx_endpoint)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800341{
Komal Seelam644263d2016-02-22 20:45:49 +0530342 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800343
344 if (!scn) {
345 HIF_ERROR("%s: error: scn or scn->hif_sc is NULL!",
346 __func__);
347 return;
348 }
349
Nirav Shahd7f91592016-04-21 14:18:43 +0530350 scn->htc_htt_tx_endpoint = htc_htt_tx_endpoint;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800351}
352
353/**
354 * hif_get_hw_name(): get a human readable name for the hardware
Komal Seelam91553ce2016-01-27 18:57:10 +0530355 * @info: Target Info
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800356 *
Komal Seelam91553ce2016-01-27 18:57:10 +0530357 * Return: human readable name for the underlying wifi hardware.
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800358 */
Komal Seelam91553ce2016-01-27 18:57:10 +0530359static const char *hif_get_hw_name(struct hif_target_info *info)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800360{
361 int i;
Komal Seelam91553ce2016-01-27 18:57:10 +0530362
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800363 for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) {
Komal Seelam91553ce2016-01-27 18:57:10 +0530364 if (info->target_version == qwlan_hw_list[i].id &&
365 info->target_revision == qwlan_hw_list[i].subid) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800366 return qwlan_hw_list[i].name;
367 }
368 }
369
370 return "Unknown Device";
371}
372
373/**
374 * hif_get_hw_info(): hif_get_hw_info
375 * @scn: scn
376 * @version: version
377 * @revision: revision
378 *
379 * Return: n/a
380 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530381void hif_get_hw_info(struct hif_opaque_softc *scn, u32 *version, u32 *revision,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800382 const char **target_name)
383{
Komal Seelam91553ce2016-01-27 18:57:10 +0530384 struct hif_target_info *info = hif_get_target_info_handle(scn);
385 *version = info->target_version;
386 *revision = info->target_revision;
387 *target_name = hif_get_hw_name(info);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800388}
389
390/**
391 * hif_open(): hif_open
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530392 * @qdf_ctx: QDF Context
Komal Seelambd7c51d2016-02-24 10:27:30 +0530393 * @mode: Driver Mode
394 * @bus_type: Bus Type
395 * @cbk: CDS Callbacks
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800396 *
Komal Seelambd7c51d2016-02-24 10:27:30 +0530397 * API to open HIF Context
398 *
399 * Return: HIF Opaque Pointer
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800400 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530401struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode,
402 enum qdf_bus_type bus_type,
Komal Seelam75080122016-03-02 15:18:25 +0530403 struct hif_driver_state_callbacks *cbk)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800404{
Komal Seelam644263d2016-02-22 20:45:49 +0530405 struct hif_softc *scn;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530406 QDF_STATUS status = QDF_STATUS_SUCCESS;
Houston Hoffman162164c2016-03-14 21:12:10 -0700407 int bus_context_size = hif_bus_get_context_size(bus_type);
408
409 if (bus_context_size == 0) {
410 HIF_ERROR("%s: context size 0 not allowed", __func__);
411 return NULL;
412 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800413
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530414 scn = (struct hif_softc *)qdf_mem_malloc(bus_context_size);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530415 if (!scn) {
416 HIF_ERROR("%s: cannot alloc memory for HIF context of size:%d",
417 __func__, bus_context_size);
418 return GET_HIF_OPAQUE_HDL(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800419 }
420
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530421 qdf_mem_zero(scn, bus_context_size);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530422
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530423 scn->qdf_dev = qdf_ctx;
Komal Seelambd7c51d2016-02-24 10:27:30 +0530424 scn->hif_con_param = mode;
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530425 qdf_atomic_init(&scn->active_tasklet_cnt);
426 qdf_atomic_init(&scn->link_suspended);
427 qdf_atomic_init(&scn->tasklet_from_intr);
Komal Seelam75080122016-03-02 15:18:25 +0530428 qdf_mem_copy(&scn->callbacks, cbk, sizeof(struct hif_driver_state_callbacks));
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800429
430 status = hif_bus_open(scn, bus_type);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530431 if (status != QDF_STATUS_SUCCESS) {
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800432 HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d",
433 __func__, status, bus_type);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530434 qdf_mem_free(scn);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530435 scn = NULL;
Houston Hoffman3cfe6862016-01-08 10:33:55 -0800436 }
437
Komal Seelambd7c51d2016-02-24 10:27:30 +0530438 return GET_HIF_OPAQUE_HDL(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800439}
440
441/**
442 * hif_close(): hif_close
443 * @hif_ctx: hif_ctx
444 *
445 * Return: n/a
446 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530447void hif_close(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800448{
Komal Seelam644263d2016-02-22 20:45:49 +0530449 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800450
451 if (scn == NULL) {
Komal Seelam5584a7c2016-02-24 19:22:48 +0530452 HIF_ERROR("%s: hif_opaque_softc is NULL", __func__);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800453 return;
454 }
455
456 if (scn->athdiag_procfs_inited) {
457 athdiag_procfs_remove();
458 scn->athdiag_procfs_inited = false;
459 }
460
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800461 hif_bus_close(scn);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530462 qdf_mem_free(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800463}
464
465/**
466 * hif_enable(): hif_enable
467 * @hif_ctx: hif_ctx
468 * @dev: dev
469 * @bdev: bus dev
470 * @bid: bus ID
471 * @bus_type: bus type
472 * @type: enable type
473 *
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530474 * Return: QDF_STATUS
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800475 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530476QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800477 void *bdev, const hif_bus_id *bid,
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530478 enum qdf_bus_type bus_type,
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800479 enum hif_enable_type type)
480{
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530481 QDF_STATUS status;
Komal Seelam644263d2016-02-22 20:45:49 +0530482 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800483
484 if (scn == NULL) {
485 HIF_ERROR("%s: hif_ctx = NULL", __func__);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530486 return QDF_STATUS_E_NULL_VALUE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800487 }
488
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800489 status = hif_enable_bus(scn, dev, bdev, bid, type);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530490 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800491 HIF_ERROR("%s: hif_enable_bus error = %d",
492 __func__, status);
493 return status;
494 }
495
496 if (ADRASTEA_BU)
Komal Seelamf8600682016-02-02 18:17:13 +0530497 hif_vote_link_up(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800498
Houston Hoffman108da402016-03-14 21:11:24 -0700499 if (hif_bus_configure(scn)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800500 HIF_ERROR("%s: Target probe failed.", __func__);
Vishwajith Upendra3f78aa62016-02-09 17:53:02 +0530501 hif_disable_bus(scn);
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530502 status = QDF_STATUS_E_FAILURE;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800503 return status;
504 }
Houston Hoffman108da402016-03-14 21:11:24 -0700505
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800506 /*
507 * Flag to avoid potential unallocated memory access from MSI
508 * interrupt handler which could get scheduled as soon as MSI
509 * is enabled, i.e to take care of the race due to the order
510 * in where MSI is enabled before the memory, that will be
511 * in interrupt handlers, is allocated.
512 */
513
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800514 scn->hif_init_done = true;
515
516 HIF_TRACE("%s: X OK", __func__);
517
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530518 return QDF_STATUS_SUCCESS;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800519}
520
521/**
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800522 * hif_wlan_disable(): call the platform driver to disable wlan
Komal Seelambd7c51d2016-02-24 10:27:30 +0530523 * @scn: HIF Context
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800524 *
525 * This function passes the con_mode to platform driver to disable
526 * wlan.
527 *
528 * Return: void
529 */
Komal Seelambd7c51d2016-02-24 10:27:30 +0530530void hif_wlan_disable(struct hif_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800531{
532 enum icnss_driver_mode mode;
Komal Seelambd7c51d2016-02-24 10:27:30 +0530533 uint32_t con_mode = hif_get_conparam(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800534
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530535 if (QDF_GLOBAL_FTM_MODE == con_mode)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800536 mode = ICNSS_FTM;
Houston Hoffman75ef5a52016-04-14 17:15:49 -0700537 else if (QDF_IS_EPPING_ENABLED(con_mode))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800538 mode = ICNSS_EPPING;
Peng Xu7b962532015-10-02 17:17:03 -0700539 else
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800540 mode = ICNSS_MISSION;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800541
542 icnss_wlan_disable(mode);
543}
544
Komal Seelam5584a7c2016-02-24 19:22:48 +0530545void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800546{
Komal Seelam644263d2016-02-22 20:45:49 +0530547 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800548
549 if (!scn)
550 return;
551
552 hif_nointrs(scn);
553 if (scn->hif_init_done == false)
Komal Seelam644263d2016-02-22 20:45:49 +0530554 hif_shut_down_device(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800555 else
Komal Seelam644263d2016-02-22 20:45:49 +0530556 hif_stop(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800557
558 if (ADRASTEA_BU)
Komal Seelamf8600682016-02-02 18:17:13 +0530559 hif_vote_link_down(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800560
Vishwajith Upendra3f78aa62016-02-09 17:53:02 +0530561 hif_disable_bus(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800562
Komal Seelambd7c51d2016-02-24 10:27:30 +0530563 hif_wlan_disable(scn);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800564
565 scn->notice_send = false;
566
567 HIF_INFO("%s: X", __func__);
568}
569
570
571/**
Govind Singh2443fb32016-01-13 17:44:48 +0530572 * hif_crash_shutdown_dump_bus_register() - dump bus registers
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800573 * @hif_ctx: hif_ctx
574 *
575 * Return: n/a
576 */
577#if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) \
Houston Hoffmanbc693492016-03-14 21:11:41 -0700578&& defined(DEBUG)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800579
Govind Singh2443fb32016-01-13 17:44:48 +0530580static void hif_crash_shutdown_dump_bus_register(void *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800581{
Komal Seelam5584a7c2016-02-24 19:22:48 +0530582 struct hif_opaque_softc *scn = hif_ctx;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800583
Govind Singh2443fb32016-01-13 17:44:48 +0530584 if (hif_check_soc_status(scn))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800585 return;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800586
Govind Singh2443fb32016-01-13 17:44:48 +0530587 if (hif_dump_registers(scn))
588 HIF_ERROR("Failed to dump bus registers!");
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800589}
590
591/**
592 * hif_crash_shutdown(): hif_crash_shutdown
593 *
594 * This function is called by the platform driver to dump CE registers
595 *
596 * @hif_ctx: hif_ctx
597 *
598 * Return: n/a
599 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530600void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800601{
Komal Seelam644263d2016-02-22 20:45:49 +0530602 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800603
Houston Hoffmanbc693492016-03-14 21:11:41 -0700604 if (!hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800605 return;
606
Houston Hoffmanbc693492016-03-14 21:11:41 -0700607 if (scn->bus_type == QDF_BUS_TYPE_SNOC) {
608 HIF_INFO_MED("%s: RAM dump disabled for bustype %d",
609 __func__, scn->bus_type);
610 return;
611 }
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800612
613 if (OL_TRGET_STATUS_RESET == scn->target_status) {
614 HIF_INFO_MED("%s: Target is already asserted, ignore!",
615 __func__);
616 return;
617 }
618
Komal Seelambd7c51d2016-02-24 10:27:30 +0530619 if (hif_is_load_or_unload_in_progress(scn)) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800620 HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__);
621 return;
622 }
623
Govind Singh2443fb32016-01-13 17:44:48 +0530624 hif_crash_shutdown_dump_bus_register(hif_ctx);
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800625
Komal Seelam644263d2016-02-22 20:45:49 +0530626 if (ol_copy_ramdump(hif_ctx))
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800627 goto out;
628
629 HIF_INFO_MED("%s: RAM dump collecting completed!", __func__);
630
631out:
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800632 return;
633}
634#else
Komal Seelam5584a7c2016-02-24 19:22:48 +0530635void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800636{
637 HIF_INFO_MED("%s: Collecting target RAM dump disabled",
638 __func__);
639 return;
640}
641#endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */
642
643#ifdef QCA_WIFI_3_0
644/**
645 * hif_check_fw_reg(): hif_check_fw_reg
646 * @scn: scn
647 * @state:
648 *
649 * Return: int
650 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530651int hif_check_fw_reg(struct hif_opaque_softc *scn)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800652{
653 return 0;
654}
655#endif
656
657#ifdef IPA_OFFLOAD
658/**
659 * hif_read_phy_mem_base(): hif_read_phy_mem_base
660 * @scn: scn
661 * @phy_mem_base: physical mem base
662 *
663 * Return: n/a
664 */
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530665void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base)
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800666{
667 *phy_mem_base = scn->mem_pa;
668}
669#endif /* IPA_OFFLOAD */
670
671/**
672 * hif_get_device_type(): hif_get_device_type
673 * @device_id: device_id
674 * @revision_id: revision_id
675 * @hif_type: returned hif_type
676 * @target_type: returned target_type
677 *
678 * Return: int
679 */
680int hif_get_device_type(uint32_t device_id,
681 uint32_t revision_id,
682 uint32_t *hif_type, uint32_t *target_type)
683{
684 int ret = 0;
685
686 switch (device_id) {
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800687 case ADRASTEA_DEVICE_ID:
688 case ADRASTEA_DEVICE_ID_P2_E12:
689
690 *hif_type = HIF_TYPE_ADRASTEA;
691 *target_type = TARGET_TYPE_ADRASTEA;
692 break;
Prakash Dhavalid5c9f1c2015-11-08 19:04:44 -0800693
694 case AR9888_DEVICE_ID:
695 *hif_type = HIF_TYPE_AR9888;
696 *target_type = TARGET_TYPE_AR9888;
697 break;
698
699 case AR6320_DEVICE_ID:
700 switch (revision_id) {
701 case AR6320_FW_1_1:
702 case AR6320_FW_1_3:
703 *hif_type = HIF_TYPE_AR6320;
704 *target_type = TARGET_TYPE_AR6320;
705 break;
706
707 case AR6320_FW_2_0:
708 case AR6320_FW_3_0:
709 case AR6320_FW_3_2:
710 *hif_type = HIF_TYPE_AR6320V2;
711 *target_type = TARGET_TYPE_AR6320V2;
712 break;
713
714 default:
715 HIF_ERROR("%s: error - dev_id = 0x%x, rev_id = 0x%x",
716 __func__, device_id, revision_id);
717 ret = -ENODEV;
718 goto end;
719 }
720 break;
721
722 default:
723 HIF_ERROR("%s: Unsupported device ID!", __func__);
724 ret = -ENODEV;
725 break;
726 }
727end:
728 return ret;
729}
Komal Seelam91553ce2016-01-27 18:57:10 +0530730
731/**
Houston Hoffman26352592016-03-14 21:11:43 -0700732 * hif_needs_bmi() - return true if the soc needs bmi through the driver
733 * @hif_ctx: hif context
734 *
735 * Return: true if the soc needs driver bmi otherwise false
736 */
737bool hif_needs_bmi(struct hif_opaque_softc *hif_ctx)
738{
739 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
740 return hif_sc->bus_type != QDF_BUS_TYPE_SNOC;
741}
742
743/**
Houston Hoffman60a1eeb2016-03-14 21:11:44 -0700744 * hif_get_bus_type() - return the bus type
745 *
746 * Return: enum qdf_bus_type
747 */
748enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl)
749{
750 struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl);
751 return scn->bus_type;
752}
753
754/**
Komal Seelam91553ce2016-01-27 18:57:10 +0530755 * Target info and ini parameters are global to the driver
756 * Hence these structures are exposed to all the modules in
757 * the driver and they don't need to maintains multiple copies
758 * of the same info, instead get the handle from hif and
759 * modify them in hif
760 */
761
762/**
763 * hif_get_ini_handle() - API to get hif_config_param handle
Komal Seelam644263d2016-02-22 20:45:49 +0530764 * @hif_ctx: HIF Context
Komal Seelam91553ce2016-01-27 18:57:10 +0530765 *
766 * Return: pointer to hif_config_info
767 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530768struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx)
Komal Seelam91553ce2016-01-27 18:57:10 +0530769{
Komal Seelam644263d2016-02-22 20:45:49 +0530770 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
771
772 return &sc->hif_config;
Komal Seelam91553ce2016-01-27 18:57:10 +0530773}
774
775/**
776 * hif_get_target_info_handle() - API to get hif_target_info handle
Komal Seelam644263d2016-02-22 20:45:49 +0530777 * @hif_ctx: HIF context
Komal Seelam91553ce2016-01-27 18:57:10 +0530778 *
779 * Return: Pointer to hif_target_info
780 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530781struct hif_target_info *hif_get_target_info_handle(
782 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->target_info;
787
Komal Seelam91553ce2016-01-27 18:57:10 +0530788}
Komal Seelamc92a0cf2016-02-22 20:43:52 +0530789
790#if defined(FEATURE_LRO)
791/**
792 * hif_lro_flush_cb_register - API to register for LRO Flush Callback
793 * @scn: HIF Context
794 * @handler: Function pointer to be called by HIF
795 * @data: Private data to be used by the module registering to HIF
796 *
797 * Return: void
798 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530799void hif_lro_flush_cb_register(struct hif_opaque_softc *scn,
800 void (handler)(void *), void *data)
Komal Seelamc92a0cf2016-02-22 20:43:52 +0530801{
802 ce_lro_flush_cb_register(scn, handler, data);
803}
804
805/**
806 * hif_lro_flush_cb_deregister - API to deregister for LRO Flush Callbacks
807 * @scn: HIF Context
808 *
809 * Return: void
810 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530811void hif_lro_flush_cb_deregister(struct hif_opaque_softc *scn)
Komal Seelamc92a0cf2016-02-22 20:43:52 +0530812{
813 ce_lro_flush_cb_deregister(scn);
814}
815#endif
Komal Seelam644263d2016-02-22 20:45:49 +0530816
817/**
818 * hif_get_target_status - API to get target status
819 * @hif_ctx: HIF Context
820 *
821 * Return: enum ol_target_status
822 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530823ol_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx)
Komal Seelam644263d2016-02-22 20:45:49 +0530824{
825 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
826
827 return scn->target_status;
828}
829
830/**
Komal Seelama5911d32016-02-24 19:21:59 +0530831 * hif_set_target_status() - API to set target status
Komal Seelam644263d2016-02-22 20:45:49 +0530832 * @hif_ctx: HIF Context
833 * @status: Target Status
834 *
835 * Return: void
836 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530837void hif_set_target_status(struct hif_opaque_softc *hif_ctx,
838 ol_target_status status)
Komal Seelam644263d2016-02-22 20:45:49 +0530839{
840 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
841
842 scn->target_status = status;
843}
Komal Seelama5911d32016-02-24 19:21:59 +0530844
845/**
846 * hif_init_ini_config() - API to initialize HIF configuration parameters
847 * @hif_ctx: HIF Context
848 * @cfg: HIF Configuration
849 *
850 * Return: void
851 */
Komal Seelam5584a7c2016-02-24 19:22:48 +0530852void hif_init_ini_config(struct hif_opaque_softc *hif_ctx,
853 struct hif_config_info *cfg)
Komal Seelama5911d32016-02-24 19:21:59 +0530854{
855 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
856
Chouhan, Anuragfc06aa92016-03-03 19:05:05 +0530857 qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info));
Komal Seelama5911d32016-02-24 19:21:59 +0530858}
Komal Seelambd7c51d2016-02-24 10:27:30 +0530859
860/**
861 * hif_get_conparam() - API to get driver mode in HIF
862 * @scn: HIF Context
863 *
864 * Return: driver mode of operation
865 */
866uint32_t hif_get_conparam(struct hif_softc *scn)
867{
868 if (!scn)
869 return 0;
870
871 return scn->hif_con_param;
872}
873
874/**
875 * hif_get_callbacks_handle() - API to get callbacks Handle
876 * @scn: HIF Context
877 *
878 * Return: pointer to HIF Callbacks
879 */
Komal Seelam75080122016-03-02 15:18:25 +0530880struct hif_driver_state_callbacks *hif_get_callbacks_handle(struct hif_softc *scn)
Komal Seelambd7c51d2016-02-24 10:27:30 +0530881{
882 return &scn->callbacks;
883}
884
885/**
886 * hif_is_driver_unloading() - API to query upper layers if driver is unloading
887 * @scn: HIF Context
888 *
889 * Return: True/False
890 */
891bool hif_is_driver_unloading(struct hif_softc *scn)
892{
Komal Seelam75080122016-03-02 15:18:25 +0530893 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530894
895 if (cbk && cbk->is_driver_unloading)
896 return cbk->is_driver_unloading(cbk->context);
897
898 return false;
899}
900
901/**
902 * hif_is_load_or_unload_in_progress() - API to query upper layers if
903 * load/unload in progress
904 * @scn: HIF Context
905 *
906 * Return: True/False
907 */
908bool hif_is_load_or_unload_in_progress(struct hif_softc *scn)
909{
Komal Seelam75080122016-03-02 15:18:25 +0530910 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530911
912 if (cbk && cbk->is_load_unload_in_progress)
913 return cbk->is_load_unload_in_progress(cbk->context);
914
915 return false;
916}
917
918/**
919 * hif_is_recovery_in_progress() - API to query upper layers if recovery in
920 * progress
921 * @scn: HIF Context
922 *
923 * Return: True/False
924 */
925bool hif_is_recovery_in_progress(struct hif_softc *scn)
926{
Komal Seelam75080122016-03-02 15:18:25 +0530927 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
Komal Seelambd7c51d2016-02-24 10:27:30 +0530928
929 if (cbk && cbk->is_recovery_in_progress)
930 return cbk->is_recovery_in_progress(cbk->context);
931
932 return false;
933}