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, ®_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