xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_pcie.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file moal_pcie.c
2  *
3  *  @brief This file contains PCIE IF (interface) module
4  *  related functions.
5  *
6  *
7  * Copyright 2008-2022 NXP
8  *
9  * This software file (the File) is distributed by NXP
10  * under the terms of the GNU General Public License Version 2, June 1991
11  * (the License).  You may use, redistribute and/or modify the File in
12  * accordance with the terms and conditions of the License, a copy of which
13  * is available by writing to the Free Software Foundation, Inc.,
14  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16  *
17  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
20  * this warranty disclaimer.
21  *
22  */
23 
24 /********************************************************
25 Change log:
26     02/01/2012: initial version
27 ********************************************************/
28 
29 #include <linux/firmware.h>
30 
31 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
32 #include "moal_cfg80211.h"
33 #endif
34 
35 #include "moal_pcie.h"
36 
37 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
38 #ifdef IMX_SUPPORT
39 #include <linux/busfreq-imx.h>
40 #endif
41 #endif
42 
43 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
44 #if IS_ENABLED(CONFIG_IPV6)
45 #include <net/addrconf.h>
46 #endif
47 #endif
48 
49 /********************************************************
50 			Local Variables
51 ********************************************************/
52 #define DRV_NAME "NXP mdriver PCIe"
53 
54 /* PCIE resume handler */
55 static int woal_pcie_resume(struct pci_dev *pdev);
56 static void woal_pcie_reg_dbg(moal_handle *phandle);
57 static void woal_pcie_unregister_dev(moal_handle *handle);
58 static void woal_pcie_cleanup(pcie_service_card *card);
59 static mlan_status woal_pcie_init(pcie_service_card *card);
60 
61 /** WLAN IDs */
62 static const struct pci_device_id wlan_ids[] = {
63 #ifdef PCIE8897
64 	{
65 		PCIE_VENDOR_ID_MRVL,
66 		PCIE_DEVICE_ID_88W8897P,
67 		PCI_ANY_ID,
68 		PCI_ANY_ID,
69 		0,
70 		0,
71 	},
72 #endif
73 #ifdef PCIE8997
74 	{
75 		PCIE_VENDOR_ID_MRVL,
76 		PCIE_DEVICE_ID_88W8997P,
77 		PCI_ANY_ID,
78 		PCI_ANY_ID,
79 		0,
80 		0,
81 	},
82 	{
83 		PCIE_VENDOR_ID_V2_MRVL,
84 		PCIE_DEVICE_ID_88W8997P,
85 		PCI_ANY_ID,
86 		PCI_ANY_ID,
87 		0,
88 		0,
89 	},
90 #endif
91 #ifdef PCIE9097
92 	{
93 		PCIE_VENDOR_ID_V2_MRVL,
94 		PCIE_DEVICE_ID_88W9097,
95 		PCI_ANY_ID,
96 		PCI_ANY_ID,
97 		0,
98 		0,
99 	},
100 #endif
101 #ifdef PCIE9098
102 	{
103 		PCIE_VENDOR_ID_V2_MRVL,
104 		PCIE_DEVICE_ID_88W9098P_FN0,
105 		PCI_ANY_ID,
106 		PCI_ANY_ID,
107 		0,
108 		0,
109 	},
110 	{
111 		PCIE_VENDOR_ID_V2_MRVL,
112 		PCIE_DEVICE_ID_88W9098P_FN1,
113 		PCI_ANY_ID,
114 		PCI_ANY_ID,
115 		0,
116 		0,
117 	},
118 #endif
119 #ifdef PCIENW62X
120 	{
121 		PCIE_VENDOR_ID_NXP,
122 		PCIE_DEVICE_ID_88WNW62X,
123 		PCI_ANY_ID,
124 		PCI_ANY_ID,
125 		0,
126 		0,
127 	},
128 #endif
129 
130 	{},
131 };
132 /* moal interface ops */
133 static moal_if_ops pcie_ops;
134 
135 /********************************************************
136 			Global Variables
137 ********************************************************/
138 
139 /********************************************************
140 			Local Functions
141 ********************************************************/
142 
143 static mlan_status woal_pcie_preinit(struct pci_dev *pdev);
144 #if defined(PCIE8897) || defined(PCIE8997) || defined(PCIE9098) ||             \
145 	defined(PCIE9097) || defined(PCIENW62X)
146 static rdwr_status woal_pcie_rdwr_firmware(moal_handle *phandle, t_u8 doneflag,
147 					   t_u8 resetflag);
148 #endif
149 
150 /**  @brief This function updates the card types
151  *
152  *  @param handle   A Pointer to the moal_handle structure
153  *  @param card     A Pointer to card
154  *
155  *  @return         N/A
156  */
woal_update_card_type(t_void * card)157 static t_u16 woal_update_card_type(t_void *card)
158 {
159 	pcie_service_card *cardp_pcie = (pcie_service_card *)card;
160 	t_u16 card_type = 0;
161 
162 	/* Update card type */
163 #ifdef PCIE8897
164 	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_88W8897P) {
165 		card_type = CARD_TYPE_PCIE8897;
166 		moal_memcpy_ext(NULL, driver_version, CARD_PCIE8897,
167 				strlen(CARD_PCIE8897), strlen(driver_version));
168 		moal_memcpy_ext(NULL,
169 				driver_version + strlen(INTF_CARDTYPE) +
170 					strlen(KERN_VERSION),
171 				V15, strlen(V15),
172 				strlen(driver_version) - strlen(INTF_CARDTYPE) -
173 					strlen(KERN_VERSION));
174 	}
175 #endif
176 #ifdef PCIE8997
177 	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_88W8997P) {
178 		card_type = CARD_TYPE_PCIE8997;
179 		moal_memcpy_ext(NULL, driver_version, CARD_PCIE8997,
180 				strlen(CARD_PCIE8997), strlen(driver_version));
181 		moal_memcpy_ext(NULL,
182 				driver_version + strlen(INTF_CARDTYPE) +
183 					strlen(KERN_VERSION),
184 				V16, strlen(V16),
185 				strlen(driver_version) - strlen(INTF_CARDTYPE) -
186 					strlen(KERN_VERSION));
187 	}
188 #endif
189 #ifdef PCIE9097
190 	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_88W9097) {
191 		card_type = CARD_TYPE_PCIE9097;
192 		moal_memcpy_ext(NULL, driver_version, CARD_PCIE9097,
193 				strlen(CARD_PCIE9097), strlen(driver_version));
194 		moal_memcpy_ext(NULL,
195 				driver_version + strlen(INTF_CARDTYPE) +
196 					strlen(KERN_VERSION),
197 				V17, strlen(V17),
198 				strlen(driver_version) - strlen(INTF_CARDTYPE) -
199 					strlen(KERN_VERSION));
200 	}
201 #endif
202 #ifdef PCIE9098
203 	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_88W9098P_FN0 ||
204 	    cardp_pcie->dev->device == PCIE_DEVICE_ID_88W9098P_FN1) {
205 		card_type = CARD_TYPE_PCIE9098;
206 		moal_memcpy_ext(NULL, driver_version, CARD_PCIE9098,
207 				strlen(CARD_PCIE9098), strlen(driver_version));
208 		moal_memcpy_ext(NULL,
209 				driver_version + strlen(INTF_CARDTYPE) +
210 					strlen(KERN_VERSION),
211 				V17, strlen(V17),
212 				strlen(driver_version) - strlen(INTF_CARDTYPE) -
213 					strlen(KERN_VERSION));
214 	}
215 #endif
216 #ifdef PCIENW62X
217 	if (cardp_pcie->dev->device == PCIE_DEVICE_ID_88WNW62X) {
218 		card_type = CARD_TYPE_PCIENW62X;
219 		moal_memcpy_ext(NULL, driver_version, CARD_PCIENW62X,
220 				strlen(CARD_PCIENW62X), strlen(driver_version));
221 		moal_memcpy_ext(NULL,
222 				driver_version + strlen(INTF_CARDTYPE) +
223 					strlen(KERN_VERSION),
224 				V17, strlen(V17),
225 				strlen(driver_version) - strlen(INTF_CARDTYPE) -
226 					strlen(KERN_VERSION));
227 	}
228 #endif
229 
230 	return card_type;
231 }
232 
233 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
234 /**
235  * @brief Function to process pre/post PCIe function level reset
236  *
237  * @param handle    A pointer to moal_handle structure
238  * @param prepare   True :- its a pre FLR call from the kernel
239  *		    False :- its a post FLR call from the kernel
240  * @param flr       True: call from FLR
241  *
242  * Note: This function is mix of woal_switch_drv_mode() and
243  * remove_card(). Idea is to cleanup the software only without
244  * touching the PCIe specific code. Likewise, during init init
245  * everything, including hw, but do not reinitiate PCIe stack
246  *
247  * @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
248  */
woal_do_flr(moal_handle * handle,bool prepare,bool flr_flag)249 static mlan_status woal_do_flr(moal_handle *handle, bool prepare, bool flr_flag)
250 {
251 	unsigned int i;
252 	int index = 0;
253 	mlan_status status = MLAN_STATUS_SUCCESS;
254 	moal_private *priv = NULL;
255 	pcie_service_card *card = NULL;
256 	int fw_serial_bkp = 0;
257 
258 	ENTER();
259 
260 	if (!handle) {
261 		PRINTM(MINFO, "\n Handle null during prepare=%d\n", prepare);
262 		LEAVE();
263 		return status;
264 	}
265 
266 	card = (pcie_service_card *)handle->card;
267 
268 	if (card == NULL) {
269 		PRINTM(MERROR, "The parameter 'card' is NULL\n");
270 		LEAVE();
271 		return (mlan_status)MLAN_STATUS_FAILURE;
272 	}
273 
274 	if (!IS_PCIE8997(handle->card_type) &&
275 	    !IS_PCIE9097(handle->card_type) &&
276 	    !IS_PCIENW62X(handle->card_type) &&
277 	    !IS_PCIE9098(handle->card_type)) {
278 		LEAVE();
279 		return status;
280 	}
281 
282 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
283 		goto exit_sem_err;
284 
285 	if (!prepare)
286 		goto perform_init;
287 
288 	/* Reset all interfaces */
289 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
290 	woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE);
291 
292 	/* Shutdown firmware */
293 	handle->init_wait_q_woken = MFALSE;
294 	status = mlan_shutdown_fw(handle->pmlan_adapter);
295 
296 	if (status == MLAN_STATUS_PENDING)
297 		wait_event_interruptible(handle->init_wait_q,
298 					 handle->init_wait_q_woken);
299 
300 	if (atomic_read(&handle->rx_pending) ||
301 	    atomic_read(&handle->tx_pending) ||
302 	    atomic_read(&handle->ioctl_pending)) {
303 		PRINTM(MERROR,
304 		       "ERR: rx_pending=%d,tx_pending=%d,ioctl_pending=%d\n",
305 		       atomic_read(&handle->rx_pending),
306 		       atomic_read(&handle->tx_pending),
307 		       atomic_read(&handle->ioctl_pending));
308 	}
309 
310 	unregister_inetaddr_notifier(&handle->woal_notifier);
311 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
312 #if IS_ENABLED(CONFIG_IPV6)
313 	unregister_inet6addr_notifier(&handle->woal_inet6_notifier);
314 #endif
315 #endif
316 
317 #ifdef WIFI_DIRECT_SUPPORT
318 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
319 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
320 	/* Remove virtual interface */
321 	woal_remove_virtual_interface(handle);
322 #endif
323 #endif
324 #endif
325 
326 	/* Remove interface */
327 	for (i = 0; i < handle->priv_num; i++)
328 		woal_remove_interface(handle, i);
329 
330 	/* Unregister mlan */
331 	if (handle->pmlan_adapter) {
332 		mlan_unregister(handle->pmlan_adapter);
333 		if (atomic_read(&handle->lock_count) ||
334 		    atomic_read(&handle->malloc_count) ||
335 		    atomic_read(&handle->mbufalloc_count)) {
336 			PRINTM(MERROR,
337 			       "mlan has memory leak: lock_count=%d,"
338 			       " malloc_count=%d, mbufalloc_count=%d\n",
339 			       atomic_read(&handle->lock_count),
340 			       atomic_read(&handle->malloc_count),
341 			       atomic_read(&handle->mbufalloc_count));
342 		}
343 		if (atomic_read(&handle->malloc_cons_count)) {
344 			PRINTM(MERROR,
345 			       "mlan has memory leak: malloc_cons_count=%d\n",
346 			       atomic_read(&handle->malloc_cons_count));
347 		}
348 		handle->pmlan_adapter = NULL;
349 	}
350 
351 	goto exit;
352 
353 perform_init:
354 	handle->priv_num = 0;
355 
356 	/* Init SW */
357 	if (woal_init_sw(handle)) {
358 		PRINTM(MFATAL, "Software Init Failed\n");
359 		goto err_init_fw;
360 	}
361 
362 #ifdef PCIE9098
363 	if (card->dev->device == PCIE_DEVICE_ID_88W9098P_FN1)
364 		mlan_set_int_mode(handle->pmlan_adapter, pcie_int_mode, 1);
365 	else
366 #endif
367 		/* Update pcie_int_mode in mlan adapter */
368 		mlan_set_int_mode(handle->pmlan_adapter,
369 				  handle->params.pcie_int_mode, 0);
370 
371 	/* Init FW and HW */
372 	/* Load wlan only binary */
373 	if (flr_flag) {
374 		fw_serial_bkp = moal_extflg_isset(handle, EXT_FW_SERIAL);
375 		moal_extflg_clear(handle, EXT_FW_SERIAL);
376 		woal_update_firmware_name(handle);
377 	}
378 	if (woal_init_fw(handle)) {
379 		PRINTM(MFATAL, "Firmware Init Failed\n");
380 		woal_pcie_reg_dbg(handle);
381 		if (fw_serial_bkp)
382 			moal_extflg_set(handle, EXT_FW_SERIAL);
383 		goto err_init_fw;
384 	}
385 	if (flr_flag && fw_serial_bkp)
386 		moal_extflg_set(handle, EXT_FW_SERIAL);
387 	if (IS_PCIE9098(handle->card_type))
388 		handle->event_fw_dump = MTRUE;
389 exit:
390 	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
391 
392 exit_sem_err:
393 	LEAVE();
394 	return status;
395 
396 err_init_fw:
397 	if ((handle->hardware_status == HardwareStatusFwReady) ||
398 	    (handle->hardware_status == HardwareStatusReady)) {
399 		PRINTM(MINFO, "shutdown mlan\n");
400 		handle->init_wait_q_woken = MFALSE;
401 		status = mlan_shutdown_fw(handle->pmlan_adapter);
402 		if (status == MLAN_STATUS_PENDING)
403 			wait_event_interruptible(handle->init_wait_q,
404 						 handle->init_wait_q_woken);
405 	}
406 #ifdef ANDROID_KERNEL
407 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
408 	wakeup_source_trash(&handle->ws);
409 #else
410 	wake_lock_destroy(&handle->wake_lock);
411 #endif
412 #endif
413 #ifdef CONFIG_PROC_FS
414 	woal_proc_exit(handle);
415 #endif
416 	/* Unregister device */
417 	PRINTM(MINFO, "unregister device\n");
418 	woal_pcie_unregister_dev(handle);
419 	handle->surprise_removed = MTRUE;
420 #ifdef REASSOCIATION
421 	if (handle->reassoc_thread.pid)
422 		wake_up_interruptible(&handle->reassoc_thread.wait_q);
423 	/* waiting for main thread quit */
424 	while (handle->reassoc_thread.pid)
425 		woal_sched_timeout(2);
426 #endif /* REASSOCIATION */
427 	woal_terminate_workqueue(handle);
428 	woal_free_moal_handle(handle);
429 
430 	for (index = 0; index < MAX_MLAN_ADAPTER; index++) {
431 		if (m_handle[index] == handle)
432 			break;
433 	}
434 	if (index < MAX_MLAN_ADAPTER)
435 		m_handle[index] = NULL;
436 	card->handle = NULL;
437 	MOAL_REL_SEMAPHORE(&AddRemoveCardSem);
438 	LEAVE();
439 	return (mlan_status)MLAN_STATUS_FAILURE;
440 }
441 #endif
442 
443 /**
444  *  @brief This function handles PCIE driver probe
445  *
446  *  @param pdev     A pointer to pci_dev structure
447  *  @param id       A pointer to pci_device_id structure
448  *
449  *  @return         error code
450  */
woal_pcie_probe(struct pci_dev * pdev,const struct pci_device_id * id)451 static int woal_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
452 {
453 	pcie_service_card *card = NULL;
454 	t_u16 card_type = 0;
455 	int ret = 0;
456 
457 	ENTER();
458 
459 	PRINTM(MINFO, "vendor=0x%4.04X device=0x%4.04X rev=%d\n", pdev->vendor,
460 	       pdev->device, pdev->revision);
461 
462 	/* Preinit PCIE device so allocate PCIE memory can be successful */
463 	if (woal_pcie_preinit(pdev)) {
464 		PRINTM(MFATAL, "MOAL PCIE preinit failed\n");
465 		LEAVE();
466 		return -EFAULT;
467 	}
468 
469 	card = kzalloc(sizeof(pcie_service_card), GFP_KERNEL);
470 	if (!card) {
471 		PRINTM(MERROR, "%s: failed to alloc memory\n", __func__);
472 		ret = -ENOMEM;
473 		goto err;
474 	}
475 
476 	card->dev = pdev;
477 
478 	card_type = woal_update_card_type(card);
479 	if (!card_type) {
480 		PRINTM(MERROR, "pcie probe: woal_update_card_type() failed\n");
481 		ret = MLAN_STATUS_FAILURE;
482 		goto err;
483 	}
484 	if (MLAN_STATUS_SUCCESS != woal_pcie_init(card)) {
485 		PRINTM(MERROR, "woal_pcie_init failed\n");
486 		ret = -EFAULT;
487 		goto err;
488 	}
489 
490 	if (woal_add_card(card, &card->dev->dev, &pcie_ops, card_type) ==
491 	    NULL) {
492 		woal_pcie_cleanup(card);
493 		PRINTM(MERROR, "%s: failed\n", __func__);
494 		ret = -EFAULT;
495 		goto err;
496 	}
497 
498 #ifdef IMX_SUPPORT
499 	woal_regist_oob_wakeup_irq(card->handle);
500 #endif /* IMX_SUPPORT */
501 
502 	LEAVE();
503 	return ret;
504 err:
505 	kfree(card);
506 	if (pci_is_enabled(pdev))
507 		pci_disable_device(pdev);
508 
509 	LEAVE();
510 	return ret;
511 }
512 
513 /**
514  *  @brief This function handles PCIE driver remove
515  *
516  *  @param pdev     A pointer to pci_dev structure
517  *
518  *  @return         error code
519  */
woal_pcie_remove(struct pci_dev * dev)520 static void woal_pcie_remove(struct pci_dev *dev)
521 {
522 	pcie_service_card *card;
523 	moal_handle *handle;
524 
525 	ENTER();
526 	card = pci_get_drvdata(dev);
527 	if (!card) {
528 		PRINTM(MINFO, "PCIE card removed from slot\n");
529 		LEAVE();
530 		return;
531 	}
532 
533 	handle = card->handle;
534 	if (!handle || !handle->priv_num) {
535 		PRINTM(MINFO, "PCIE card handle removed\n");
536 		LEAVE();
537 		return;
538 	}
539 	handle->surprise_removed = MTRUE;
540 
541 #ifdef IMX_SUPPORT
542 	woal_unregist_oob_wakeup_irq(card->handle);
543 #endif /* IMX_SUPPORT */
544 	woal_remove_card(card);
545 	woal_pcie_cleanup(card);
546 	kfree(card);
547 
548 	LEAVE();
549 	return;
550 }
551 
552 /**
553  *  @brief This function handles PCIE driver remove
554  *
555  *  @param pdev     A pointer to pci_dev structure
556  *
557  *  @return         error code
558  */
woal_pcie_shutdown(struct pci_dev * dev)559 static void woal_pcie_shutdown(struct pci_dev *dev)
560 {
561 	pcie_service_card *card;
562 	moal_handle *handle;
563 
564 	ENTER();
565 	PRINTM(MCMND, "<--- Enter woal_pcie_shutdown --->\n");
566 
567 	card = pci_get_drvdata(dev);
568 	if (!card) {
569 		PRINTM(MINFO, "PCIE card removed from slot\n");
570 		LEAVE();
571 		return;
572 	}
573 	handle = card->handle;
574 	if (handle->second_mac)
575 		goto done;
576 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
577 	if (IS_PCIE9098(handle->card_type) || IS_PCIENW62X(handle->card_type) ||
578 	    IS_PCIE9097(handle->card_type)) {
579 		if (RDWR_STATUS_FAILURE !=
580 		    woal_pcie_rdwr_firmware(handle, 0, 1))
581 			PRINTM(MMSG, "wlan: start in-bound IR...\n");
582 	}
583 #endif
584 done:
585 	handle->surprise_removed = MTRUE;
586 	pci_disable_device(dev);
587 	PRINTM(MCMND, "<--- Leave woal_pcie_shutdown --->\n");
588 	LEAVE();
589 	return;
590 }
591 
592 /**
593  *  @brief Handle suspend
594  *
595  *  @param pdev     A pointer to pci_dev structure
596  *  @param state    PM state message
597  *
598  *  @return         error code
599  */
woal_pcie_suspend(struct pci_dev * pdev,pm_message_t state)600 static int woal_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
601 {
602 	pcie_service_card *cardp;
603 	moal_handle *handle = NULL;
604 	moal_handle *ref_handle = NULL;
605 	int i;
606 	int ret = MLAN_STATUS_SUCCESS;
607 	int hs_actived;
608 	mlan_ds_ps_info pm_info;
609 	int keep_power = 0;
610 
611 	ENTER();
612 	if (pdev) {
613 		cardp = (pcie_service_card *)pci_get_drvdata(pdev);
614 		if (!cardp || !cardp->handle) {
615 			LEAVE();
616 			return MLAN_STATUS_SUCCESS;
617 		}
618 	} else {
619 		PRINTM(MERROR, "PCIE device is not specified\n");
620 		LEAVE();
621 		return -ENOSYS;
622 	}
623 
624 	handle = cardp->handle;
625 	if (handle->second_mac)
626 		PRINTM(MCMND, "<--- Enter woal_pcie_suspend# --->\n");
627 	else
628 		PRINTM(MCMND, "<--- Enter woal_pcie_suspend --->\n");
629 	if (handle->is_suspended == MTRUE) {
630 		PRINTM(MWARN, "Device already suspended\n");
631 		LEAVE();
632 		return MLAN_STATUS_SUCCESS;
633 	}
634 	if (handle->fw_dump) {
635 		PRINTM(MMSG, "suspend not allowed while FW dump!");
636 		ret = -EBUSY;
637 		goto done;
638 	}
639 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
640 		if (handle->priv[i] &&
641 		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA))
642 			woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT);
643 	}
644 	handle->suspend_fail = MFALSE;
645 	memset(&pm_info, 0, sizeof(pm_info));
646 #define MAX_RETRY_NUM 8
647 	for (i = 0; i < MAX_RETRY_NUM; i++) {
648 		if (MLAN_STATUS_SUCCESS ==
649 		    woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
650 				     &pm_info)) {
651 			if (pm_info.is_suspend_allowed == MTRUE)
652 				break;
653 			else
654 				PRINTM(MMSG,
655 				       "Suspend not allowed and retry again\n");
656 		}
657 		woal_sched_timeout(100);
658 	}
659 	if (pm_info.is_suspend_allowed == MFALSE) {
660 		PRINTM(MMSG, "Suspend not allowed\n");
661 		ret = -EBUSY;
662 		goto done;
663 	}
664 
665 	for (i = 0; i < handle->priv_num; i++)
666 		netif_device_detach(handle->priv[i]->netdev);
667 	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER))
668 		keep_power = MTRUE;
669 	else
670 		keep_power = MFALSE;
671 
672 	if (keep_power) {
673 		/* Enable Host Sleep */
674 		hs_actived = woal_enable_hs(
675 			woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
676 		if (hs_actived == MTRUE) {
677 			/* Indicate device suspended */
678 			handle->is_suspended = MTRUE;
679 		} else {
680 			PRINTM(MMSG, "HS not actived, suspend fail!");
681 			handle->suspend_fail = MTRUE;
682 			for (i = 0; i < handle->priv_num; i++)
683 				netif_device_attach(handle->priv[i]->netdev);
684 			ret = -EBUSY;
685 			goto done;
686 		}
687 	}
688 	woal_flush_workqueue(handle);
689 	if (!keep_power) {
690 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
691 		woal_do_flr(handle, true, false);
692 #endif
693 		handle->surprise_removed = MTRUE;
694 		handle->is_suspended = MTRUE;
695 	}
696 #ifdef IMX_SUPPORT
697 	woal_enable_oob_wakeup_irq(handle);
698 #endif /* IMX_SUPPORT */
699 	pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
700 	pci_save_state(pdev);
701 	ref_handle = (moal_handle *)handle->pref_mac;
702 	if (ref_handle && ref_handle->is_suspended)
703 		pci_set_power_state(pdev, pci_choose_state(pdev, state));
704 done:
705 	PRINTM(MCMND, "<--- Leave woal_pcie_suspend --->\n");
706 	LEAVE();
707 	return ret;
708 }
709 
710 /**
711  *  @brief Handle resume
712  *
713  *  @param pdev     A pointer to pci_dev structure
714  *
715  *  @return         error code
716  */
woal_pcie_resume(struct pci_dev * pdev)717 static int woal_pcie_resume(struct pci_dev *pdev)
718 {
719 	moal_handle *handle;
720 	pcie_service_card *cardp;
721 	int keep_power = 0;
722 	int i;
723 
724 	ENTER();
725 	if (pdev) {
726 		cardp = (pcie_service_card *)pci_get_drvdata(pdev);
727 		if (!cardp || !cardp->handle) {
728 			PRINTM(MERROR, "Card or handle is not valid\n");
729 			LEAVE();
730 			return MLAN_STATUS_SUCCESS;
731 		}
732 	} else {
733 		PRINTM(MERROR, "PCIE device is not specified\n");
734 		LEAVE();
735 		return -ENOSYS;
736 	}
737 	handle = cardp->handle;
738 	if (handle->second_mac)
739 		PRINTM(MCMND, "<--- Enter woal_pcie_resume# --->\n");
740 	else
741 		PRINTM(MCMND, "<--- Enter woal_pcie_resume --->\n");
742 	if (handle->is_suspended == MFALSE) {
743 		PRINTM(MWARN, "Device already resumed\n");
744 		goto done;
745 	}
746 	handle->is_suspended = MFALSE;
747 
748 	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER))
749 		keep_power = MTRUE;
750 	else
751 		keep_power = MFALSE;
752 
753 	pci_set_power_state(pdev, PCI_D0);
754 	pci_restore_state(pdev);
755 	pci_enable_wake(pdev, PCI_D0, 0);
756 	if (!keep_power) {
757 		handle->surprise_removed = MFALSE;
758 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
759 		woal_do_flr(handle, false, false);
760 #endif
761 	} else {
762 		if (woal_check_driver_status(handle)) {
763 			PRINTM(MERROR, "Resuem, device is in hang state\n");
764 			LEAVE();
765 			return MLAN_STATUS_SUCCESS;
766 		}
767 		for (i = 0; i < handle->priv_num; i++)
768 			netif_device_attach(handle->priv[i]->netdev);
769 
770 		woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
771 			       MOAL_NO_WAIT);
772 #ifdef IMX_SUPPORT
773 		woal_disable_oob_wakeup_irq(handle);
774 #endif /* IMX_SUPPORT */
775 	}
776 done:
777 	PRINTM(MCMND, "<--- Leave woal_pcie_resume --->\n");
778 	LEAVE();
779 	return 0;
780 }
781 
782 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
783 
784 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
785 /**
786  *  @brief Pcie reset prepare handler
787  *
788  *  @param pdev     A pointer to pci_dev structure
789  */
woal_pcie_reset_prepare(struct pci_dev * pdev)790 static void woal_pcie_reset_prepare(struct pci_dev *pdev)
791 {
792 	pcie_service_card *card;
793 	moal_handle *handle;
794 	moal_handle *ref_handle = NULL;
795 
796 	ENTER();
797 
798 	card = pci_get_drvdata(pdev);
799 	if (!card) {
800 		PRINTM(MINFO, "PCIE card removed from slot\n");
801 		LEAVE();
802 		return;
803 	}
804 
805 	handle = card->handle;
806 
807 	if (!handle) {
808 		PRINTM(MINFO, "Invalid handle\n");
809 		LEAVE();
810 		return;
811 	}
812 
813 	PRINTM(MMSG, "%s: vendor=0x%4.04X device=0x%4.04X rev=%d Pre-FLR\n",
814 	       __func__, pdev->vendor, pdev->device, pdev->revision);
815 
816 	/* Kernel would be performing FLR after this notification.
817 	 * Cleanup up all software withouth cleaning anything related to
818 	 * PCIe and HW.
819 	 * Note. FW might not be healthy.
820 	 */
821 	// handle-> mac0 , ref_handle->second mac
822 	if (handle->pref_mac) {
823 		if (handle->second_mac) {
824 			handle = (moal_handle *)handle->pref_mac;
825 			ref_handle = (moal_handle *)handle->pref_mac;
826 		} else {
827 			ref_handle = (moal_handle *)handle->pref_mac;
828 		}
829 	}
830 	handle->surprise_removed = MTRUE;
831 	woal_do_flr(handle, true, true);
832 	if (ref_handle) {
833 		ref_handle->surprise_removed = MTRUE;
834 		woal_do_flr(ref_handle, true, true);
835 	}
836 
837 	LEAVE();
838 }
839 /**
840  *  @brief Pcie reset done handler
841  *
842  *  @param pdev     A pointer to pci_dev structure
843  */
woal_pcie_reset_done(struct pci_dev * pdev)844 static void woal_pcie_reset_done(struct pci_dev *pdev)
845 {
846 	pcie_service_card *card;
847 	moal_handle *handle;
848 	moal_handle *ref_handle = NULL;
849 	ENTER();
850 
851 	card = pci_get_drvdata(pdev);
852 	if (!card) {
853 		PRINTM(MINFO, "PCIE card removed from slot\n");
854 		LEAVE();
855 		return;
856 	}
857 
858 	handle = card->handle;
859 	if (!handle) {
860 		PRINTM(MINFO, "Invalid handle\n");
861 		LEAVE();
862 		return;
863 	}
864 
865 	PRINTM(MMSG, "%s: vendor=0x%4.04X device=0x%4.04X rev=%d Post-FLR\n",
866 	       __func__, pdev->vendor, pdev->device, pdev->revision);
867 
868 	/* Kernel stores and restores PCIe function context before and
869 	 * after performing FLR, respectively.
870 	 *
871 	 * Reconfigure the sw and fw including fw redownload
872 	 */
873 	// handle-> mac0 , ref_handle->second mac
874 	if (handle->pref_mac) {
875 		if (handle->second_mac) {
876 			handle = (moal_handle *)handle->pref_mac;
877 			ref_handle = (moal_handle *)handle->pref_mac;
878 		} else {
879 			ref_handle = (moal_handle *)handle->pref_mac;
880 		}
881 	}
882 	handle->surprise_removed = MFALSE;
883 	woal_do_flr(handle, false, true);
884 	if (ref_handle) {
885 		ref_handle->surprise_removed = MFALSE;
886 		woal_do_flr(ref_handle, false, true);
887 	}
888 
889 	LEAVE();
890 }
891 #else
woal_pcie_reset_notify(struct pci_dev * pdev,bool prepare)892 static void woal_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
893 {
894 	pcie_service_card *card;
895 	moal_handle *handle;
896 	moal_handle *ref_handle = NULL;
897 
898 	ENTER();
899 
900 	card = pci_get_drvdata(pdev);
901 	if (!card) {
902 		PRINTM(MINFO, "PCIE card removed from slot\n");
903 		LEAVE();
904 		return;
905 	}
906 
907 	handle = card->handle;
908 	if (!handle) {
909 		PRINTM(MINFO, "Invalid handle\n");
910 		LEAVE();
911 		return;
912 	}
913 
914 	PRINTM(MMSG, "%s: vendor=0x%4.04X device=0x%4.04X rev=%d %s\n",
915 	       __func__, pdev->vendor, pdev->device, pdev->revision,
916 	       prepare ? "Pre-FLR" : "Post-FLR");
917 
918 	// handle-> mac0 , ref_handle->second mac
919 	if (handle->pref_mac) {
920 		if (handle->second_mac) {
921 			handle = (moal_handle *)handle->pref_mac;
922 			ref_handle = (moal_handle *)handle->pref_mac;
923 		} else {
924 			ref_handle = (moal_handle *)handle->pref_mac;
925 		}
926 	}
927 
928 	if (prepare) {
929 		/* Kernel would be performing FLR after this notification.
930 		 * Cleanup up all software withouth cleaning anything related to
931 		 * PCIe and HW.
932 		 * Note. FW might not be healthy.
933 		 */
934 		handle->surprise_removed = MTRUE;
935 		woal_do_flr(handle, prepare, true);
936 		if (ref_handle) {
937 			ref_handle->surprise_removed = MTRUE;
938 			woal_do_flr(ref_handle, prepare, true);
939 		}
940 	} else {
941 		/* Kernel stores and restores PCIe function context before and
942 		 * after performing FLR, respectively.
943 		 *
944 		 * Reconfigure the sw and fw including fw redownload
945 		 */
946 		handle->surprise_removed = MFALSE;
947 		woal_do_flr(handle, prepare, true);
948 		if (ref_handle) {
949 			ref_handle->surprise_removed = MFALSE;
950 			woal_do_flr(ref_handle, prepare, true);
951 		}
952 	}
953 	LEAVE();
954 }
955 #endif
956 
957 static const struct pci_error_handlers woal_pcie_err_handler[] = {
958 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
959 	{
960 		.reset_prepare = woal_pcie_reset_prepare,
961 		.reset_done = woal_pcie_reset_done,
962 	},
963 #else
964 	{
965 		.reset_notify = woal_pcie_reset_notify,
966 	},
967 #endif
968 };
969 #endif // KERNEL_VERSION(3.18.0)
970 
971 /* PCI Device Driver */
972 static struct pci_driver REFDATA wlan_pcie = {
973 	.name = "wlan_pcie",
974 	.id_table = wlan_ids,
975 	.probe = woal_pcie_probe,
976 	.remove = woal_pcie_remove,
977 	.shutdown = woal_pcie_shutdown,
978 #ifdef CONFIG_PM
979 	/* Power Management Hooks */
980 	.suspend = woal_pcie_suspend,
981 	.resume = woal_pcie_resume,
982 #endif
983 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
984 	.err_handler = woal_pcie_err_handler,
985 #endif
986 };
987 
988 /********************************************************
989 			Global Functions
990 ********************************************************/
991 
992 /**
993  *  @brief This function writes data into card register
994  *
995  *  @param handle   A Pointer to the moal_handle structure
996  *  @param reg      Register offset
997  *  @param data     Value
998  *
999  *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1000  */
woal_pcie_write_reg(moal_handle * handle,t_u32 reg,t_u32 data)1001 static mlan_status woal_pcie_write_reg(moal_handle *handle, t_u32 reg,
1002 				       t_u32 data)
1003 {
1004 	pcie_service_card *card = (pcie_service_card *)handle->card;
1005 
1006 	iowrite32(data, card->pci_mmap1 + reg);
1007 
1008 	return MLAN_STATUS_SUCCESS;
1009 }
1010 
1011 /**
1012  *  @brief This function reads data from card register
1013  *
1014  *  @param handle   A Pointer to the moal_handle structure
1015  *  @param reg      Register offset
1016  *  @param data     Value
1017  *
1018  *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1019  */
woal_pcie_read_reg(moal_handle * handle,t_u32 reg,t_u32 * data)1020 static mlan_status woal_pcie_read_reg(moal_handle *handle, t_u32 reg,
1021 				      t_u32 *data)
1022 {
1023 	pcie_service_card *card = (pcie_service_card *)handle->card;
1024 	*data = ioread32(card->pci_mmap1 + reg);
1025 
1026 	if (*data == MLAN_STATUS_FAILURE)
1027 		return MLAN_STATUS_FAILURE;
1028 
1029 	return MLAN_STATUS_SUCCESS;
1030 }
1031 
1032 /**
1033  *  @brief This function writes multiple bytes into card memory
1034  *
1035  *  @param handle   A Pointer to the moal_handle structure
1036  *  @param pmbuf	Pointer to mlan_buffer structure
1037  *  @param port		Port
1038  *  @param timeout 	Time out value
1039  *
1040  *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1041  */
woal_pcie_write_data_sync(moal_handle * handle,mlan_buffer * pmbuf,t_u32 port,t_u32 timeout)1042 static mlan_status woal_pcie_write_data_sync(moal_handle *handle,
1043 					     mlan_buffer *pmbuf, t_u32 port,
1044 					     t_u32 timeout)
1045 {
1046 	return MLAN_STATUS_SUCCESS;
1047 }
1048 
1049 /**
1050  *  @brief This function reads multiple bytes from card memory
1051  *
1052  *  @param handle   A Pointer to the moal_handle structure
1053  *  @param pmbuf	Pointer to mlan_buffer structure
1054  *  @param port		Port
1055  *  @param timeout 	Time out value
1056  *
1057  *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1058  */
woal_pcie_read_data_sync(moal_handle * handle,mlan_buffer * pmbuf,t_u32 port,t_u32 timeout)1059 static mlan_status woal_pcie_read_data_sync(moal_handle *handle,
1060 					    mlan_buffer *pmbuf, t_u32 port,
1061 					    t_u32 timeout)
1062 {
1063 	return MLAN_STATUS_SUCCESS;
1064 }
1065 
1066 /**
1067  *  @brief This function handles the interrupt.
1068  *
1069  *  @param irq	    The irq no. of PCIE device
1070  *  @param dev_id   A pointer to the pci_dev structure
1071  *
1072  *  @return         IRQ_HANDLED
1073  */
woal_pcie_interrupt(int irq,void * dev_id)1074 static irqreturn_t woal_pcie_interrupt(int irq, void *dev_id)
1075 {
1076 	struct pci_dev *pdev;
1077 	pcie_service_card *card;
1078 	moal_handle *handle;
1079 	mlan_status ret = MLAN_STATUS_SUCCESS;
1080 
1081 	pdev = (struct pci_dev *)dev_id;
1082 	if (!pdev) {
1083 		PRINTM(MFATAL, "%s: pdev is NULL\n", (t_u8 *)pdev);
1084 		goto exit;
1085 	}
1086 
1087 	card = (pcie_service_card *)pci_get_drvdata(pdev);
1088 	if (!card || !card->handle) {
1089 		PRINTM(MFATAL, "%s: card=%p handle=%p\n", __func__, card,
1090 		       card ? card->handle : NULL);
1091 		goto exit;
1092 	}
1093 	handle = card->handle;
1094 	if (handle->surprise_removed == MTRUE) {
1095 		ret = MLAN_STATUS_FAILURE;
1096 		goto exit;
1097 	}
1098 	PRINTM(MINFO, "*** IN PCIE IRQ ***\n");
1099 	handle->main_state = MOAL_RECV_INT;
1100 	if (handle->second_mac)
1101 		PRINTM(MINTR, "**\n");
1102 	else
1103 		PRINTM(MINTR, "*\n");
1104 
1105 	ret = mlan_interrupt(0xffff, handle->pmlan_adapter);
1106 	if (handle->is_suspended) {
1107 		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
1108 		goto exit;
1109 	}
1110 	queue_work(handle->workqueue, &handle->main_work);
1111 
1112 exit:
1113 	if (ret == MLAN_STATUS_SUCCESS)
1114 		return IRQ_HANDLED;
1115 	else
1116 		return IRQ_NONE;
1117 }
1118 
1119 /**
1120  *  @brief This function handles the MSI-X interrupt.
1121  *
1122  *  @param irq	    The irq no. of PCIE device
1123  *  @param dev_id   A pointer to the msix_context structure
1124  *
1125  *  @return         IRQ_HANDLED
1126  */
woal_pcie_msix_interrupt(int irq,void * dev_id)1127 static irqreturn_t woal_pcie_msix_interrupt(int irq, void *dev_id)
1128 {
1129 	struct pci_dev *pdev;
1130 	pcie_service_card *card;
1131 	moal_handle *handle;
1132 	msix_context *ctx = (msix_context *)dev_id;
1133 	mlan_status ret = MLAN_STATUS_SUCCESS;
1134 
1135 	if (!ctx) {
1136 		PRINTM(MFATAL, "%s: ctx=%p is NULL\n", __func__, ctx);
1137 		goto exit;
1138 	}
1139 
1140 	pdev = ctx->dev;
1141 
1142 	if (!pdev) {
1143 		PRINTM(MFATAL, "%s: pdev is NULL\n", (t_u8 *)pdev);
1144 		goto exit;
1145 	}
1146 
1147 	card = (pcie_service_card *)pci_get_drvdata(pdev);
1148 	if (!card || !card->handle) {
1149 		PRINTM(MFATAL, "%s: card=%p handle=%p\n", __func__, card,
1150 		       card ? card->handle : NULL);
1151 		goto exit;
1152 	}
1153 	handle = card->handle;
1154 	if (handle->surprise_removed == MTRUE) {
1155 		ret = MLAN_STATUS_FAILURE;
1156 		goto exit;
1157 	}
1158 	PRINTM(MINFO, "*** IN PCIE IRQ ***\n");
1159 	handle->main_state = MOAL_RECV_INT;
1160 	if (handle->second_mac)
1161 		PRINTM(MINTR, "**\n");
1162 	else
1163 		PRINTM(MINTR, "*\n");
1164 	ret = mlan_interrupt(ctx->msg_id, handle->pmlan_adapter);
1165 	queue_work(handle->workqueue, &handle->main_work);
1166 
1167 exit:
1168 	if (ret == MLAN_STATUS_SUCCESS)
1169 		return IRQ_HANDLED;
1170 	else
1171 		return IRQ_NONE;
1172 }
1173 /**
1174  *  @brief This function pre-initializes the PCI-E host
1175  *  memory space, etc.
1176  *
1177  *  @param handle   A pointer to moal_handle structure
1178  *
1179  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1180  */
woal_pcie_preinit(struct pci_dev * pdev)1181 static mlan_status woal_pcie_preinit(struct pci_dev *pdev)
1182 {
1183 	int ret;
1184 
1185 	if (pdev->multifunction)
1186 		device_disable_async_suspend(&pdev->dev);
1187 
1188 	ret = pci_enable_device(pdev);
1189 
1190 	if (ret)
1191 		goto err_enable_dev;
1192 
1193 	pci_set_master(pdev);
1194 
1195 	PRINTM(MINFO, "Try set_consistent_dma_mask(32)\n");
1196 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
1197 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
1198 #else
1199 	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
1200 #endif
1201 	if (ret) {
1202 		PRINTM(MERROR, "set_dma_mask(32) failed\n");
1203 		goto err_set_dma_mask;
1204 	}
1205 
1206 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
1207 	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
1208 #else
1209 	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
1210 #endif
1211 	if (ret) {
1212 		PRINTM(MERROR, "set_consistent_dma_mask(64) failed\n");
1213 		goto err_set_dma_mask;
1214 	}
1215 	return MLAN_STATUS_SUCCESS;
1216 
1217 err_set_dma_mask:
1218 	pci_disable_device(pdev);
1219 err_enable_dev:
1220 	return MLAN_STATUS_FAILURE;
1221 }
1222 
1223 /**
1224  *  @brief This function initializes the PCI-E host
1225  *  memory space, etc.
1226  *
1227  *  @param card   A pointer to pcie_service_card structure
1228  *
1229  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1230  */
woal_pcie_init(pcie_service_card * card)1231 static mlan_status woal_pcie_init(pcie_service_card *card)
1232 {
1233 	struct pci_dev *pdev = NULL;
1234 	int ret;
1235 
1236 	pdev = card->dev;
1237 	pci_set_drvdata(pdev, card);
1238 #if 0
1239 	ret = pci_enable_device(pdev);
1240 	if (ret)
1241 		goto err_enable_dev;
1242 
1243 	pci_set_master(pdev);
1244 
1245 	PRINTM(MINFO, "Try set_consistent_dma_mask(32)\n");
1246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
1247 	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
1248 #else
1249 	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
1250 #endif
1251 	if (ret) {
1252 		PRINTM(MERROR, "set_dma_mask(32) failed\n");
1253 		goto err_set_dma_mask;
1254 	}
1255 
1256 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
1257 	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
1258 #else
1259 	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
1260 #endif
1261 	if (ret) {
1262 		PRINTM(MERROR, "set_consistent_dma_mask(64) failed\n");
1263 		goto err_set_dma_mask;
1264 	}
1265 #endif
1266 
1267 	ret = pci_request_region(pdev, 0, DRV_NAME);
1268 	if (ret) {
1269 		PRINTM(MERROR, "req_reg(0) error\n");
1270 		goto err_req_region0;
1271 	}
1272 	card->pci_mmap = pci_iomap(pdev, 0, 0);
1273 	if (!card->pci_mmap) {
1274 		PRINTM(MERROR, "iomap(0) error\n");
1275 		goto err_iomap0;
1276 	}
1277 	ret = pci_request_region(pdev, 2, DRV_NAME);
1278 	if (ret) {
1279 		PRINTM(MERROR, "req_reg(2) error\n");
1280 		goto err_req_region2;
1281 	}
1282 	card->pci_mmap1 = pci_iomap(pdev, 2, 0);
1283 	if (!card->pci_mmap1) {
1284 		PRINTM(MERROR, "iomap(2) error\n");
1285 		goto err_iomap2;
1286 	}
1287 
1288 	PRINTM(MINFO,
1289 	       "PCI memory map Virt0: %p PCI memory map Virt2: "
1290 	       "%p\n",
1291 	       card->pci_mmap, card->pci_mmap1);
1292 
1293 	return MLAN_STATUS_SUCCESS;
1294 
1295 err_iomap2:
1296 	pci_release_region(pdev, 2);
1297 err_req_region2:
1298 	pci_iounmap(pdev, card->pci_mmap);
1299 err_iomap0:
1300 	pci_release_region(pdev, 0);
1301 err_req_region0:
1302 #if 0
1303 err_set_dma_mask:
1304 #endif
1305 
1306 #if 0
1307 err_enable_dev:
1308 #endif
1309 	pci_set_drvdata(pdev, NULL);
1310 	return MLAN_STATUS_FAILURE;
1311 }
1312 
1313 /**
1314  *  @brief This function registers the PCIE device
1315  *
1316  *  @param handle   A pointer to moal_handle structure
1317  *
1318  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1319  */
woal_pcie_register_dev(moal_handle * handle)1320 static mlan_status woal_pcie_register_dev(moal_handle *handle)
1321 {
1322 	mlan_status ret = MLAN_STATUS_SUCCESS;
1323 	pcie_service_card *card = NULL;
1324 	struct pci_dev *pdev = NULL;
1325 	unsigned char nvec;
1326 	unsigned char i, j;
1327 	ENTER();
1328 
1329 	if (!handle || !handle->card) {
1330 		PRINTM(MINFO, "%s: handle=%p card=%p\n", __FUNCTION__, handle,
1331 		       handle ? handle->card : NULL);
1332 		LEAVE();
1333 		return MLAN_STATUS_FAILURE;
1334 	}
1335 
1336 	card = (pcie_service_card *)handle->card;
1337 	pdev = card->dev;
1338 	/* save adapter pointer in card */
1339 	card->handle = handle;
1340 
1341 	switch (pcie_int_mode) {
1342 	case PCIE_INT_MODE_MSIX:
1343 		pcie_int_mode = PCIE_INT_MODE_MSIX;
1344 		nvec = PCIE_NUM_MSIX_VECTORS;
1345 
1346 		for (i = 0; i < nvec; i++) {
1347 			card->msix_entries[i].entry = i;
1348 		}
1349 
1350 		/* Try to enable msix */
1351 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1352 		ret = pci_enable_msix_exact(pdev, card->msix_entries, nvec);
1353 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */
1354 		ret = pci_enable_msix(pdev, card->msix_entries, nvec);
1355 #endif
1356 
1357 		if (ret == 0) {
1358 			for (i = 0; i < nvec; i++) {
1359 				card->msix_contexts[i].dev = pdev;
1360 				card->msix_contexts[i].msg_id = i;
1361 				ret = request_irq(card->msix_entries[i].vector,
1362 						  woal_pcie_msix_interrupt, 0,
1363 						  "mrvl_pcie_msix",
1364 						  &(card->msix_contexts[i]));
1365 
1366 				if (ret) {
1367 					PRINTM(MFATAL,
1368 					       "request_irq failed: ret=%d\n",
1369 					       ret);
1370 					for (j = 0; j < i; j++)
1371 						free_irq(card->msix_entries[j]
1372 								 .vector,
1373 							 &(card->msix_contexts
1374 								   [i]));
1375 					pci_disable_msix(pdev);
1376 					break;
1377 				}
1378 			}
1379 			if (i == nvec)
1380 				break;
1381 		}
1382 		// follow through
1383 
1384 		/* fall through */
1385 	case PCIE_INT_MODE_MSI:
1386 		pcie_int_mode = PCIE_INT_MODE_MSI;
1387 		ret = pci_enable_msi(pdev);
1388 		if (ret == 0) {
1389 			ret = request_irq(pdev->irq, woal_pcie_interrupt, 0,
1390 					  "mrvl_pcie_msi", pdev);
1391 			if (ret) {
1392 				PRINTM(MFATAL, "request_irq failed: ret=%d\n",
1393 				       ret);
1394 				pci_disable_msi(pdev);
1395 			} else {
1396 				break;
1397 			}
1398 		}
1399 		// follow through
1400 
1401 		/* fall through */
1402 	case PCIE_INT_MODE_LEGACY:
1403 		pcie_int_mode = PCIE_INT_MODE_LEGACY;
1404 		ret = request_irq(pdev->irq, woal_pcie_interrupt, IRQF_SHARED,
1405 				  "mrvl_pcie", pdev);
1406 		if (ret) {
1407 			PRINTM(MFATAL, "request_irq failed: ret=%d\n", ret);
1408 			ret = MLAN_STATUS_FAILURE;
1409 			goto done;
1410 		}
1411 
1412 		break;
1413 
1414 	default:
1415 		PRINTM(MFATAL, "pcie_int_mode %d failed\n", pcie_int_mode);
1416 		ret = MLAN_STATUS_FAILURE;
1417 		goto done;
1418 		break;
1419 	}
1420 
1421 #ifdef PCIE9098
1422 	if (card->dev->device == PCIE_DEVICE_ID_88W9098P_FN1)
1423 		mlan_set_int_mode(handle->pmlan_adapter, pcie_int_mode, 1);
1424 	else
1425 #endif
1426 		mlan_set_int_mode(handle->pmlan_adapter, pcie_int_mode, 0);
1427 
1428 done:
1429 	LEAVE();
1430 	return ret;
1431 }
1432 
1433 /**
1434  *  @brief This function cleans up the host memory spaces
1435  *
1436  *  @param card   A pointer to pcie_service_card structure
1437  *
1438  *  @return         N/A
1439  */
woal_pcie_cleanup(pcie_service_card * card)1440 static void woal_pcie_cleanup(pcie_service_card *card)
1441 {
1442 	struct pci_dev *pdev = NULL;
1443 	pdev = card->dev;
1444 	PRINTM(MINFO, "Clearing driver ready signature\n");
1445 
1446 	if (pdev) {
1447 		pci_iounmap(pdev, card->pci_mmap);
1448 		pci_iounmap(pdev, card->pci_mmap1);
1449 
1450 		if (pci_is_enabled(pdev))
1451 			pci_disable_device(pdev);
1452 
1453 		pci_release_region(pdev, 0);
1454 		pci_release_region(pdev, 2);
1455 		pci_set_drvdata(pdev, NULL);
1456 	}
1457 }
1458 
1459 /**
1460  *  @brief This function unregisters the PCIE device
1461  *
1462  *  @param handle   A pointer to moal_handle structure
1463  *
1464  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1465  */
woal_pcie_unregister_dev(moal_handle * handle)1466 static void woal_pcie_unregister_dev(moal_handle *handle)
1467 {
1468 	pcie_service_card *card =
1469 		handle ? (pcie_service_card *)handle->card : NULL;
1470 	struct pci_dev *pdev = NULL;
1471 	unsigned char i;
1472 	unsigned char nvec;
1473 	ENTER();
1474 
1475 	if (card) {
1476 		pdev = card->dev;
1477 		PRINTM(MINFO, "%s(): calling free_irq()\n", __func__);
1478 
1479 		switch (pcie_int_mode) {
1480 		case PCIE_INT_MODE_MSIX:
1481 			nvec = PCIE_NUM_MSIX_VECTORS;
1482 
1483 			for (i = 0; i < nvec; i++)
1484 				synchronize_irq(card->msix_entries[i].vector);
1485 
1486 			for (i = 0; i < nvec; i++)
1487 				free_irq(card->msix_entries[i].vector,
1488 					 &(card->msix_contexts[i]));
1489 
1490 			pci_disable_msix(pdev);
1491 
1492 			break;
1493 
1494 		case PCIE_INT_MODE_MSI:
1495 			free_irq(card->dev->irq, pdev);
1496 			pci_disable_msi(pdev);
1497 			break;
1498 
1499 		case PCIE_INT_MODE_LEGACY:
1500 			free_irq(card->dev->irq, pdev);
1501 			break;
1502 
1503 		default:
1504 			PRINTM(MFATAL, "pcie_int_mode %d failed\n",
1505 			       pcie_int_mode);
1506 			break;
1507 		}
1508 		card->handle = NULL;
1509 	}
1510 	LEAVE();
1511 }
1512 
1513 /**
1514  *  @brief This function registers the IF module in bus driver
1515  *
1516  *  @return	    MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1517  */
woal_pcie_bus_register(void)1518 mlan_status woal_pcie_bus_register(void)
1519 {
1520 	mlan_status ret = MLAN_STATUS_SUCCESS;
1521 	ENTER();
1522 
1523 	/* API registers the NXP PCIE driver */
1524 	if (pci_register_driver(&wlan_pcie)) {
1525 		PRINTM(MFATAL, "PCIE Driver Registration Failed \n");
1526 		ret = MLAN_STATUS_FAILURE;
1527 	}
1528 
1529 	LEAVE();
1530 	return ret;
1531 }
1532 
1533 /**
1534  *  @brief This function de-registers the IF module in bus driver
1535  *
1536  *  @return 	   N/A
1537  */
woal_pcie_bus_unregister(void)1538 void woal_pcie_bus_unregister(void)
1539 {
1540 	ENTER();
1541 
1542 	/* PCIE Driver Unregistration */
1543 	pci_unregister_driver(&wlan_pcie);
1544 
1545 	LEAVE();
1546 }
1547 
1548 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1549 #define PCIE9098_DUMP_CTRL_REG 0x1C94
1550 #define PCIE9098_DUMP_START_REG 0x1C98
1551 #define PCIE9098_DUMP_END_REG 0x1C9F
1552 #endif
1553 #if defined(PCIE8897) || defined(PCIE8997)
1554 #define DEBUG_DUMP_CTRL_REG 0xCF4
1555 #define DEBUG_DUMP_START_REG 0xCF8
1556 #define DEBUG_DUMP_END_REG 0xCFF
1557 #endif
1558 
1559 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1560 #define PCIE9098_SCRATCH_12_REG 0x1C90
1561 #define PCIE9098_SCRATCH_14_REG 0x1C98
1562 #define PCIE9098_SCRATCH_15_REG 0x1C9C
1563 #define PCIE9098_DUMP_REG_START 0x1C20
1564 #define PCIE9098_DUMP_REG_END 0x1C9C
1565 #endif
1566 
1567 #if defined(PCIE8997) || defined(PCIE8897)
1568 #define PCIE_SCRATCH_12_REG 0x0CF0;
1569 #define PCIE_SCRATCH_14_REG 0x0CF8;
1570 #define PCIE_SCRATCH_15_REG 0x0CFC;
1571 #define PCIE_DUMP_START_REG 0xC00
1572 #define PCIE_DUMP_END_REG 0xCFC
1573 #endif
1574 /**
1575  *  @brief This function save the log of pcie register value
1576  *
1577  *  @param phandle   A pointer to moal_handle
1578  *  @param buffer    A pointer to buffer saving log
1579  *
1580  *  @return         The length of this log
1581  */
woal_pcie_dump_reg_info(moal_handle * phandle,t_u8 * buffer)1582 static int woal_pcie_dump_reg_info(moal_handle *phandle, t_u8 *buffer)
1583 {
1584 	char *drv_ptr = (char *)buffer;
1585 	t_u32 reg = 0, value = 0;
1586 	t_u8 i;
1587 	char buf[256], *ptr;
1588 	pcie_service_card *card = (pcie_service_card *)phandle->card;
1589 	int config_reg_table[] = {0x00, 0x04, 0x10, 0x18, 0x2c,
1590 				  0x3c, 0x44, 0x80, 0x98, 0x170};
1591 	t_u32 dump_start_reg = 0;
1592 	t_u32 dump_end_reg = 0;
1593 	t_u32 scratch_14_reg = 0;
1594 	t_u32 scratch_15_reg = 0;
1595 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1596 	/* Tx/Rx/Event AMDA start address */
1597 	t_u32 adma_reg_table[] = {0x10000, 0x10800, 0x10880, 0x11000, 0x11080};
1598 	t_u8 j;
1599 #endif
1600 	ENTER();
1601 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
1602 	drv_ptr += sprintf(drv_ptr,
1603 			   "------------PCIe Registers dump-------------\n");
1604 	drv_ptr += sprintf(drv_ptr, "Config Space Registers:\n");
1605 	for (i = 0; i < ARRAY_SIZE(config_reg_table); i++) {
1606 		pci_read_config_dword(card->dev, config_reg_table[i], &value);
1607 		drv_ptr += sprintf(drv_ptr, "reg:0x%02x value=0x%08x\n",
1608 				   config_reg_table[i], value);
1609 	}
1610 	drv_ptr += sprintf(drv_ptr, "FW Scrach Registers:\n");
1611 
1612 #if defined(PCIE8897) || defined(PCIE8997)
1613 	if (IS_PCIE8897(phandle->card_type) ||
1614 	    IS_PCIE8997(phandle->card_type)) {
1615 		reg = PCIE_SCRATCH_12_REG;
1616 		dump_start_reg = PCIE_DUMP_START_REG;
1617 		dump_end_reg = PCIE_DUMP_END_REG;
1618 		scratch_14_reg = PCIE_SCRATCH_14_REG;
1619 		scratch_15_reg = PCIE_SCRATCH_15_REG;
1620 	}
1621 #endif
1622 
1623 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1624 	if (IS_PCIE9098(phandle->card_type) ||
1625 	    IS_PCIENW62X(phandle->card_type) ||
1626 	    IS_PCIE9097(phandle->card_type)) {
1627 		reg = PCIE9098_SCRATCH_12_REG;
1628 		dump_start_reg = PCIE9098_DUMP_REG_START;
1629 		dump_end_reg = PCIE9098_DUMP_REG_END;
1630 		scratch_14_reg = PCIE9098_SCRATCH_14_REG;
1631 		scratch_15_reg = PCIE9098_SCRATCH_15_REG;
1632 	}
1633 #endif
1634 
1635 	woal_pcie_read_reg(phandle, reg, &value);
1636 	drv_ptr += sprintf(drv_ptr, "reg:0x%x value=0x%x\n", reg, value);
1637 	for (i = 0; i < 2; i++) {
1638 		reg = scratch_14_reg;
1639 		woal_pcie_read_reg(phandle, reg, &value);
1640 		drv_ptr +=
1641 			sprintf(drv_ptr, "reg:0x%x value=0x%x\n", reg, value);
1642 
1643 		reg = scratch_15_reg;
1644 		woal_pcie_read_reg(phandle, reg, &value);
1645 		drv_ptr +=
1646 			sprintf(drv_ptr, "reg:0x%x value=0x%x\n", reg, value);
1647 
1648 		mdelay(100);
1649 	}
1650 	drv_ptr +=
1651 		sprintf(drv_ptr,
1652 			"Interface registers dump from offset 0x%x to 0x%x\n",
1653 			dump_start_reg, dump_end_reg);
1654 	memset(buf, 0, sizeof(buf));
1655 	ptr = buf;
1656 	i = 1;
1657 	for (reg = dump_start_reg; reg <= dump_end_reg; reg += 4) {
1658 		woal_pcie_read_reg(phandle, reg, &value);
1659 		ptr += sprintf(ptr, "%08x ", value);
1660 		if (!(i % 8)) {
1661 			drv_ptr += sprintf(drv_ptr, "%s\n", buf);
1662 			memset(buf, 0, sizeof(buf));
1663 			ptr = buf;
1664 		}
1665 		i++;
1666 	}
1667 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1668 	if (IS_PCIE9098(phandle->card_type) ||
1669 	    IS_PCIENW62X(phandle->card_type) ||
1670 	    IS_PCIE9097(phandle->card_type)) {
1671 		drv_ptr += sprintf(
1672 			drv_ptr,
1673 			"PCIE registers from offset 0x1c20 to 0x1c9c:\n");
1674 		memset(buf, 0, sizeof(buf));
1675 		ptr = buf;
1676 		i = 1;
1677 		for (reg = 0x1c20; reg <= 0x1c9c; reg += 4) {
1678 			woal_pcie_read_reg(phandle, reg, &value);
1679 			ptr += sprintf(ptr, "%08x ", value);
1680 			if (!(i % 8)) {
1681 				drv_ptr += sprintf(drv_ptr, "%s\n", buf);
1682 				memset(buf, 0, sizeof(buf));
1683 				ptr = buf;
1684 			}
1685 			i++;
1686 		}
1687 		drv_ptr += sprintf(drv_ptr, "%s\n", buf);
1688 	}
1689 	if (IS_PCIE9098(phandle->card_type) ||
1690 	    IS_PCIENW62X(phandle->card_type) ||
1691 	    IS_PCIE9097(phandle->card_type)) {
1692 		drv_ptr += sprintf(drv_ptr,
1693 				   "ADMA Tx/Rx/Event/Cmd/CmdResp registers:\n");
1694 		for (j = 0; j < ARRAY_SIZE(adma_reg_table); j++) {
1695 			drv_ptr += sprintf(
1696 				drv_ptr,
1697 				"ADMA registers dump from offset 0x%x to 0x%x\n",
1698 				adma_reg_table[j], adma_reg_table[j] + 0x68);
1699 			memset(buf, 0, sizeof(buf));
1700 			ptr = buf;
1701 			i = 1;
1702 			for (reg = adma_reg_table[j];
1703 			     reg <= (adma_reg_table[j] + 0x68); reg += 4) {
1704 				woal_pcie_read_reg(phandle, reg, &value);
1705 				ptr += sprintf(ptr, "%08x ", value);
1706 				if (!(i % 8)) {
1707 					drv_ptr +=
1708 						sprintf(drv_ptr, "%s\n", buf);
1709 					memset(buf, 0, sizeof(buf));
1710 					ptr = buf;
1711 				}
1712 				i++;
1713 			}
1714 			drv_ptr += sprintf(drv_ptr, "%s\n", buf);
1715 		}
1716 	}
1717 #endif
1718 	drv_ptr += sprintf(drv_ptr,
1719 			   "-----------PCIe Registers dump End-----------\n");
1720 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
1721 	LEAVE();
1722 	return drv_ptr - (char *)buffer;
1723 }
1724 
1725 /**
1726  *  @brief This function reads and displays PCIE scratch registers for debugging
1727  *
1728  *  @param phandle  A pointer to moal_handle
1729  *
1730  *  @return         N/A
1731  */
woal_pcie_reg_dbg(moal_handle * phandle)1732 static void woal_pcie_reg_dbg(moal_handle *phandle)
1733 {
1734 	t_u32 reg = 0, value = 0;
1735 	t_u8 i;
1736 	char buf[256], *ptr;
1737 	pcie_service_card *card = (pcie_service_card *)phandle->card;
1738 	int config_reg_table[] = {0x00, 0x04, 0x10, 0x18, 0x2c,
1739 				  0x3c, 0x44, 0x80, 0x98, 0x170};
1740 	t_u32 dump_start_reg = 0;
1741 	t_u32 dump_end_reg = 0;
1742 	t_u32 scratch_14_reg = 0;
1743 	t_u32 scratch_15_reg = 0;
1744 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1745 	/* Tx/Rx/Event AMDA start address */
1746 	t_u32 adma_reg_table[] = {0x10000, 0x10800, 0x10880, 0x11000, 0x11080};
1747 	t_u8 j;
1748 #endif
1749 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
1750 	PRINTM(MMSG, "Config Space Registers:\n");
1751 	for (i = 0; i < ARRAY_SIZE(config_reg_table); i++) {
1752 		pci_read_config_dword(card->dev, config_reg_table[i], &value);
1753 		PRINTM(MERROR, "reg:0x%02x value=0x%08x\n", config_reg_table[i],
1754 		       value);
1755 	}
1756 	PRINTM(MMSG, "FW Scrach Registers:\n");
1757 #if defined(PCIE8897) || defined(PCIE8997)
1758 	if (IS_PCIE8897(phandle->card_type) ||
1759 	    IS_PCIE8997(phandle->card_type)) {
1760 		reg = PCIE_SCRATCH_12_REG;
1761 		dump_start_reg = PCIE_DUMP_START_REG;
1762 		dump_end_reg = PCIE_DUMP_END_REG;
1763 		scratch_14_reg = PCIE_SCRATCH_14_REG;
1764 		scratch_15_reg = PCIE_SCRATCH_15_REG;
1765 	}
1766 #endif
1767 
1768 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1769 	if (IS_PCIE9098(phandle->card_type) ||
1770 	    IS_PCIENW62X(phandle->card_type) ||
1771 	    IS_PCIE9097(phandle->card_type)) {
1772 		reg = PCIE9098_SCRATCH_12_REG;
1773 		dump_start_reg = PCIE9098_DUMP_START_REG;
1774 		dump_end_reg = PCIE9098_DUMP_END_REG;
1775 		scratch_14_reg = PCIE9098_SCRATCH_14_REG;
1776 		scratch_15_reg = PCIE9098_SCRATCH_15_REG;
1777 	}
1778 #endif
1779 	woal_pcie_read_reg(phandle, reg, &value);
1780 	PRINTM(MERROR, "reg:0x%x value=0x%x\n", reg, value);
1781 	for (i = 0; i < 2; i++) {
1782 		reg = scratch_14_reg;
1783 		woal_pcie_read_reg(phandle, reg, &value);
1784 		PRINTM(MERROR, "reg:0x%x value=0x%x\n", reg, value);
1785 
1786 		reg = scratch_15_reg;
1787 		woal_pcie_read_reg(phandle, reg, &value);
1788 		PRINTM(MERROR, "reg:0x%x value=0x%x\n", reg, value);
1789 
1790 		mdelay(100);
1791 	}
1792 	PRINTM(MMSG, "Interface registers dump from offset 0x%x to 0x%x\n",
1793 	       dump_start_reg, dump_end_reg);
1794 	memset(buf, 0, sizeof(buf));
1795 	ptr = buf;
1796 	i = 1;
1797 	for (reg = dump_start_reg; reg <= dump_end_reg; reg += 4) {
1798 		woal_pcie_read_reg(phandle, reg, &value);
1799 		ptr += sprintf(ptr, "%08x ", value);
1800 		if (!(i % 8)) {
1801 			PRINTM(MMSG, "%s\n", buf);
1802 			memset(buf, 0, sizeof(buf));
1803 			ptr = buf;
1804 		}
1805 		i++;
1806 	}
1807 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1808 	if (IS_PCIE9098(phandle->card_type) ||
1809 	    IS_PCIENW62X(phandle->card_type) ||
1810 	    IS_PCIE9097(phandle->card_type)) {
1811 		PRINTM(MMSG, "PCIE registers from offset 0x1c20 to 0x1c9c:\n");
1812 		memset(buf, 0, sizeof(buf));
1813 		ptr = buf;
1814 		i = 1;
1815 		for (reg = 0x1c20; reg <= 0x1c9c; reg += 4) {
1816 			woal_pcie_read_reg(phandle, reg, &value);
1817 			ptr += sprintf(ptr, "%08x ", value);
1818 			if (!(i % 8)) {
1819 				PRINTM(MMSG, "%s\n", buf);
1820 				memset(buf, 0, sizeof(buf));
1821 				ptr = buf;
1822 			}
1823 			i++;
1824 		}
1825 		PRINTM(MMSG, "%s\n", buf);
1826 	}
1827 	if (IS_PCIE9098(phandle->card_type) ||
1828 	    IS_PCIENW62X(phandle->card_type) ||
1829 	    IS_PCIE9097(phandle->card_type)) {
1830 		PRINTM(MMSG, "ADMA Tx/Rx/Event/Cmd/CmdResp registers:\n");
1831 		for (j = 0; j < ARRAY_SIZE(adma_reg_table); j++) {
1832 			PRINTM(MMSG,
1833 			       "ADMA registers dump from offset 0x%x to 0x%x\n",
1834 			       adma_reg_table[j], adma_reg_table[j] + 0x68);
1835 			memset(buf, 0, sizeof(buf));
1836 			ptr = buf;
1837 			i = 1;
1838 			for (reg = adma_reg_table[j];
1839 			     reg <= (adma_reg_table[j] + 0x68); reg += 4) {
1840 				woal_pcie_read_reg(phandle, reg, &value);
1841 				ptr += sprintf(ptr, "%08x ", value);
1842 				if (!(i % 8)) {
1843 					PRINTM(MMSG, "%s\n", buf);
1844 					memset(buf, 0, sizeof(buf));
1845 					ptr = buf;
1846 				}
1847 				i++;
1848 			}
1849 			PRINTM(MMSG, "%s\n", buf);
1850 		}
1851 	}
1852 #endif
1853 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
1854 }
1855 
1856 #define DEBUG_FW_DONE 0xFF
1857 #define MAX_POLL_TRIES 100
1858 
1859 typedef enum {
1860 	DUMP_TYPE_ITCM = 0,
1861 	DUMP_TYPE_DTCM = 1,
1862 	DUMP_TYPE_SQRAM = 2,
1863 	DUMP_TYPE_IRAM = 3,
1864 	DUMP_TYPE_APU = 4,
1865 	DUMP_TYPE_CIU = 5,
1866 	DUMP_TYPE_ICU = 6,
1867 	DUMP_TYPE_MAC = 7,
1868 } dumped_mem_type;
1869 
1870 #define MAX_NAME_LEN 8
1871 
1872 typedef struct {
1873 	t_u8 mem_name[MAX_NAME_LEN];
1874 	t_u8 *mem_Ptr;
1875 	struct file *pfile_mem;
1876 	t_u8 done_flag;
1877 	t_u8 type;
1878 } memory_type_mapping;
1879 
1880 #ifdef PCIE8897
1881 #define DEBUG_HOST_READY_8897 0xEE
1882 #define DEBUG_MEMDUMP_FINISH_8897 0xFE
1883 static memory_type_mapping mem_type_mapping_tbl_8897[] = {
1884 	{"ITCM", NULL, NULL, 0xF0, FW_DUMP_TYPE_MEM_ITCM},
1885 	{"DTCM", NULL, NULL, 0xF1, FW_DUMP_TYPE_MEM_DTCM},
1886 	{"SQRAM", NULL, NULL, 0xF2, FW_DUMP_TYPE_MEM_SQRAM},
1887 	{"IRAM", NULL, NULL, 0xF3, FW_DUMP_TYPE_MEM_IRAM},
1888 	{"APU", NULL, NULL, 0xF4, FW_DUMP_TYPE_REG_APU},
1889 	{"CIU", NULL, NULL, 0xF5, FW_DUMP_TYPE_REG_CIU},
1890 	{"ICU", NULL, NULL, 0xF6, FW_DUMP_TYPE_REG_ICU},
1891 	{"MAC", NULL, NULL, 0xF7, FW_DUMP_TYPE_REG_MAC},
1892 };
1893 #endif
1894 
1895 #if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097) ||             \
1896 	defined(PCIENW62X)
1897 #define DEBUG_HOST_READY_8997 0xCC
1898 #define DEBUG_HOST_EVENT_READY 0xAA
1899 #define DEBUG_HOST_RESET_READY 0x99
1900 static memory_type_mapping mem_type_mapping_tbl_8997 = {"DUMP", NULL, NULL,
1901 							0xDD, 0x00};
1902 
1903 #endif
1904 
1905 #if defined(PCIE8897) || defined(PCIE8997) || defined(PCIE9098) ||             \
1906 	defined(PCIE9097) || defined(PCIENW62X)
1907 /**
1908  *  @brief This function reads data by 8 bit from card register
1909  *
1910  *  @param handle   A Pointer to the moal_handle structure
1911  *  @param reg      Register offset
1912  *  @param data     Value
1913  *
1914  *  @return    		MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1915  */
woal_read_reg_eight_bit(moal_handle * handle,t_u32 reg,t_u8 * data)1916 static mlan_status woal_read_reg_eight_bit(moal_handle *handle, t_u32 reg,
1917 					   t_u8 *data)
1918 {
1919 	pcie_service_card *card = (pcie_service_card *)handle->card;
1920 	*data = ioread8(card->pci_mmap1 + reg);
1921 	return MLAN_STATUS_SUCCESS;
1922 }
1923 
1924 /**
1925  *  @brief This function read/write firmware
1926  *
1927  *  @param phandle   A pointer to moal_handle
1928  *  @param doneflag  done flag
1929  *  @param resetflag reset flag;
1930  *
1931  *  @return         MLAN_STATUS_SUCCESS
1932  */
woal_pcie_rdwr_firmware(moal_handle * phandle,t_u8 doneflag,t_u8 resetflag)1933 static rdwr_status woal_pcie_rdwr_firmware(moal_handle *phandle, t_u8 doneflag,
1934 					   t_u8 resetflag)
1935 {
1936 	int ret = 0;
1937 	int tries = 0;
1938 	t_u8 ctrl_data = 0;
1939 	t_u32 reg_data = 0;
1940 	t_u32 debug_host_ready = 0;
1941 	t_u32 dump_ctrl_reg = 0;
1942 
1943 #ifdef PCIE8897
1944 	if (IS_PCIE8897(phandle->card_type)) {
1945 		debug_host_ready = DEBUG_HOST_READY_8897;
1946 		dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
1947 	}
1948 #endif
1949 #if defined(PCIE8997)
1950 	if (IS_PCIE8997(phandle->card_type)) {
1951 		debug_host_ready = DEBUG_HOST_READY_8997;
1952 		dump_ctrl_reg = DEBUG_DUMP_CTRL_REG;
1953 	}
1954 #endif
1955 
1956 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1957 	if (IS_PCIE9098(phandle->card_type) ||
1958 	    IS_PCIENW62X(phandle->card_type) ||
1959 	    IS_PCIE9097(phandle->card_type)) {
1960 		if (phandle->event_fw_dump)
1961 			debug_host_ready = DEBUG_HOST_EVENT_READY;
1962 		else
1963 			debug_host_ready = DEBUG_HOST_READY_8997;
1964 		if (resetflag)
1965 			debug_host_ready = DEBUG_HOST_RESET_READY;
1966 		dump_ctrl_reg = PCIE9098_DUMP_CTRL_REG;
1967 	}
1968 #endif
1969 
1970 	ret = woal_pcie_write_reg(phandle, dump_ctrl_reg, debug_host_ready);
1971 	if (ret) {
1972 		PRINTM(MERROR, "PCIE Write ERR, reg=0x%x debug_reay=0x%x\n",
1973 		       dump_ctrl_reg, debug_host_ready);
1974 		return RDWR_STATUS_FAILURE;
1975 	}
1976 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
1977 	if (IS_PCIE9098(phandle->card_type) ||
1978 	    IS_PCIENW62X(phandle->card_type) ||
1979 	    IS_PCIE9097(phandle->card_type)) {
1980 		if (phandle->event_fw_dump || resetflag)
1981 			return RDWR_STATUS_SUCCESS;
1982 	}
1983 #endif
1984 	ret = woal_pcie_read_reg(phandle, dump_ctrl_reg, &reg_data);
1985 	if (ret) {
1986 		PRINTM(MERROR, "PCIE Read DEBUG_DUMP_CTRL_REG 0x%x fail\n",
1987 		       dump_ctrl_reg);
1988 		return RDWR_STATUS_FAILURE;
1989 	}
1990 	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
1991 		ret = woal_read_reg_eight_bit(phandle, dump_ctrl_reg,
1992 					      &ctrl_data);
1993 		if (ret) {
1994 			PRINTM(MERROR, "PCIE READ reg 0x%x 8bit ERR\n",
1995 			       dump_ctrl_reg);
1996 			return RDWR_STATUS_FAILURE;
1997 		}
1998 		if (ctrl_data == DEBUG_FW_DONE)
1999 			break;
2000 		if (doneflag && ctrl_data == doneflag)
2001 			return RDWR_STATUS_DONE;
2002 		if (ctrl_data != debug_host_ready) {
2003 			PRINTM(MMSG,
2004 			       "The ctrl reg was changed, ctrl_data=0x%x, host_ready:0x%x try again!\n",
2005 			       ctrl_data, debug_host_ready);
2006 			ret = woal_pcie_write_reg(phandle, dump_ctrl_reg,
2007 						  debug_host_ready);
2008 			if (ret) {
2009 				PRINTM(MERROR, "PCIE Write ERR\n");
2010 				return RDWR_STATUS_FAILURE;
2011 			}
2012 		}
2013 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
2014 		usleep_range(99, 100);
2015 #else
2016 		udelay(100);
2017 #endif
2018 	}
2019 	if (ctrl_data == debug_host_ready) {
2020 		PRINTM(MERROR, "Fail to pull ctrl_data=0x%x host_ready=0x%x\n",
2021 		       ctrl_data, debug_host_ready);
2022 		return RDWR_STATUS_FAILURE;
2023 	}
2024 	return RDWR_STATUS_SUCCESS;
2025 }
2026 #endif
2027 
2028 #ifdef PCIE8897
2029 /**
2030  *  @brief This function dump firmware memory to file
2031  *
2032  *  @param phandle   A pointer to moal_handle
2033  *
2034  *  @return         N/A
2035  */
woal_pcie_dump_fw_info_v1(moal_handle * phandle)2036 static void woal_pcie_dump_fw_info_v1(moal_handle *phandle)
2037 {
2038 	int ret = 0;
2039 	unsigned int reg, reg_start, reg_end;
2040 	t_u8 *dbg_ptr = NULL;
2041 	t_u32 sec, usec;
2042 	t_u8 dump_num = 0;
2043 	t_u8 idx = 0;
2044 	t_u8 doneflag = 0;
2045 	rdwr_status stat;
2046 	t_u8 i = 0;
2047 	t_u8 read_reg = 0;
2048 	t_u32 memory_size = 0;
2049 	t_u32 memdump_finsh = 0;
2050 	t_u8 *end_ptr = NULL;
2051 	memory_type_mapping *mem_type_mapping_tbl = mem_type_mapping_tbl_8897;
2052 
2053 	if (!phandle) {
2054 		PRINTM(MERROR, "Could not dump firmwware info\n");
2055 		return;
2056 	}
2057 	if (!phandle->fw_dump_buf) {
2058 		ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
2059 				   &(phandle->fw_dump_buf));
2060 		if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
2061 			PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n");
2062 			return;
2063 		}
2064 	} else {
2065 		memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
2066 	}
2067 	phandle->fw_dump_len = 0;
2068 	/* start dump fw memory	*/
2069 	moal_get_system_time(phandle, &sec, &usec);
2070 	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT START: %u.%06u ====\n", sec,
2071 	       usec);
2072 	/* read the number of the memories which will dump */
2073 	if (RDWR_STATUS_FAILURE ==
2074 	    woal_pcie_rdwr_firmware(phandle, doneflag, 0))
2075 		goto done;
2076 	reg = DEBUG_DUMP_START_REG;
2077 	ret = woal_read_reg_eight_bit(phandle, reg, &dump_num);
2078 	if (ret) {
2079 		PRINTM(MMSG, "PCIE READ MEM NUM ERR\n");
2080 		goto done;
2081 	}
2082 
2083 	/* read the length of every memory which will dump */
2084 	for (idx = 0;
2085 	     idx < dump_num && idx < ARRAY_SIZE(mem_type_mapping_tbl_8897);
2086 	     idx++) {
2087 		if (RDWR_STATUS_FAILURE ==
2088 		    woal_pcie_rdwr_firmware(phandle, doneflag, 0))
2089 			goto done;
2090 		memory_size = 0;
2091 		reg = DEBUG_DUMP_START_REG;
2092 		for (i = 0; i < 4; i++) {
2093 			ret = woal_read_reg_eight_bit(phandle, reg, &read_reg);
2094 			if (ret) {
2095 				PRINTM(MMSG, "PCIE READ ERR\n");
2096 				goto done;
2097 			}
2098 			memory_size |= (read_reg << i * 8);
2099 			reg++;
2100 		}
2101 		if (memory_size == 0) {
2102 			PRINTM(MMSG, "Firmware Dump Finished!\n");
2103 			ret = woal_pcie_write_reg(phandle, DEBUG_DUMP_CTRL_REG,
2104 						  memdump_finsh);
2105 			if (ret) {
2106 				PRINTM(MERROR,
2107 				       "PCIE Write MEMDUMP_FINISH ERR\n");
2108 				goto done;
2109 			}
2110 			break;
2111 		} else {
2112 			PRINTM(MMSG, "%s_SIZE=0x%x\n",
2113 			       mem_type_mapping_tbl[idx].mem_name, memory_size);
2114 			ret = moal_vmalloc(
2115 				phandle, memory_size + 1,
2116 				(t_u8 **)&mem_type_mapping_tbl[idx].mem_Ptr);
2117 			if ((ret != MLAN_STATUS_SUCCESS) ||
2118 			    !mem_type_mapping_tbl[idx].mem_Ptr) {
2119 				PRINTM(MERROR,
2120 				       "Error: vmalloc %s buffer failed!!!\n",
2121 				       mem_type_mapping_tbl[idx].mem_name);
2122 				goto done;
2123 			}
2124 			dbg_ptr = mem_type_mapping_tbl[idx].mem_Ptr;
2125 			end_ptr = dbg_ptr + memory_size;
2126 		}
2127 		doneflag = mem_type_mapping_tbl[idx].done_flag;
2128 		moal_get_system_time(phandle, &sec, &usec);
2129 		PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
2130 		       mem_type_mapping_tbl[idx].mem_name, sec, usec);
2131 		do {
2132 			stat = woal_pcie_rdwr_firmware(phandle, doneflag, 0);
2133 			if (RDWR_STATUS_FAILURE == stat)
2134 				goto done;
2135 
2136 			reg_start = DEBUG_DUMP_START_REG;
2137 			reg_end = DEBUG_DUMP_END_REG;
2138 			for (reg = reg_start; reg <= reg_end; reg++) {
2139 				ret = woal_read_reg_eight_bit(phandle, reg,
2140 							      dbg_ptr);
2141 				if (ret) {
2142 					PRINTM(MMSG, "PCIE READ ERR\n");
2143 					goto done;
2144 				}
2145 				if (dbg_ptr < end_ptr)
2146 					dbg_ptr++;
2147 				else
2148 					PRINTM(MINFO,
2149 					       "pre-allocced buf is not enough\n");
2150 			}
2151 			if (RDWR_STATUS_DONE == stat) {
2152 				PRINTM(MMSG, "%s done: size=0x%x\n",
2153 				       mem_type_mapping_tbl[idx].mem_name,
2154 				       (unsigned int)(dbg_ptr -
2155 						      mem_type_mapping_tbl[idx]
2156 							      .mem_Ptr));
2157 				woal_save_dump_info_to_buf(
2158 					phandle,
2159 					mem_type_mapping_tbl[idx].mem_Ptr,
2160 					memory_size,
2161 					mem_type_mapping_tbl[idx].type);
2162 				moal_vfree(phandle,
2163 					   mem_type_mapping_tbl[idx].mem_Ptr);
2164 				mem_type_mapping_tbl[idx].mem_Ptr = NULL;
2165 				break;
2166 			}
2167 		} while (1);
2168 	}
2169 	woal_append_end_block(phandle);
2170 	moal_get_system_time(phandle, &sec, &usec);
2171 	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT END: %u.%06u ====\n", sec,
2172 	       usec);
2173 	/* end dump fw memory */
2174 done:
2175 	for (idx = 0;
2176 	     idx < dump_num && idx < ARRAY_SIZE(mem_type_mapping_tbl_8897);
2177 	     idx++) {
2178 		if (mem_type_mapping_tbl[idx].mem_Ptr) {
2179 			moal_vfree(phandle, mem_type_mapping_tbl[idx].mem_Ptr);
2180 			mem_type_mapping_tbl[idx].mem_Ptr = NULL;
2181 		}
2182 	}
2183 
2184 	return;
2185 }
2186 #endif
2187 
2188 #if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097) ||             \
2189 	defined(PCIENW62X)
2190 /**
2191  *  @brief This function dump firmware memory to file
2192  *
2193  *  @param phandle   A pointer to moal_handle
2194  *
2195  *  @return         N/A
2196  */
woal_pcie_dump_fw_info_v2(moal_handle * phandle)2197 static void woal_pcie_dump_fw_info_v2(moal_handle *phandle)
2198 {
2199 	int ret = 0;
2200 	unsigned int reg, reg_start, reg_end;
2201 	t_u8 *dbg_ptr = NULL;
2202 	t_u8 *tmp_ptr = NULL;
2203 	t_u32 sec, usec;
2204 	t_u8 dump_num = 0;
2205 	t_u8 doneflag = 0;
2206 	rdwr_status stat;
2207 	t_u32 memory_size = 0;
2208 	t_u8 *end_ptr = NULL;
2209 	memory_type_mapping *mem_type_mapping_tbl = &mem_type_mapping_tbl_8997;
2210 	t_u32 dump_start_reg = 0;
2211 	t_u32 dump_end_reg = 0;
2212 
2213 	if (!phandle) {
2214 		PRINTM(MERROR, "Could not dump firmwware info\n");
2215 		return;
2216 	}
2217 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2218 	if (IS_PCIE9098(phandle->card_type) ||
2219 	    IS_PCIENW62X(phandle->card_type) ||
2220 	    IS_PCIE9097(phandle->card_type)) {
2221 		if (phandle->event_fw_dump) {
2222 			if (RDWR_STATUS_FAILURE !=
2223 			    woal_pcie_rdwr_firmware(phandle, doneflag, 0)) {
2224 				PRINTM(MMSG,
2225 				       "====PCIE FW DUMP EVENT MODE START ====\n");
2226 				return;
2227 			}
2228 		}
2229 	}
2230 #endif
2231 
2232 	/* start dump fw memory	*/
2233 	moal_get_system_time(phandle, &sec, &usec);
2234 	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT START: %u.%06u ====\n", sec,
2235 	       usec);
2236 	/* read the number of the memories which will dump */
2237 	if (RDWR_STATUS_FAILURE ==
2238 	    woal_pcie_rdwr_firmware(phandle, doneflag, 0))
2239 		goto done;
2240 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2241 	if (IS_PCIE9098(phandle->card_type) ||
2242 	    IS_PCIENW62X(phandle->card_type) ||
2243 	    IS_PCIE9097(phandle->card_type)) {
2244 		dump_start_reg = PCIE9098_DUMP_START_REG;
2245 		dump_end_reg = PCIE9098_DUMP_END_REG;
2246 	}
2247 #endif
2248 #ifdef PCIE8997
2249 	if (IS_PCIE8997(phandle->card_type)) {
2250 		dump_start_reg = DEBUG_DUMP_START_REG;
2251 		dump_end_reg = DEBUG_DUMP_END_REG;
2252 	}
2253 #endif
2254 	reg = dump_start_reg;
2255 	ret = woal_read_reg_eight_bit(phandle, reg, &dump_num);
2256 	if (ret) {
2257 		PRINTM(MMSG, "PCIE READ MEM NUM ERR\n");
2258 		goto done;
2259 	}
2260 
2261 	memory_size = 0x80000;
2262 	ret = moal_vmalloc(phandle, memory_size + 1,
2263 			   (t_u8 **)&mem_type_mapping_tbl->mem_Ptr);
2264 	if ((ret != MLAN_STATUS_SUCCESS) || !mem_type_mapping_tbl->mem_Ptr) {
2265 		PRINTM(MERROR, "Error: vmalloc %s buffer failed!!!\n",
2266 		       mem_type_mapping_tbl->mem_name);
2267 		goto done;
2268 	}
2269 	dbg_ptr = mem_type_mapping_tbl->mem_Ptr;
2270 	end_ptr = dbg_ptr + memory_size;
2271 
2272 	doneflag = mem_type_mapping_tbl->done_flag;
2273 	moal_get_system_time(phandle, &sec, &usec);
2274 	PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
2275 	       mem_type_mapping_tbl->mem_name, sec, usec);
2276 	do {
2277 		stat = woal_pcie_rdwr_firmware(phandle, doneflag, 0);
2278 		if (RDWR_STATUS_FAILURE == stat)
2279 			goto done;
2280 
2281 		reg_start = dump_start_reg;
2282 		reg_end = dump_end_reg;
2283 		for (reg = reg_start; reg <= reg_end; reg++) {
2284 			ret = woal_read_reg_eight_bit(phandle, reg, dbg_ptr);
2285 			if (ret) {
2286 				PRINTM(MMSG, "PCIE READ ERR\n");
2287 				goto done;
2288 			}
2289 			dbg_ptr++;
2290 			if (dbg_ptr >= end_ptr) {
2291 				PRINTM(MINFO,
2292 				       "pre-allocced buf is not enough\n");
2293 				ret = moal_vmalloc(phandle,
2294 						   memory_size + 0x4000 + 1,
2295 						   (t_u8 **)&tmp_ptr);
2296 				if ((ret != MLAN_STATUS_SUCCESS) || !tmp_ptr) {
2297 					PRINTM(MERROR,
2298 					       "Error: vmalloc  buffer failed!!!\n");
2299 					goto done;
2300 				}
2301 				moal_memcpy_ext(phandle, tmp_ptr,
2302 						mem_type_mapping_tbl->mem_Ptr,
2303 						memory_size,
2304 						memory_size + 0x4000);
2305 				moal_vfree(phandle,
2306 					   mem_type_mapping_tbl->mem_Ptr);
2307 				mem_type_mapping_tbl->mem_Ptr = tmp_ptr;
2308 				tmp_ptr = NULL;
2309 				dbg_ptr = mem_type_mapping_tbl->mem_Ptr +
2310 					  memory_size;
2311 				memory_size += 0x4000;
2312 				end_ptr = mem_type_mapping_tbl->mem_Ptr +
2313 					  memory_size;
2314 			}
2315 		}
2316 		if (RDWR_STATUS_DONE == stat) {
2317 #ifdef MLAN_64BIT
2318 			PRINTM(MMSG,
2319 			       "%s done:"
2320 			       "size = 0x%lx\n",
2321 			       mem_type_mapping_tbl->mem_name,
2322 			       dbg_ptr - mem_type_mapping_tbl->mem_Ptr);
2323 #else
2324 			PRINTM(MMSG,
2325 			       "%s done:"
2326 			       "size = 0x%x\n",
2327 			       mem_type_mapping_tbl->mem_name,
2328 			       dbg_ptr - mem_type_mapping_tbl->mem_Ptr);
2329 #endif
2330 			if (phandle->fw_dump_buf) {
2331 				moal_vfree(phandle, phandle->fw_dump_buf);
2332 				phandle->fw_dump_buf = NULL;
2333 				phandle->fw_dump_len = 0;
2334 			}
2335 			phandle->fw_dump_buf = mem_type_mapping_tbl->mem_Ptr;
2336 			phandle->fw_dump_len =
2337 				dbg_ptr - mem_type_mapping_tbl->mem_Ptr;
2338 			mem_type_mapping_tbl->mem_Ptr = NULL;
2339 			break;
2340 		}
2341 	} while (1);
2342 	moal_get_system_time(phandle, &sec, &usec);
2343 	PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT END: %u.%06u ====\n", sec,
2344 	       usec);
2345 	/* end dump fw memory */
2346 done:
2347 	if (mem_type_mapping_tbl->mem_Ptr) {
2348 		moal_vfree(phandle, mem_type_mapping_tbl->mem_Ptr);
2349 		mem_type_mapping_tbl->mem_Ptr = NULL;
2350 	}
2351 
2352 	return;
2353 }
2354 #endif
2355 
2356 /**
2357  *  @brief This function check if this is second mac
2358  *
2359  *  @param handle   A pointer to moal_handle structure
2360  *  @return         MTRUE/MFALSE
2361  *
2362  */
woal_pcie_is_second_mac(moal_handle * handle)2363 static t_u8 woal_pcie_is_second_mac(moal_handle *handle)
2364 {
2365 #ifdef PCIE9098
2366 	pcie_service_card *card = (pcie_service_card *)handle->card;
2367 	if (card->dev->device == PCIE_DEVICE_ID_88W9098P_FN1)
2368 		return MTRUE;
2369 #endif
2370 	return MFALSE;
2371 }
2372 
woal_pcie_dump_fw_info(moal_handle * phandle)2373 static void woal_pcie_dump_fw_info(moal_handle *phandle)
2374 {
2375 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
2376 	phandle->fw_dump = MTRUE;
2377 #ifdef PCIE8897
2378 	if (IS_PCIE8897(phandle->card_type))
2379 		woal_pcie_dump_fw_info_v1(phandle);
2380 #endif
2381 #if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097) ||             \
2382 	defined(PCIENW62X)
2383 	if (IS_PCIE8997(phandle->card_type) ||
2384 	    IS_PCIENW62X(phandle->card_type) ||
2385 	    IS_PCIE9098(phandle->card_type) ||
2386 	    IS_PCIE9097(phandle->card_type)) {
2387 		woal_pcie_dump_fw_info_v2(phandle);
2388 		if (phandle->event_fw_dump) {
2389 			phandle->event_fw_dump = MFALSE;
2390 			queue_work(phandle->workqueue, &phandle->main_work);
2391 			phandle->is_fw_dump_timer_set = MTRUE;
2392 			woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
2393 			return;
2394 		}
2395 	}
2396 #endif
2397 	phandle->fw_dump = MFALSE;
2398 	if (!phandle->priv_num)
2399 		return;
2400 	woal_send_fw_dump_complete_event(
2401 		woal_get_priv(phandle, MLAN_BSS_ROLE_ANY));
2402 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
2403 	queue_work(phandle->workqueue, &phandle->main_work);
2404 	woal_process_hang(phandle);
2405 }
2406 
woal_pcie_get_fw_name(moal_handle * handle)2407 static mlan_status woal_pcie_get_fw_name(moal_handle *handle)
2408 {
2409 	mlan_status ret = MLAN_STATUS_SUCCESS;
2410 #ifdef PCIE9098
2411 	pcie_service_card *card = (pcie_service_card *)handle->card;
2412 	moal_handle *ref_handle = NULL;
2413 #endif
2414 
2415 #if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097) ||             \
2416 	defined(PCIENW62X)
2417 	t_u32 rev_id_reg = handle->card_info->rev_id_reg;
2418 	t_u32 revision_id = 0;
2419 #endif
2420 
2421 #if defined(PCIE8997) || defined(PCIE9098) || defined(PCIE9097) ||             \
2422 	defined(PCIENW62X)
2423 	t_u32 host_strap_reg = handle->card_info->host_strap_reg;
2424 	t_u32 magic_reg = handle->card_info->magic_reg;
2425 	t_u32 strap = 0;
2426 	t_u32 magic = 0;
2427 #endif
2428 
2429 	ENTER();
2430 
2431 	if (handle->params.fw_name) {
2432 #ifdef PCIE9097
2433 		if (IS_PCIE9097(handle->card_type)) {
2434 			woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
2435 			revision_id &= 0xff;
2436 			PRINTM(MCMND, "revision_id=0x%x\n", revision_id);
2437 			switch (revision_id) {
2438 			case PCIE9097_A0:
2439 				break;
2440 			case PCIE9097_B0:
2441 			case PCIE9097_B1:
2442 				handle->card_rev = CHIP_9097_REV_B0;
2443 				break;
2444 			default:
2445 				break;
2446 			}
2447 		}
2448 #endif
2449 		goto done;
2450 	}
2451 
2452 #ifdef PCIE8997
2453 	if (IS_PCIE8997(handle->card_type)) {
2454 		woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
2455 		woal_pcie_read_reg(handle, host_strap_reg, &strap);
2456 		woal_pcie_read_reg(handle, magic_reg, &magic);
2457 		revision_id &= 0xff;
2458 		strap &= 0x7;
2459 		magic &= 0xff;
2460 		PRINTM(MCMND, "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
2461 		       magic, strap, revision_id);
2462 		if ((revision_id == PCIE8997_A1) &&
2463 		    (magic == CHIP_MAGIC_VALUE)) {
2464 			if (strap == CARD_TYPE_PCIE_UART)
2465 				strcpy(handle->card_info->fw_name,
2466 				       PCIEUART8997_DEFAULT_COMBO_FW_NAME);
2467 			else
2468 				strcpy(handle->card_info->fw_name,
2469 				       PCIEUSB8997_DEFAULT_COMBO_FW_NAME);
2470 		}
2471 	}
2472 #endif
2473 #ifdef PCIE9098
2474 	if (IS_PCIE9098(handle->card_type)) {
2475 		if (card->dev->device == PCIE_DEVICE_ID_88W9098P_FN0) {
2476 			woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
2477 			woal_pcie_read_reg(handle, host_strap_reg, &strap);
2478 			woal_pcie_read_reg(handle, magic_reg, &magic);
2479 			revision_id &= 0xff;
2480 			strap &= 0x7;
2481 			magic &= 0xff;
2482 			PRINTM(MCMND,
2483 			       "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
2484 			       magic, strap, revision_id);
2485 			switch (revision_id) {
2486 			case PCIE9098_Z1Z2:
2487 				if (magic == CHIP_MAGIC_VALUE) {
2488 					if (strap == CARD_TYPE_PCIE_UART)
2489 						strcpy(handle->card_info
2490 							       ->fw_name,
2491 						       PCIEUART9098_DEFAULT_COMBO_FW_NAME);
2492 					else if (strap == CARD_TYPE_PCIE_PCIE)
2493 						strcpy(handle->card_info
2494 							       ->fw_name,
2495 						       PCIEPCIE9098_DEFAULT_COMBO_FW_NAME);
2496 					else
2497 						strcpy(handle->card_info
2498 							       ->fw_name,
2499 						       PCIEUSB9098_DEFAULT_COMBO_FW_NAME);
2500 				}
2501 				strcpy(handle->card_info->fw_name_wlan,
2502 				       PCIE9098_DEFAULT_WLAN_FW_NAME);
2503 				break;
2504 			case PCIE9098_A0:
2505 			case PCIE9098_A1:
2506 			case PCIE9098_A2:
2507 				if (magic == CHIP_MAGIC_VALUE) {
2508 					if (strap == CARD_TYPE_PCIE_UART)
2509 						strcpy(handle->card_info
2510 							       ->fw_name,
2511 						       PCIEUART9098_COMBO_V1_FW_NAME);
2512 					else if (strap == CARD_TYPE_PCIE_PCIE)
2513 						strcpy(handle->card_info
2514 							       ->fw_name,
2515 						       PCIEPCIE9098_COMBO_V1_FW_NAME);
2516 					else
2517 						strcpy(handle->card_info
2518 							       ->fw_name,
2519 						       PCIEUSB9098_COMBO_V1_FW_NAME);
2520 				}
2521 				strcpy(handle->card_info->fw_name_wlan,
2522 				       PCIE9098_WLAN_V1_FW_NAME);
2523 				break;
2524 			default:
2525 				break;
2526 			}
2527 		} else {
2528 			ref_handle = (moal_handle *)handle->pref_mac;
2529 			if (ref_handle) {
2530 				strcpy(handle->card_info->fw_name,
2531 				       ref_handle->card_info->fw_name);
2532 				strcpy(handle->card_info->fw_name_wlan,
2533 				       ref_handle->card_info->fw_name_wlan);
2534 			}
2535 		}
2536 	}
2537 #endif
2538 #ifdef PCIE9097
2539 	if (IS_PCIE9097(handle->card_type)) {
2540 		woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
2541 		woal_pcie_read_reg(handle, host_strap_reg, &strap);
2542 		woal_pcie_read_reg(handle, magic_reg, &magic);
2543 		revision_id &= 0xff;
2544 		strap &= 0x7;
2545 		magic &= 0xff;
2546 		PRINTM(MCMND, "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
2547 		       magic, strap, revision_id);
2548 		switch (revision_id) {
2549 		case PCIE9097_A0:
2550 			if (magic == CHIP_MAGIC_VALUE) {
2551 				if (strap == CARD_TYPE_PCIE_UART)
2552 					strcpy(handle->card_info->fw_name,
2553 					       PCIEUART9097_DEFAULT_COMBO_FW_NAME);
2554 				else
2555 					strcpy(handle->card_info->fw_name,
2556 					       PCIEUSB9097_DEFAULT_COMBO_FW_NAME);
2557 			}
2558 			strcpy(handle->card_info->fw_name_wlan,
2559 			       PCIE9097_DEFAULT_WLAN_FW_NAME);
2560 			break;
2561 		case PCIE9097_B0:
2562 		case PCIE9097_B1:
2563 			if (magic == CHIP_MAGIC_VALUE) {
2564 				if (strap == CARD_TYPE_PCIE_UART)
2565 					strcpy(handle->card_info->fw_name,
2566 					       PCIEUART9097_COMBO_V1_FW_NAME);
2567 				else
2568 					strcpy(handle->card_info->fw_name,
2569 					       PCIEUSB9097_COMBO_V1_FW_NAME);
2570 			}
2571 			strcpy(handle->card_info->fw_name_wlan,
2572 			       PCIE9097_WLAN_V1_FW_NAME);
2573 			handle->card_rev = CHIP_9097_REV_B0;
2574 			break;
2575 		default:
2576 			break;
2577 		}
2578 	}
2579 #endif
2580 #ifdef PCIENW62X
2581 	if (IS_PCIENW62X(handle->card_type)) {
2582 		woal_pcie_read_reg(handle, rev_id_reg, &revision_id);
2583 		woal_pcie_read_reg(handle, host_strap_reg, &strap);
2584 		woal_pcie_read_reg(handle, magic_reg, &magic);
2585 		revision_id &= 0xff;
2586 		strap &= 0x7;
2587 		magic &= 0xff;
2588 		PRINTM(MCMND, "magic=0x%x, strap=0x%x, revision_id=0x%x\n",
2589 		       magic, strap, revision_id);
2590 		if (magic == CHIP_MAGIC_VALUE) {
2591 			if (strap == CARD_TYPE_PCIE_UART)
2592 				strcpy(handle->card_info->fw_name,
2593 				       PCIEUARTNW62X_DEFAULT_COMBO_FW_NAME);
2594 			else
2595 				strcpy(handle->card_info->fw_name,
2596 				       PCIEUSBNW62X_DEFAULT_COMBO_FW_NAME);
2597 		}
2598 	}
2599 #endif
2600 done:
2601 	PRINTM(MCMND, "combo fw:%s wlan fw:%s \n", handle->card_info->fw_name,
2602 	       handle->card_info->fw_name_wlan);
2603 	LEAVE();
2604 	return ret;
2605 }
2606 
2607 static moal_if_ops pcie_ops = {
2608 	.register_dev = woal_pcie_register_dev,
2609 	.unregister_dev = woal_pcie_unregister_dev,
2610 	.read_reg = woal_pcie_read_reg,
2611 	.write_reg = woal_pcie_write_reg,
2612 	.read_data_sync = woal_pcie_read_data_sync,
2613 	.write_data_sync = woal_pcie_write_data_sync,
2614 	.get_fw_name = woal_pcie_get_fw_name,
2615 	.dump_fw_info = woal_pcie_dump_fw_info,
2616 	.reg_dbg = woal_pcie_reg_dbg,
2617 	.dump_reg_info = woal_pcie_dump_reg_info,
2618 	.is_second_mac = woal_pcie_is_second_mac,
2619 };
2620