blob: de364381fe7be82d76c1bb282f7aa0649e1c586b [file] [log] [blame]
Amitkumar Karward930fae2011-10-11 17:41:21 -07001/*
2 * Marvell Wireless LAN device driver: PCIE specific handling
3 *
Xinming Hu65da33f2014-06-19 21:38:57 -07004 * Copyright (C) 2011-2014, Marvell International Ltd.
Amitkumar Karward930fae2011-10-11 17:41:21 -07005 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include <linux/firmware.h>
21
22#include "decl.h"
23#include "ioctl.h"
24#include "util.h"
25#include "fw.h"
26#include "main.h"
27#include "wmm.h"
28#include "11n.h"
29#include "pcie.h"
30
31#define PCIE_VERSION "1.0"
32#define DRV_NAME "Marvell mwifiex PCIe"
33
34static u8 user_rmmod;
35
36static struct mwifiex_if_ops pcie_ops;
37
38static struct semaphore add_remove_card_sem;
Amitkumar Karward930fae2011-10-11 17:41:21 -070039
Avinash Patilfc331462013-01-03 21:21:30 -080040static int
41mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
Aaron Durbindbccc922014-02-07 16:25:50 -080042 size_t size, int flags)
Amitkumar Karward930fae2011-10-11 17:41:21 -070043{
Avinash Patilfc331462013-01-03 21:21:30 -080044 struct pcie_service_card *card = adapter->card;
Aaron Durbindbccc922014-02-07 16:25:50 -080045 struct mwifiex_dma_mapping mapping;
Amitkumar Karward930fae2011-10-11 17:41:21 -070046
Aaron Durbindbccc922014-02-07 16:25:50 -080047 mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
48 if (pci_dma_mapping_error(card->dev, mapping.addr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +053049 mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
Avinash Patilfc331462013-01-03 21:21:30 -080050 return -1;
51 }
Aaron Durbindbccc922014-02-07 16:25:50 -080052 mapping.len = size;
Chin-Ran Lobca463e2014-06-06 19:37:10 -070053 mwifiex_store_mapping(skb, &mapping);
Avinash Patilfc331462013-01-03 21:21:30 -080054 return 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -070055}
56
Aaron Durbindbccc922014-02-07 16:25:50 -080057static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
58 struct sk_buff *skb, int flags)
59{
60 struct pcie_service_card *card = adapter->card;
61 struct mwifiex_dma_mapping mapping;
62
Chin-Ran Lobca463e2014-06-06 19:37:10 -070063 mwifiex_get_mapping(skb, &mapping);
Aaron Durbindbccc922014-02-07 16:25:50 -080064 pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
65}
66
Amitkumar Karward930fae2011-10-11 17:41:21 -070067/*
68 * This function reads sleep cookie and checks if FW is ready
69 */
70static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
71{
72 u32 *cookie_addr;
73 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -080074 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
75
76 if (!reg->sleep_cookie)
77 return true;
Amitkumar Karward930fae2011-10-11 17:41:21 -070078
Avinash Patilfc331462013-01-03 21:21:30 -080079 if (card->sleep_cookie_vbase) {
80 cookie_addr = (u32 *)card->sleep_cookie_vbase;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +053081 mwifiex_dbg(adapter, INFO,
82 "info: ACCESS_HW: sleep cookie=0x%x\n",
83 *cookie_addr);
Amitkumar Karward930fae2011-10-11 17:41:21 -070084 if (*cookie_addr == FW_AWAKE_COOKIE)
85 return true;
86 }
87
88 return false;
89}
90
Shuah Khan3266d732013-07-03 10:47:10 -060091#ifdef CONFIG_PM_SLEEP
Amitkumar Karward930fae2011-10-11 17:41:21 -070092/*
Bing Zhaofcca8d52013-03-04 16:27:53 -080093 * Kernel needs to suspend all functions separately. Therefore all
94 * registered functions must have drivers with suspend and resume
95 * methods. Failing that the kernel simply removes the whole card.
96 *
97 * If already not suspended, this function allocates and sends a host
98 * sleep activate request to the firmware and turns off the traffic.
99 */
Shuah Khan3266d732013-07-03 10:47:10 -0600100static int mwifiex_pcie_suspend(struct device *dev)
Bing Zhaofcca8d52013-03-04 16:27:53 -0800101{
102 struct mwifiex_adapter *adapter;
103 struct pcie_service_card *card;
104 int hs_actived;
Shuah Khan3266d732013-07-03 10:47:10 -0600105 struct pci_dev *pdev = to_pci_dev(dev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800106
107 if (pdev) {
Jingoo Hanb2a31202013-09-09 14:26:51 +0900108 card = pci_get_drvdata(pdev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800109 if (!card || !card->adapter) {
110 pr_err("Card or adapter structure is not valid\n");
111 return 0;
112 }
113 } else {
114 pr_err("PCIE device is not specified\n");
115 return 0;
116 }
117
118 adapter = card->adapter;
119
120 hs_actived = mwifiex_enable_hs(adapter);
121
122 /* Indicate device suspended */
123 adapter->is_suspended = true;
Amitkumar Karwarc0dbba62014-03-25 19:01:20 -0700124 adapter->hs_enabling = false;
Bing Zhaofcca8d52013-03-04 16:27:53 -0800125
126 return 0;
127}
128
129/*
130 * Kernel needs to suspend all functions separately. Therefore all
131 * registered functions must have drivers with suspend and resume
132 * methods. Failing that the kernel simply removes the whole card.
133 *
134 * If already not resumed, this function turns on the traffic and
135 * sends a host sleep cancel request to the firmware.
136 */
Shuah Khan3266d732013-07-03 10:47:10 -0600137static int mwifiex_pcie_resume(struct device *dev)
Bing Zhaofcca8d52013-03-04 16:27:53 -0800138{
139 struct mwifiex_adapter *adapter;
140 struct pcie_service_card *card;
Shuah Khan3266d732013-07-03 10:47:10 -0600141 struct pci_dev *pdev = to_pci_dev(dev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800142
143 if (pdev) {
Jingoo Hanb2a31202013-09-09 14:26:51 +0900144 card = pci_get_drvdata(pdev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800145 if (!card || !card->adapter) {
146 pr_err("Card or adapter structure is not valid\n");
147 return 0;
148 }
149 } else {
150 pr_err("PCIE device is not specified\n");
151 return 0;
152 }
153
154 adapter = card->adapter;
155
156 if (!adapter->is_suspended) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530157 mwifiex_dbg(adapter, WARN,
158 "Device already resumed\n");
Bing Zhaofcca8d52013-03-04 16:27:53 -0800159 return 0;
160 }
161
162 adapter->is_suspended = false;
163
164 mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
165 MWIFIEX_ASYNC_CMD);
166
167 return 0;
168}
Bing Zhao8509e822013-03-04 16:27:54 -0800169#endif
Bing Zhaofcca8d52013-03-04 16:27:53 -0800170
171/*
Amitkumar Karward930fae2011-10-11 17:41:21 -0700172 * This function probes an mwifiex device and registers it. It allocates
173 * the card structure, enables PCIE function number and initiates the
174 * device registration and initialization procedure by adding a logical
175 * interface.
176 */
177static int mwifiex_pcie_probe(struct pci_dev *pdev,
178 const struct pci_device_id *ent)
179{
180 struct pcie_service_card *card;
181
182 pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700183 pdev->vendor, pdev->device, pdev->revision);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700184
185 card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
Joe Perchese404dec2012-01-29 12:56:23 +0000186 if (!card)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700187 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700188
189 card->dev = pdev;
190
Avinash Patildd04e6a2013-02-08 18:18:06 -0800191 if (ent->driver_data) {
192 struct mwifiex_pcie_device *data = (void *)ent->driver_data;
193 card->pcie.firmware = data->firmware;
194 card->pcie.reg = data->reg;
195 card->pcie.blksz_fw_dl = data->blksz_fw_dl;
Amitkumar Karwar828cf222014-02-27 19:35:13 -0800196 card->pcie.tx_buf_size = data->tx_buf_size;
Avinash Patilb4e8aeb2015-02-11 23:12:26 +0530197 card->pcie.can_dump_fw = data->can_dump_fw;
Xinming Hu50632092016-02-02 22:05:06 -0800198 card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl;
199 card->pcie.num_mem_types = data->num_mem_types;
Avinash Patil1fe192d2015-01-23 17:09:19 +0530200 card->pcie.can_ext_scan = data->can_ext_scan;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800201 }
202
Amitkumar Karward930fae2011-10-11 17:41:21 -0700203 if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
204 MWIFIEX_PCIE)) {
205 pr_err("%s failed\n", __func__);
206 kfree(card);
207 return -1;
208 }
209
210 return 0;
211}
212
213/*
214 * This function removes the interface and frees up the card structure.
215 */
216static void mwifiex_pcie_remove(struct pci_dev *pdev)
217{
218 struct pcie_service_card *card;
219 struct mwifiex_adapter *adapter;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700220 struct mwifiex_private *priv;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700221
222 card = pci_get_drvdata(pdev);
223 if (!card)
224 return;
225
226 adapter = card->adapter;
227 if (!adapter || !adapter->priv_num)
228 return;
229
230 if (user_rmmod) {
Shuah Khan3266d732013-07-03 10:47:10 -0600231#ifdef CONFIG_PM_SLEEP
Amitkumar Karward930fae2011-10-11 17:41:21 -0700232 if (adapter->is_suspended)
Shuah Khan3266d732013-07-03 10:47:10 -0600233 mwifiex_pcie_resume(&pdev->dev);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700234#endif
235
Amitkumar Karwar848819f2014-02-27 19:35:17 -0800236 mwifiex_deauthenticate_all(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700237
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700238 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700239
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700240 mwifiex_disable_auto_ds(priv);
241
242 mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700243 }
244
245 mwifiex_remove_card(card->adapter, &add_remove_card_sem);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700246}
247
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700248static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
249{
250 user_rmmod = 1;
251 mwifiex_pcie_remove(pdev);
252
253 return;
254}
255
Benoit Taine9baa3c32014-08-08 15:56:03 +0200256static const struct pci_device_id mwifiex_ids[] = {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700257 {
258 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
259 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700260 .driver_data = (unsigned long)&mwifiex_pcie8766,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700261 },
Avinash Patilca8f2112013-02-08 18:18:09 -0800262 {
263 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
264 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700265 .driver_data = (unsigned long)&mwifiex_pcie8897,
266 },
267 {
268 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
269 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
270 .driver_data = (unsigned long)&mwifiex_pcie8997,
Avinash Patilca8f2112013-02-08 18:18:09 -0800271 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700272 {},
273};
274
275MODULE_DEVICE_TABLE(pci, mwifiex_ids);
276
Shuah Khan3266d732013-07-03 10:47:10 -0600277#ifdef CONFIG_PM_SLEEP
278/* Power Management Hooks */
279static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
280 mwifiex_pcie_resume);
281#endif
282
Amitkumar Karward930fae2011-10-11 17:41:21 -0700283/* PCI Device Driver */
284static struct pci_driver __refdata mwifiex_pcie = {
285 .name = "mwifiex_pcie",
286 .id_table = mwifiex_ids,
287 .probe = mwifiex_pcie_probe,
288 .remove = mwifiex_pcie_remove,
Shuah Khan3266d732013-07-03 10:47:10 -0600289#ifdef CONFIG_PM_SLEEP
290 .driver = {
291 .pm = &mwifiex_pcie_pm_ops,
292 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700293#endif
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700294 .shutdown = mwifiex_pcie_shutdown,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700295};
296
297/*
298 * This function writes data into PCIE card register.
299 */
300static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
301{
302 struct pcie_service_card *card = adapter->card;
303
304 iowrite32(data, card->pci_mmap1 + reg);
305
306 return 0;
307}
308
309/*
310 * This function reads data from PCIE card register.
311 */
312static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
313{
314 struct pcie_service_card *card = adapter->card;
315
316 *data = ioread32(card->pci_mmap1 + reg);
Xinming Huaf051482016-02-02 22:05:03 -0800317 if (*data == 0xffffffff)
318 return 0xffffffff;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700319
320 return 0;
321}
322
Amitkumar Karwar92c25382014-06-19 21:38:52 -0700323/* This function reads u8 data from PCIE card register. */
324static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
325 int reg, u8 *data)
326{
327 struct pcie_service_card *card = adapter->card;
328
329 *data = ioread8(card->pci_mmap1 + reg);
330
331 return 0;
332}
333
Amitkumar Karward930fae2011-10-11 17:41:21 -0700334/*
Avinash Patilc0880a22013-03-22 21:49:07 -0700335 * This function adds delay loop to ensure FW is awake before proceeding.
Amitkumar Karward930fae2011-10-11 17:41:21 -0700336 */
Avinash Patilc0880a22013-03-22 21:49:07 -0700337static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700338{
339 int i = 0;
340
Avinash Patilc0880a22013-03-22 21:49:07 -0700341 while (mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700342 i++;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -0700343 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700344 /* 50ms max wait */
Avinash Patil3e7a4ff2013-02-25 16:01:34 -0800345 if (i == 5000)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700346 break;
347 }
348
Avinash Patilc0880a22013-03-22 21:49:07 -0700349 return;
350}
351
Avinash Patilc4bc9802014-03-18 22:19:17 -0700352static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
353 u32 max_delay_loop_cnt)
354{
355 struct pcie_service_card *card = adapter->card;
356 u8 *buffer;
357 u32 sleep_cookie, count;
358
359 for (count = 0; count < max_delay_loop_cnt; count++) {
360 buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
361 sleep_cookie = *(u32 *)buffer;
362
363 if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530364 mwifiex_dbg(adapter, INFO,
365 "sleep cookie found at count %d\n", count);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700366 break;
367 }
368 usleep_range(20, 30);
369 }
370
371 if (count >= max_delay_loop_cnt)
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530372 mwifiex_dbg(adapter, INFO,
373 "max count reached while accessing sleep cookie\n");
Avinash Patilc4bc9802014-03-18 22:19:17 -0700374}
375
Avinash Patilc0880a22013-03-22 21:49:07 -0700376/* This function wakes up the card by reading fw_status register. */
377static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
378{
379 u32 fw_status;
380 struct pcie_service_card *card = adapter->card;
381 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
382
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530383 mwifiex_dbg(adapter, EVENT,
384 "event: Wakeup device...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700385
Avinash Patilc0880a22013-03-22 21:49:07 -0700386 if (reg->sleep_cookie)
387 mwifiex_pcie_dev_wakeup_delay(adapter);
388
389 /* Reading fw_status register will wakeup device */
390 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530391 mwifiex_dbg(adapter, ERROR,
392 "Reading fw_status register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700393 return -1;
394 }
395
Avinash Patilc0880a22013-03-22 21:49:07 -0700396 if (reg->sleep_cookie) {
397 mwifiex_pcie_dev_wakeup_delay(adapter);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530398 mwifiex_dbg(adapter, INFO,
399 "PCIE wakeup: Setting PS_STATE_AWAKE\n");
Avinash Patilc0880a22013-03-22 21:49:07 -0700400 adapter->ps_state = PS_STATE_AWAKE;
401 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700402
403 return 0;
404}
405
406/*
407 * This function is called after the card has woken up.
408 *
409 * The card configuration register is reset.
410 */
411static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
412{
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530413 mwifiex_dbg(adapter, CMD,
414 "cmd: Wakeup device completed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700415
416 return 0;
417}
418
419/*
420 * This function disables the host interrupt.
421 *
422 * The host interrupt mask is read, the disable bit is reset and
423 * written back to the card host interrupt mask register.
424 */
425static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
426{
427 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
428 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
429 0x00000000)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530430 mwifiex_dbg(adapter, ERROR,
431 "Disable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700432 return -1;
433 }
434 }
435
436 return 0;
437}
438
439/*
440 * This function enables the host interrupt.
441 *
442 * The host interrupt enable mask is written to the card
443 * host interrupt mask register.
444 */
445static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
446{
447 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
448 /* Simply write the mask to the register */
449 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
450 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530451 mwifiex_dbg(adapter, ERROR,
452 "Enable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700453 return -1;
454 }
455 }
456
457 return 0;
458}
459
460/*
Avinash Patil07324842013-02-08 18:18:07 -0800461 * This function initializes TX buffer ring descriptors
462 */
463static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
464{
465 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800466 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800467 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800468 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800469 int i;
470
471 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
472 card->tx_buf_list[i] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -0800473 if (reg->pfu_enabled) {
474 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
475 (sizeof(*desc2) * i);
476 desc2 = card->txbd_ring[i];
477 memset(desc2, 0, sizeof(*desc2));
478 } else {
479 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
480 (sizeof(*desc) * i);
481 desc = card->txbd_ring[i];
482 memset(desc, 0, sizeof(*desc));
483 }
Avinash Patil07324842013-02-08 18:18:07 -0800484 }
485
486 return 0;
487}
488
489/* This function initializes RX buffer ring descriptors. Each SKB is allocated
490 * here and after mapping PCI memory, its physical address is assigned to
491 * PCIE Rx buffer descriptor's physical address.
492 */
493static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
494{
495 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800496 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800497 struct sk_buff *skb;
498 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800499 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800500 dma_addr_t buf_pa;
501 int i;
502
503 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
504 /* Allocate skb here so that firmware can DMA data from it */
Avinash Patil62159942015-03-13 17:37:52 +0530505 skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
506 GFP_KERNEL | GFP_DMA);
Avinash Patil07324842013-02-08 18:18:07 -0800507 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530508 mwifiex_dbg(adapter, ERROR,
509 "Unable to allocate skb for RX ring.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800510 kfree(card->rxbd_ring_vbase);
511 return -ENOMEM;
512 }
513
514 if (mwifiex_map_pci_memory(adapter, skb,
515 MWIFIEX_RX_DATA_BUF_SIZE,
516 PCI_DMA_FROMDEVICE))
517 return -1;
518
Aaron Durbindbccc922014-02-07 16:25:50 -0800519 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800520
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530521 mwifiex_dbg(adapter, INFO,
522 "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
523 skb, skb->len, skb->data, (u32)buf_pa,
524 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800525
526 card->rx_buf_list[i] = skb;
Avinash Patilca8f2112013-02-08 18:18:09 -0800527 if (reg->pfu_enabled) {
528 card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
529 (sizeof(*desc2) * i);
530 desc2 = card->rxbd_ring[i];
531 desc2->paddr = buf_pa;
532 desc2->len = (u16)skb->len;
533 desc2->frag_len = (u16)skb->len;
534 desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
535 desc2->offset = 0;
536 } else {
537 card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
538 (sizeof(*desc) * i));
539 desc = card->rxbd_ring[i];
540 desc->paddr = buf_pa;
541 desc->len = (u16)skb->len;
542 desc->flags = 0;
543 }
Avinash Patil07324842013-02-08 18:18:07 -0800544 }
545
546 return 0;
547}
548
549/* This function initializes event buffer ring descriptors. Each SKB is
550 * allocated here and after mapping PCI memory, its physical address is assigned
551 * to PCIE Rx buffer descriptor's physical address
552 */
553static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
554{
555 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800556 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800557 struct sk_buff *skb;
558 dma_addr_t buf_pa;
559 int i;
560
561 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
562 /* Allocate skb here so that firmware can DMA data from it */
563 skb = dev_alloc_skb(MAX_EVENT_SIZE);
564 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530565 mwifiex_dbg(adapter, ERROR,
566 "Unable to allocate skb for EVENT buf.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800567 kfree(card->evtbd_ring_vbase);
568 return -ENOMEM;
569 }
570 skb_put(skb, MAX_EVENT_SIZE);
571
572 if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
573 PCI_DMA_FROMDEVICE))
574 return -1;
575
Aaron Durbindbccc922014-02-07 16:25:50 -0800576 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800577
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530578 mwifiex_dbg(adapter, EVENT,
579 "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
580 skb, skb->len, skb->data, (u32)buf_pa,
581 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800582
583 card->evt_buf_list[i] = skb;
584 card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
585 (sizeof(*desc) * i));
Avinash Patil07324842013-02-08 18:18:07 -0800586 desc = card->evtbd_ring[i];
587 desc->paddr = buf_pa;
588 desc->len = (u16)skb->len;
589 desc->flags = 0;
590 }
591
592 return 0;
593}
594
595/* This function cleans up TX buffer rings. If any of the buffer list has valid
596 * SKB address, associated SKB is freed.
597 */
598static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
599{
600 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800601 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800602 struct sk_buff *skb;
603 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800604 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800605 int i;
606
607 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800608 if (reg->pfu_enabled) {
609 desc2 = card->txbd_ring[i];
610 if (card->tx_buf_list[i]) {
611 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800612 mwifiex_unmap_pci_memory(adapter, skb,
613 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800614 dev_kfree_skb_any(skb);
615 }
616 memset(desc2, 0, sizeof(*desc2));
617 } else {
618 desc = card->txbd_ring[i];
619 if (card->tx_buf_list[i]) {
620 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800621 mwifiex_unmap_pci_memory(adapter, skb,
622 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800623 dev_kfree_skb_any(skb);
624 }
625 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800626 }
627 card->tx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800628 }
629
630 return;
631}
632
633/* This function cleans up RX buffer rings. If any of the buffer list has valid
634 * SKB address, associated SKB is freed.
635 */
636static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
637{
638 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800639 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800640 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800641 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800642 struct sk_buff *skb;
643 int i;
644
645 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800646 if (reg->pfu_enabled) {
647 desc2 = card->rxbd_ring[i];
648 if (card->rx_buf_list[i]) {
649 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800650 mwifiex_unmap_pci_memory(adapter, skb,
651 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800652 dev_kfree_skb_any(skb);
653 }
654 memset(desc2, 0, sizeof(*desc2));
655 } else {
656 desc = card->rxbd_ring[i];
657 if (card->rx_buf_list[i]) {
658 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800659 mwifiex_unmap_pci_memory(adapter, skb,
660 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800661 dev_kfree_skb_any(skb);
662 }
663 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800664 }
Avinash Patilca8f2112013-02-08 18:18:09 -0800665 card->rx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800666 }
667
668 return;
669}
670
671/* This function cleans up event buffer rings. If any of the buffer list has
672 * valid SKB address, associated SKB is freed.
673 */
674static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
675{
676 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800677 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800678 struct sk_buff *skb;
679 int i;
680
681 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
682 desc = card->evtbd_ring[i];
683 if (card->evt_buf_list[i]) {
684 skb = card->evt_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800685 mwifiex_unmap_pci_memory(adapter, skb,
686 PCI_DMA_FROMDEVICE);
Avinash Patil07324842013-02-08 18:18:07 -0800687 dev_kfree_skb_any(skb);
688 }
689 card->evt_buf_list[i] = NULL;
690 memset(desc, 0, sizeof(*desc));
691 }
692
693 return;
694}
695
696/* This function creates buffer descriptor ring for TX
Amitkumar Karward930fae2011-10-11 17:41:21 -0700697 */
698static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
699{
700 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800701 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700702
703 /*
704 * driver maintaines the write pointer and firmware maintaines the read
705 * pointer. The write pointer starts at 0 (zero) while the read pointer
706 * starts at zero with rollover bit set
707 */
708 card->txbd_wrptr = 0;
Avinash Patilca8f2112013-02-08 18:18:09 -0800709
710 if (reg->pfu_enabled)
711 card->txbd_rdptr = 0;
712 else
713 card->txbd_rdptr |= reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700714
715 /* allocate shared memory for the BD ring and divide the same in to
716 several descriptors */
Avinash Patilca8f2112013-02-08 18:18:09 -0800717 if (reg->pfu_enabled)
718 card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
719 MWIFIEX_MAX_TXRX_BD;
720 else
721 card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
722 MWIFIEX_MAX_TXRX_BD;
723
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530724 mwifiex_dbg(adapter, INFO,
725 "info: txbd_ring: Allocating %d bytes\n",
726 card->txbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800727 card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
728 card->txbd_ring_size,
729 &card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700730 if (!card->txbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530731 mwifiex_dbg(adapter, ERROR,
732 "allocate consistent memory (%d bytes) failed!\n",
733 card->txbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800734 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700735 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530736 mwifiex_dbg(adapter, DATA,
737 "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
738 card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
739 (u32)((u64)card->txbd_ring_pbase >> 32),
740 card->txbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700741
Avinash Patil07324842013-02-08 18:18:07 -0800742 return mwifiex_init_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700743}
744
745static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
746{
747 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800748 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700749
Avinash Patil07324842013-02-08 18:18:07 -0800750 mwifiex_cleanup_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700751
Avinash Patilfc331462013-01-03 21:21:30 -0800752 if (card->txbd_ring_vbase)
753 pci_free_consistent(card->dev, card->txbd_ring_size,
754 card->txbd_ring_vbase,
755 card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700756 card->txbd_ring_size = 0;
757 card->txbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800758 card->txbd_rdptr = 0 | reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700759 card->txbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800760 card->txbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700761
762 return 0;
763}
764
765/*
766 * This function creates buffer descriptor ring for RX
767 */
768static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
769{
770 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800771 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700772
773 /*
774 * driver maintaines the read pointer and firmware maintaines the write
775 * pointer. The write pointer starts at 0 (zero) while the read pointer
776 * starts at zero with rollover bit set
777 */
778 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800779 card->rxbd_rdptr = reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700780
Avinash Patilca8f2112013-02-08 18:18:09 -0800781 if (reg->pfu_enabled)
782 card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
783 MWIFIEX_MAX_TXRX_BD;
784 else
785 card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
786 MWIFIEX_MAX_TXRX_BD;
787
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530788 mwifiex_dbg(adapter, INFO,
789 "info: rxbd_ring: Allocating %d bytes\n",
790 card->rxbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800791 card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
792 card->rxbd_ring_size,
793 &card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700794 if (!card->rxbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530795 mwifiex_dbg(adapter, ERROR,
796 "allocate consistent memory (%d bytes) failed!\n",
797 card->rxbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800798 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700799 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700800
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530801 mwifiex_dbg(adapter, DATA,
802 "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
803 card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
804 (u32)((u64)card->rxbd_ring_pbase >> 32),
805 card->rxbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700806
Avinash Patil07324842013-02-08 18:18:07 -0800807 return mwifiex_init_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700808}
809
810/*
811 * This function deletes Buffer descriptor ring for RX
812 */
813static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
814{
815 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800816 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700817
Avinash Patil07324842013-02-08 18:18:07 -0800818 mwifiex_cleanup_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700819
Avinash Patilfc331462013-01-03 21:21:30 -0800820 if (card->rxbd_ring_vbase)
821 pci_free_consistent(card->dev, card->rxbd_ring_size,
822 card->rxbd_ring_vbase,
823 card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700824 card->rxbd_ring_size = 0;
825 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800826 card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700827 card->rxbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800828 card->rxbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700829
830 return 0;
831}
832
833/*
834 * This function creates buffer descriptor ring for Events
835 */
836static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
837{
838 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800839 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700840
841 /*
842 * driver maintaines the read pointer and firmware maintaines the write
843 * pointer. The write pointer starts at 0 (zero) while the read pointer
844 * starts at zero with rollover bit set
845 */
846 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800847 card->evtbd_rdptr = reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700848
Avinash Patile05dc3e2013-02-08 18:18:08 -0800849 card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
Avinash Patilca8f2112013-02-08 18:18:09 -0800850 MWIFIEX_MAX_EVT_BD;
851
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530852 mwifiex_dbg(adapter, INFO,
853 "info: evtbd_ring: Allocating %d bytes\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700854 card->evtbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800855 card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
856 card->evtbd_ring_size,
857 &card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700858 if (!card->evtbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530859 mwifiex_dbg(adapter, ERROR,
860 "allocate consistent memory (%d bytes) failed!\n",
861 card->evtbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800862 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700863 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700864
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530865 mwifiex_dbg(adapter, EVENT,
866 "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
867 card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
868 (u32)((u64)card->evtbd_ring_pbase >> 32),
869 card->evtbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700870
Avinash Patil07324842013-02-08 18:18:07 -0800871 return mwifiex_pcie_init_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700872}
873
874/*
875 * This function deletes Buffer descriptor ring for Events
876 */
877static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
878{
879 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800880 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700881
Avinash Patil07324842013-02-08 18:18:07 -0800882 mwifiex_cleanup_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700883
Avinash Patilfc331462013-01-03 21:21:30 -0800884 if (card->evtbd_ring_vbase)
885 pci_free_consistent(card->dev, card->evtbd_ring_size,
886 card->evtbd_ring_vbase,
887 card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700888 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800889 card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700890 card->evtbd_ring_size = 0;
891 card->evtbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800892 card->evtbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700893
894 return 0;
895}
896
897/*
898 * This function allocates a buffer for CMDRSP
899 */
900static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
901{
902 struct pcie_service_card *card = adapter->card;
903 struct sk_buff *skb;
904
905 /* Allocate memory for receiving command response data */
906 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
907 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530908 mwifiex_dbg(adapter, ERROR,
909 "Unable to allocate skb for command response data.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700910 return -ENOMEM;
911 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700912 skb_put(skb, MWIFIEX_UPLD_SIZE);
Avinash Patilfc331462013-01-03 21:21:30 -0800913 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
914 PCI_DMA_FROMDEVICE))
915 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700916
Avinash Patilfc331462013-01-03 21:21:30 -0800917 card->cmdrsp_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700918
919 return 0;
920}
921
922/*
923 * This function deletes a buffer for CMDRSP
924 */
925static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
926{
927 struct pcie_service_card *card;
928
929 if (!adapter)
930 return 0;
931
932 card = adapter->card;
933
Avinash Patilfc331462013-01-03 21:21:30 -0800934 if (card && card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800935 mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
936 PCI_DMA_FROMDEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700937 dev_kfree_skb_any(card->cmdrsp_buf);
Avinash Patilfc331462013-01-03 21:21:30 -0800938 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700939
Avinash Patilfc331462013-01-03 21:21:30 -0800940 if (card && card->cmd_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800941 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
942 PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -0800943 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700944 return 0;
945}
946
947/*
948 * This function allocates a buffer for sleep cookie
949 */
950static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
951{
Amitkumar Karward930fae2011-10-11 17:41:21 -0700952 struct pcie_service_card *card = adapter->card;
953
Avinash Patilfc331462013-01-03 21:21:30 -0800954 card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
955 &card->sleep_cookie_pbase);
956 if (!card->sleep_cookie_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530957 mwifiex_dbg(adapter, ERROR,
958 "pci_alloc_consistent failed!\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700959 return -ENOMEM;
960 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700961 /* Init val of Sleep Cookie */
Avinash Patilfc331462013-01-03 21:21:30 -0800962 *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700963
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530964 mwifiex_dbg(adapter, INFO,
965 "alloc_scook: sleep cookie=0x%x\n",
966 *((u32 *)card->sleep_cookie_vbase));
Amitkumar Karward930fae2011-10-11 17:41:21 -0700967
968 return 0;
969}
970
971/*
972 * This function deletes buffer for sleep cookie
973 */
974static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
975{
976 struct pcie_service_card *card;
977
978 if (!adapter)
979 return 0;
980
981 card = adapter->card;
982
Avinash Patilfc331462013-01-03 21:21:30 -0800983 if (card && card->sleep_cookie_vbase) {
984 pci_free_consistent(card->dev, sizeof(u32),
985 card->sleep_cookie_vbase,
986 card->sleep_cookie_pbase);
987 card->sleep_cookie_vbase = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700988 }
989
990 return 0;
991}
992
Avinash Patilfbd7e7a2013-01-03 21:21:31 -0800993/* This function flushes the TX buffer descriptor ring
994 * This function defined as handler is also called while cleaning TXRX
995 * during disconnect/ bss stop.
996 */
997static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
998{
999 struct pcie_service_card *card = adapter->card;
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001000
Avinash Patil48f4d912013-02-20 21:12:58 -08001001 if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001002 card->txbd_flush = 1;
1003 /* write pointer already set at last send
1004 * send dnld-rdy intr again, wait for completion.
1005 */
1006 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1007 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301008 mwifiex_dbg(adapter, ERROR,
1009 "failed to assert dnld-rdy interrupt.\n");
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001010 return -1;
1011 }
1012 }
1013 return 0;
1014}
1015
Amitkumar Karward930fae2011-10-11 17:41:21 -07001016/*
Avinash Patile7f767a2013-01-03 21:21:32 -08001017 * This function unmaps and frees downloaded data buffer
Amitkumar Karward930fae2011-10-11 17:41:21 -07001018 */
Avinash Patile7f767a2013-01-03 21:21:32 -08001019static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001020{
Avinash Patile7f767a2013-01-03 21:21:32 -08001021 struct sk_buff *skb;
Avinash Patilca8f2112013-02-08 18:18:09 -08001022 u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001023 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001024 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001025 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001026 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001027
1028 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1029 mwifiex_pm_wakeup_card(adapter);
1030
1031 /* Read the TX ring read pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001032 if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301033 mwifiex_dbg(adapter, ERROR,
1034 "SEND COMP: failed to read reg->tx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001035 return -1;
1036 }
1037
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301038 mwifiex_dbg(adapter, DATA,
1039 "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
1040 card->txbd_rdptr, rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001041
Avinash Patilca8f2112013-02-08 18:18:09 -08001042 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001043 /* free from previous txbd_rdptr to current txbd_rdptr */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001044 while (((card->txbd_rdptr & reg->tx_mask) !=
1045 (rdptr & reg->tx_mask)) ||
1046 ((card->txbd_rdptr & reg->tx_rollover_ind) !=
1047 (rdptr & reg->tx_rollover_ind))) {
Avinash Patilca8f2112013-02-08 18:18:09 -08001048 wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
1049 reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001050
1051 skb = card->tx_buf_list[wrdoneidx];
Aaron Durbindbccc922014-02-07 16:25:50 -08001052
Avinash Patile7f767a2013-01-03 21:21:32 -08001053 if (skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301054 mwifiex_dbg(adapter, DATA,
1055 "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
1056 skb, wrdoneidx);
Aaron Durbindbccc922014-02-07 16:25:50 -08001057 mwifiex_unmap_pci_memory(adapter, skb,
1058 PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001059
1060 unmap_count++;
1061
1062 if (card->txbd_flush)
1063 mwifiex_write_data_complete(adapter, skb, 0,
1064 -1);
1065 else
1066 mwifiex_write_data_complete(adapter, skb, 0, 0);
1067 }
1068
1069 card->tx_buf_list[wrdoneidx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001070
1071 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001072 desc2 = card->txbd_ring[wrdoneidx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001073 memset(desc2, 0, sizeof(*desc2));
1074 } else {
1075 desc = card->txbd_ring[wrdoneidx];
1076 memset(desc, 0, sizeof(*desc));
1077 }
1078 switch (card->dev->device) {
1079 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1080 card->txbd_rdptr++;
1081 break;
1082 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001083 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001084 card->txbd_rdptr += reg->ring_tx_start_ptr;
1085 break;
1086 }
1087
Avinash Patile7f767a2013-01-03 21:21:32 -08001088
Avinash Patildd04e6a2013-02-08 18:18:06 -08001089 if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
Avinash Patile7f767a2013-01-03 21:21:32 -08001090 card->txbd_rdptr = ((card->txbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001091 reg->tx_rollover_ind) ^
1092 reg->tx_rollover_ind);
Avinash Patile7f767a2013-01-03 21:21:32 -08001093 }
1094
1095 if (unmap_count)
1096 adapter->data_sent = false;
1097
1098 if (card->txbd_flush) {
Avinash Patil3d482032013-02-15 21:37:54 -08001099 if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
Avinash Patile7f767a2013-01-03 21:21:32 -08001100 card->txbd_flush = 0;
1101 else
1102 mwifiex_clean_pcie_ring_buf(adapter);
1103 }
1104
1105 return 0;
1106}
1107
1108/* This function sends data buffer to device. First 4 bytes of payload
1109 * are filled with payload length and payload type. Then this payload
1110 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
1111 * Download ready interrupt to FW is deffered if Tx ring is not full and
1112 * additional payload can be accomodated.
Avinash Patil8d767dc2014-05-13 19:50:13 -07001113 * Caller must ensure tx_param parameter to this function is not NULL.
Avinash Patile7f767a2013-01-03 21:21:32 -08001114 */
1115static int
1116mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
1117 struct mwifiex_tx_param *tx_param)
1118{
1119 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001120 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001121 u32 wrindx, num_tx_buffs, rx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001122 int ret;
1123 dma_addr_t buf_pa;
Bing Zhao99310782013-03-04 16:27:55 -08001124 struct mwifiex_pcie_buf_desc *desc = NULL;
1125 struct mwifiex_pfu_buf_desc *desc2 = NULL;
Avinash Patile7f767a2013-01-03 21:21:32 -08001126 __le16 *tmp;
1127
1128 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301129 mwifiex_dbg(adapter, ERROR,
1130 "%s(): invalid parameter <%p, %#x>\n",
1131 __func__, skb->data, skb->len);
Avinash Patile7f767a2013-01-03 21:21:32 -08001132 return -1;
1133 }
1134
1135 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1136 mwifiex_pm_wakeup_card(adapter);
1137
Avinash Patilca8f2112013-02-08 18:18:09 -08001138 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301139 mwifiex_dbg(adapter, DATA,
1140 "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
Avinash Patile7f767a2013-01-03 21:21:32 -08001141 card->txbd_rdptr, card->txbd_wrptr);
1142 if (mwifiex_pcie_txbd_not_full(card)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001143 u8 *payload;
1144
1145 adapter->data_sent = true;
Avinash Patile7f767a2013-01-03 21:21:32 -08001146 payload = skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001147 tmp = (__le16 *)&payload[0];
1148 *tmp = cpu_to_le16((u16)skb->len);
1149 tmp = (__le16 *)&payload[2];
1150 *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
Avinash Patile7f767a2013-01-03 21:21:32 -08001151
Aaron Durbindbccc922014-02-07 16:25:50 -08001152 if (mwifiex_map_pci_memory(adapter, skb, skb->len,
Avinash Patile7f767a2013-01-03 21:21:32 -08001153 PCI_DMA_TODEVICE))
1154 return -1;
1155
Avinash Patilca8f2112013-02-08 18:18:09 -08001156 wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
Aaron Durbindbccc922014-02-07 16:25:50 -08001157 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile7f767a2013-01-03 21:21:32 -08001158 card->tx_buf_list[wrindx] = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001159
Avinash Patilca8f2112013-02-08 18:18:09 -08001160 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001161 desc2 = card->txbd_ring[wrindx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001162 desc2->paddr = buf_pa;
1163 desc2->len = (u16)skb->len;
1164 desc2->frag_len = (u16)skb->len;
1165 desc2->offset = 0;
1166 desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1167 MWIFIEX_BD_FLAG_LAST_DESC;
1168 } else {
1169 desc = card->txbd_ring[wrindx];
1170 desc->paddr = buf_pa;
1171 desc->len = (u16)skb->len;
1172 desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1173 MWIFIEX_BD_FLAG_LAST_DESC;
1174 }
1175
1176 switch (card->dev->device) {
1177 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1178 card->txbd_wrptr++;
1179 break;
1180 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001181 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001182 card->txbd_wrptr += reg->ring_tx_start_ptr;
1183 break;
1184 }
1185
1186 if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001187 card->txbd_wrptr = ((card->txbd_wrptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001188 reg->tx_rollover_ind) ^
1189 reg->tx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001190
Avinash Patilca8f2112013-02-08 18:18:09 -08001191 rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001192 /* Write the TX ring write pointer in to reg->tx_wrptr */
1193 if (mwifiex_write_reg(adapter, reg->tx_wrptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001194 card->txbd_wrptr | rx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301195 mwifiex_dbg(adapter, ERROR,
1196 "SEND DATA: failed to write reg->tx_wrptr\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001197 ret = -1;
1198 goto done_unmap;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001199 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001200 if ((mwifiex_pcie_txbd_not_full(card)) &&
1201 tx_param->next_pkt_len) {
1202 /* have more packets and TxBD still can hold more */
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301203 mwifiex_dbg(adapter, DATA,
1204 "SEND DATA: delay dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001205 adapter->data_sent = false;
1206 } else {
1207 /* Send the TX ready interrupt */
1208 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1209 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301210 mwifiex_dbg(adapter, ERROR,
1211 "SEND DATA: failed to assert dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001212 ret = -1;
1213 goto done_unmap;
1214 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001215 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301216 mwifiex_dbg(adapter, DATA,
1217 "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
1218 "%#x> and sent packet to firmware successfully\n",
1219 card->txbd_rdptr, card->txbd_wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001220 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301221 mwifiex_dbg(adapter, DATA,
1222 "info: TX Ring full, can't send packets to fw\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001223 adapter->data_sent = true;
1224 /* Send the TX ready interrupt */
1225 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1226 CPU_INTR_DNLD_RDY))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301227 mwifiex_dbg(adapter, ERROR,
1228 "SEND DATA: failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001229 return -EBUSY;
1230 }
1231
Avinash Patile7f767a2013-01-03 21:21:32 -08001232 return -EINPROGRESS;
1233done_unmap:
Aaron Durbindbccc922014-02-07 16:25:50 -08001234 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001235 card->tx_buf_list[wrindx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001236 if (reg->pfu_enabled)
1237 memset(desc2, 0, sizeof(*desc2));
1238 else
1239 memset(desc, 0, sizeof(*desc));
1240
Avinash Patile7f767a2013-01-03 21:21:32 -08001241 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001242}
1243
1244/*
1245 * This function handles received buffer ring and
1246 * dispatches packets to upper
1247 */
1248static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
1249{
1250 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001251 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001252 u32 wrptr, rd_index, tx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001253 dma_addr_t buf_pa;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001254 int ret = 0;
1255 struct sk_buff *skb_tmp = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001256 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001257 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001258
Avinash Patile7f767a2013-01-03 21:21:32 -08001259 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1260 mwifiex_pm_wakeup_card(adapter);
1261
Amitkumar Karward930fae2011-10-11 17:41:21 -07001262 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001263 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301264 mwifiex_dbg(adapter, ERROR,
1265 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001266 ret = -1;
1267 goto done;
1268 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001269 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001270
Avinash Patildd04e6a2013-02-08 18:18:06 -08001271 while (((wrptr & reg->rx_mask) !=
1272 (card->rxbd_rdptr & reg->rx_mask)) ||
1273 ((wrptr & reg->rx_rollover_ind) ==
1274 (card->rxbd_rdptr & reg->rx_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001275 struct sk_buff *skb_data;
1276 u16 rx_len;
Avinash Patile7f767a2013-01-03 21:21:32 -08001277 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001278
Avinash Patildd04e6a2013-02-08 18:18:06 -08001279 rd_index = card->rxbd_rdptr & reg->rx_mask;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001280 skb_data = card->rx_buf_list[rd_index];
1281
Amitkumar Karwarbb8e6a12014-02-18 15:41:55 -08001282 /* If skb allocation was failed earlier for Rx packet,
1283 * rx_buf_list[rd_index] would have been left with a NULL.
1284 */
1285 if (!skb_data)
1286 return -ENOMEM;
1287
Aaron Durbindbccc922014-02-07 16:25:50 -08001288 mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001289 card->rx_buf_list[rd_index] = NULL;
1290
Amitkumar Karward930fae2011-10-11 17:41:21 -07001291 /* Get data length from interface header -
Avinash Patile7f767a2013-01-03 21:21:32 -08001292 * first 2 bytes for len, next 2 bytes is for type
1293 */
1294 pkt_len = *((__le16 *)skb_data->data);
1295 rx_len = le16_to_cpu(pkt_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301296 if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
1297 rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301298 mwifiex_dbg(adapter, ERROR,
1299 "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
1300 rx_len, card->rxbd_rdptr, wrptr);
Avinash Patil42a028a2014-09-12 20:08:47 +05301301 dev_kfree_skb_any(skb_data);
1302 } else {
1303 skb_put(skb_data, rx_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301304 mwifiex_dbg(adapter, DATA,
1305 "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
1306 card->rxbd_rdptr, wrptr, rx_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301307 skb_pull(skb_data, INTF_HEADER_LEN);
Avinash Patil6e251172014-09-12 20:08:59 +05301308 if (adapter->rx_work_enabled) {
Avinash Patil6e251172014-09-12 20:08:59 +05301309 skb_queue_tail(&adapter->rx_data_q, skb_data);
Avinash Patil6e251172014-09-12 20:08:59 +05301310 adapter->data_received = true;
1311 atomic_inc(&adapter->rx_pending);
1312 } else {
1313 mwifiex_handle_rx_packet(adapter, skb_data);
1314 }
Avinash Patil42a028a2014-09-12 20:08:47 +05301315 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001316
Avinash Patil62159942015-03-13 17:37:52 +05301317 skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
1318 GFP_KERNEL | GFP_DMA);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001319 if (!skb_tmp) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301320 mwifiex_dbg(adapter, ERROR,
1321 "Unable to allocate skb.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001322 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001323 }
1324
Avinash Patile7f767a2013-01-03 21:21:32 -08001325 if (mwifiex_map_pci_memory(adapter, skb_tmp,
1326 MWIFIEX_RX_DATA_BUF_SIZE,
1327 PCI_DMA_FROMDEVICE))
1328 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001329
Aaron Durbindbccc922014-02-07 16:25:50 -08001330 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
Avinash Patile7f767a2013-01-03 21:21:32 -08001331
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301332 mwifiex_dbg(adapter, INFO,
1333 "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
1334 skb_tmp, rd_index);
Avinash Patile7f767a2013-01-03 21:21:32 -08001335 card->rx_buf_list[rd_index] = skb_tmp;
Avinash Patilca8f2112013-02-08 18:18:09 -08001336
1337 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001338 desc2 = card->rxbd_ring[rd_index];
Avinash Patilca8f2112013-02-08 18:18:09 -08001339 desc2->paddr = buf_pa;
1340 desc2->len = skb_tmp->len;
1341 desc2->frag_len = skb_tmp->len;
1342 desc2->offset = 0;
1343 desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
1344 } else {
1345 desc = card->rxbd_ring[rd_index];
1346 desc->paddr = buf_pa;
1347 desc->len = skb_tmp->len;
1348 desc->flags = 0;
1349 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001350
Avinash Patildd04e6a2013-02-08 18:18:06 -08001351 if ((++card->rxbd_rdptr & reg->rx_mask) ==
Amitkumar Karward930fae2011-10-11 17:41:21 -07001352 MWIFIEX_MAX_TXRX_BD) {
1353 card->rxbd_rdptr = ((card->rxbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001354 reg->rx_rollover_ind) ^
1355 reg->rx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001356 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301357 mwifiex_dbg(adapter, DATA,
1358 "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
1359 card->rxbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001360
Avinash Patilca8f2112013-02-08 18:18:09 -08001361 tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001362 /* Write the RX ring read pointer in to reg->rx_rdptr */
1363 if (mwifiex_write_reg(adapter, reg->rx_rdptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001364 card->rxbd_rdptr | tx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301365 mwifiex_dbg(adapter, DATA,
1366 "RECV DATA: failed to write reg->rx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001367 ret = -1;
1368 goto done;
1369 }
1370
1371 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001372 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301373 mwifiex_dbg(adapter, ERROR,
1374 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001375 ret = -1;
1376 goto done;
1377 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301378 mwifiex_dbg(adapter, DATA,
1379 "info: RECV DATA: Rcvd packet from fw successfully\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001380 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001381 }
1382
1383done:
Amitkumar Karward930fae2011-10-11 17:41:21 -07001384 return ret;
1385}
1386
1387/*
1388 * This function downloads the boot command to device
1389 */
1390static int
1391mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1392{
Avinash Patilfc331462013-01-03 21:21:30 -08001393 dma_addr_t buf_pa;
1394 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001395 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001396
Avinash Patilfc331462013-01-03 21:21:30 -08001397 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301398 mwifiex_dbg(adapter, ERROR,
1399 "Invalid parameter in %s <%p. len %d>\n",
1400 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001401 return -1;
1402 }
1403
Ujjal Roy3a968d72016-02-25 00:49:43 +05301404 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
Avinash Patilfc331462013-01-03 21:21:30 -08001405 return -1;
1406
Aaron Durbindbccc922014-02-07 16:25:50 -08001407 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patilfc331462013-01-03 21:21:30 -08001408
Avinash Patildd04e6a2013-02-08 18:18:06 -08001409 /* Write the lower 32bits of the physical address to low command
1410 * address scratch register
1411 */
1412 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301413 mwifiex_dbg(adapter, ERROR,
1414 "%s: failed to write download command to boot code.\n",
1415 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001416 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001417 return -1;
1418 }
1419
Avinash Patildd04e6a2013-02-08 18:18:06 -08001420 /* Write the upper 32bits of the physical address to high command
1421 * address scratch register
1422 */
1423 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001424 (u32)((u64)buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301425 mwifiex_dbg(adapter, ERROR,
1426 "%s: failed to write download command to boot code.\n",
1427 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001428 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001429 return -1;
1430 }
1431
Avinash Patildd04e6a2013-02-08 18:18:06 -08001432 /* Write the command length to cmd_size scratch register */
1433 if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301434 mwifiex_dbg(adapter, ERROR,
1435 "%s: failed to write command len to cmd_size scratch reg\n",
1436 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001437 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001438 return -1;
1439 }
1440
1441 /* Ring the door bell */
1442 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1443 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301444 mwifiex_dbg(adapter, ERROR,
1445 "%s: failed to assert door-bell intr\n", __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001446 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001447 return -1;
1448 }
1449
1450 return 0;
1451}
1452
Avinash Patilc6d1d872013-01-03 21:21:29 -08001453/* This function init rx port in firmware which in turn enables to receive data
1454 * from device before transmitting any packet.
1455 */
1456static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
1457{
1458 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001459 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001460 int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patilc6d1d872013-01-03 21:21:29 -08001461
Avinash Patildd04e6a2013-02-08 18:18:06 -08001462 /* Write the RX ring read pointer in to reg->rx_rdptr */
Avinash Patilca8f2112013-02-08 18:18:09 -08001463 if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
1464 tx_wrap)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301465 mwifiex_dbg(adapter, ERROR,
1466 "RECV DATA: failed to write reg->rx_rdptr\n");
Avinash Patilc6d1d872013-01-03 21:21:29 -08001467 return -1;
1468 }
1469 return 0;
1470}
1471
1472/* This function downloads commands to the device
Amitkumar Karward930fae2011-10-11 17:41:21 -07001473 */
1474static int
1475mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1476{
1477 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001478 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001479 int ret = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001480 dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
1481 u8 *payload = (u8 *)skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001482
1483 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301484 mwifiex_dbg(adapter, ERROR,
1485 "Invalid parameter in %s <%p, %#x>\n",
1486 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001487 return -1;
1488 }
1489
1490 /* Make sure a command response buffer is available */
1491 if (!card->cmdrsp_buf) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301492 mwifiex_dbg(adapter, ERROR,
1493 "No response buffer available, send command failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001494 return -EBUSY;
1495 }
1496
Avinash Patilfc331462013-01-03 21:21:30 -08001497 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1498 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001499
1500 adapter->cmd_sent = true;
Avinash Patilfc331462013-01-03 21:21:30 -08001501
1502 *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
1503 *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
1504
1505 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
1506 return -1;
1507
1508 card->cmd_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001509
1510 /* To send a command, the driver will:
1511 1. Write the 64bit physical address of the data buffer to
Avinash Patildd04e6a2013-02-08 18:18:06 -08001512 cmd response address low + cmd response address high
Amitkumar Karward930fae2011-10-11 17:41:21 -07001513 2. Ring the door bell (i.e. set the door bell interrupt)
1514
1515 In response to door bell interrupt, the firmware will perform
1516 the DMA of the command packet (first header to obtain the total
1517 length and then rest of the command).
1518 */
1519
1520 if (card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001521 cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001522 /* Write the lower 32bits of the cmdrsp buffer physical
1523 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001524 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
Avinash Patilfc331462013-01-03 21:21:30 -08001525 (u32)cmdrsp_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301526 mwifiex_dbg(adapter, ERROR,
1527 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001528 ret = -1;
1529 goto done;
1530 }
1531 /* Write the upper 32bits of the cmdrsp buffer physical
1532 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001533 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001534 (u32)((u64)cmdrsp_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301535 mwifiex_dbg(adapter, ERROR,
1536 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001537 ret = -1;
1538 goto done;
1539 }
1540 }
1541
Aaron Durbindbccc922014-02-07 16:25:50 -08001542 cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001543 /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
1544 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
1545 (u32)cmd_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301546 mwifiex_dbg(adapter, ERROR,
1547 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001548 ret = -1;
1549 goto done;
1550 }
Avinash Patildd04e6a2013-02-08 18:18:06 -08001551 /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
1552 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001553 (u32)((u64)cmd_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301554 mwifiex_dbg(adapter, ERROR,
1555 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001556 ret = -1;
1557 goto done;
1558 }
1559
Avinash Patildd04e6a2013-02-08 18:18:06 -08001560 /* Write the command length to reg->cmd_size */
1561 if (mwifiex_write_reg(adapter, reg->cmd_size,
1562 card->cmd_buf->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301563 mwifiex_dbg(adapter, ERROR,
1564 "Failed to write cmd len to reg->cmd_size\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001565 ret = -1;
1566 goto done;
1567 }
1568
1569 /* Ring the door bell */
1570 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1571 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301572 mwifiex_dbg(adapter, ERROR,
1573 "Failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001574 ret = -1;
1575 goto done;
1576 }
1577
1578done:
1579 if (ret)
1580 adapter->cmd_sent = false;
1581
1582 return 0;
1583}
1584
1585/*
1586 * This function handles command complete interrupt
1587 */
1588static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
1589{
1590 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001591 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001592 struct sk_buff *skb = card->cmdrsp_buf;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001593 int count = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001594 u16 rx_len;
1595 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001596
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301597 mwifiex_dbg(adapter, CMD,
1598 "info: Rx CMD Response\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001599
Aaron Durbindbccc922014-02-07 16:25:50 -08001600 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001601
Aaron Durbin189b3292014-02-07 16:25:51 -08001602 /* Unmap the command as a response has been received. */
1603 if (card->cmd_buf) {
1604 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1605 PCI_DMA_TODEVICE);
1606 card->cmd_buf = NULL;
1607 }
1608
Avinash Patilfc331462013-01-03 21:21:30 -08001609 pkt_len = *((__le16 *)skb->data);
1610 rx_len = le16_to_cpu(pkt_len);
1611 skb_trim(skb, rx_len);
1612 skb_pull(skb, INTF_HEADER_LEN);
1613
Amitkumar Karward930fae2011-10-11 17:41:21 -07001614 if (!adapter->curr_cmd) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001615 if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001616 mwifiex_process_sleep_confirm_resp(adapter, skb->data,
1617 skb->len);
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001618 mwifiex_pcie_enable_host_int(adapter);
1619 if (mwifiex_write_reg(adapter,
1620 PCIE_CPU_INT_EVENT,
1621 CPU_INTR_SLEEP_CFM_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301622 mwifiex_dbg(adapter, ERROR,
1623 "Write register failed\n");
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001624 return -1;
1625 }
Avinash Patilc4bc9802014-03-18 22:19:17 -07001626 mwifiex_delay_for_sleep_cookie(adapter,
1627 MWIFIEX_MAX_DELAY_COUNT);
Avinash Patil52301a82013-02-12 14:38:32 -08001628 while (reg->sleep_cookie && (count++ < 10) &&
1629 mwifiex_pcie_ok_to_access_hw(adapter))
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001630 usleep_range(50, 60);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001631 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301632 mwifiex_dbg(adapter, ERROR,
1633 "There is no command but got cmdrsp\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001634 }
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001635 memcpy(adapter->upld_buf, skb->data,
1636 min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
Avinash Patil0f49d642013-03-20 17:56:23 -07001637 skb_push(skb, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001638 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1639 PCI_DMA_FROMDEVICE))
1640 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001641 } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001642 adapter->curr_cmd->resp_skb = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001643 adapter->cmd_resp_received = true;
1644 /* Take the pointer and set it to CMD node and will
1645 return in the response complete callback */
1646 card->cmdrsp_buf = NULL;
1647
1648 /* Clear the cmd-rsp buffer address in scratch registers. This
1649 will prevent firmware from writing to the same response
1650 buffer again. */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001651 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301652 mwifiex_dbg(adapter, ERROR,
1653 "cmd_done: failed to clear cmd_rsp_addr_lo\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001654 return -1;
1655 }
1656 /* Write the upper 32bits of the cmdrsp buffer physical
1657 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001658 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301659 mwifiex_dbg(adapter, ERROR,
1660 "cmd_done: failed to clear cmd_rsp_addr_hi\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001661 return -1;
1662 }
1663 }
1664
1665 return 0;
1666}
1667
1668/*
1669 * Command Response processing complete handler
1670 */
1671static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
1672 struct sk_buff *skb)
1673{
1674 struct pcie_service_card *card = adapter->card;
1675
1676 if (skb) {
1677 card->cmdrsp_buf = skb;
1678 skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001679 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1680 PCI_DMA_FROMDEVICE))
1681 return -1;
1682 }
1683
Amitkumar Karward930fae2011-10-11 17:41:21 -07001684 return 0;
1685}
1686
1687/*
1688 * This function handles firmware event ready interrupt
1689 */
1690static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
1691{
1692 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001693 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001694 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1695 u32 wrptr, event;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001696 struct mwifiex_evt_buf_desc *desc;
Avinash Patilfc331462013-01-03 21:21:30 -08001697
1698 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1699 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001700
1701 if (adapter->event_received) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301702 mwifiex_dbg(adapter, EVENT,
1703 "info: Event being processed,\t"
1704 "do not process this interrupt just yet\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001705 return 0;
1706 }
1707
1708 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301709 mwifiex_dbg(adapter, ERROR,
1710 "info: Invalid read pointer...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001711 return -1;
1712 }
1713
1714 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001715 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301716 mwifiex_dbg(adapter, ERROR,
1717 "EventReady: failed to read reg->evt_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001718 return -1;
1719 }
1720
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301721 mwifiex_dbg(adapter, EVENT,
1722 "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
1723 card->evtbd_rdptr, wrptr);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001724 if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
1725 & MWIFIEX_EVTBD_MASK)) ||
Avinash Patildd04e6a2013-02-08 18:18:06 -08001726 ((wrptr & reg->evt_rollover_ind) ==
1727 (card->evtbd_rdptr & reg->evt_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001728 struct sk_buff *skb_cmd;
1729 __le16 data_len = 0;
1730 u16 evt_len;
1731
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301732 mwifiex_dbg(adapter, INFO,
1733 "info: Read Index: %d\n", rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001734 skb_cmd = card->evt_buf_list[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001735 mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001736
Amitkumar Karward930fae2011-10-11 17:41:21 -07001737 /* Take the pointer and set it to event pointer in adapter
1738 and will return back after event handling callback */
1739 card->evt_buf_list[rdptr] = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001740 desc = card->evtbd_ring[rdptr];
1741 memset(desc, 0, sizeof(*desc));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001742
1743 event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
1744 adapter->event_cause = event;
1745 /* The first 4bytes will be the event transfer header
1746 len is 2 bytes followed by type which is 2 bytes */
1747 memcpy(&data_len, skb_cmd->data, sizeof(__le16));
1748 evt_len = le16_to_cpu(data_len);
Zhaoyang Liu868093a2015-05-12 00:48:19 +05301749 skb_trim(skb_cmd, evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001750 skb_pull(skb_cmd, INTF_HEADER_LEN);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301751 mwifiex_dbg(adapter, EVENT,
1752 "info: Event length: %d\n", evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001753
1754 if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
1755 memcpy(adapter->event_body, skb_cmd->data +
1756 MWIFIEX_EVENT_HEADER_LEN, evt_len -
1757 MWIFIEX_EVENT_HEADER_LEN);
1758
1759 adapter->event_received = true;
1760 adapter->event_skb = skb_cmd;
1761
1762 /* Do not update the event read pointer here, wait till the
1763 buffer is released. This is just to make things simpler,
1764 we need to find a better method of managing these buffers.
1765 */
Avinash Patil2703a662014-09-12 20:08:49 +05301766 } else {
1767 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1768 CPU_INTR_EVENT_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301769 mwifiex_dbg(adapter, ERROR,
1770 "Write register failed\n");
Avinash Patil2703a662014-09-12 20:08:49 +05301771 return -1;
1772 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001773 }
1774
1775 return 0;
1776}
1777
1778/*
1779 * Event processing complete handler
1780 */
1781static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
1782 struct sk_buff *skb)
1783{
1784 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001785 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001786 int ret = 0;
1787 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1788 u32 wrptr;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001789 struct mwifiex_evt_buf_desc *desc;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001790
1791 if (!skb)
1792 return 0;
1793
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001794 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301795 mwifiex_dbg(adapter, ERROR,
1796 "event_complete: Invalid rdptr 0x%x\n",
1797 rdptr);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001798 return -EINVAL;
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001799 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001800
1801 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001802 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301803 mwifiex_dbg(adapter, ERROR,
1804 "event_complete: failed to read reg->evt_wrptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001805 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001806 }
1807
1808 if (!card->evt_buf_list[rdptr]) {
1809 skb_push(skb, INTF_HEADER_LEN);
Amitkumar Karwar2728cec2015-07-22 04:53:45 -07001810 skb_put(skb, MAX_EVENT_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001811 if (mwifiex_map_pci_memory(adapter, skb,
1812 MAX_EVENT_SIZE,
1813 PCI_DMA_FROMDEVICE))
1814 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001815 card->evt_buf_list[rdptr] = skb;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001816 desc = card->evtbd_ring[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001817 desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile05dc3e2013-02-08 18:18:08 -08001818 desc->len = (u16)skb->len;
1819 desc->flags = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001820 skb = NULL;
1821 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301822 mwifiex_dbg(adapter, ERROR,
1823 "info: ERROR: buf still valid at index %d, <%p, %p>\n",
1824 rdptr, card->evt_buf_list[rdptr], skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001825 }
1826
1827 if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
1828 card->evtbd_rdptr = ((card->evtbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001829 reg->evt_rollover_ind) ^
1830 reg->evt_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001831 }
1832
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301833 mwifiex_dbg(adapter, EVENT,
1834 "info: Updated <Rd: 0x%x, Wr: 0x%x>",
1835 card->evtbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001836
Avinash Patildd04e6a2013-02-08 18:18:06 -08001837 /* Write the event ring read pointer in to reg->evt_rdptr */
1838 if (mwifiex_write_reg(adapter, reg->evt_rdptr,
1839 card->evtbd_rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301840 mwifiex_dbg(adapter, ERROR,
1841 "event_complete: failed to read reg->evt_rdptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001842 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001843 }
1844
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301845 mwifiex_dbg(adapter, EVENT,
1846 "info: Check Events Again\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001847 ret = mwifiex_pcie_process_event_ready(adapter);
1848
1849 return ret;
1850}
1851
1852/*
1853 * This function downloads the firmware to the card.
1854 *
1855 * Firmware is downloaded to the card in blocks. Every block download
1856 * is tested for CRC errors, and retried a number of times before
1857 * returning failure.
1858 */
1859static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
1860 struct mwifiex_fw_image *fw)
1861{
1862 int ret;
1863 u8 *firmware = fw->fw_buf;
1864 u32 firmware_len = fw->fw_len;
1865 u32 offset = 0;
1866 struct sk_buff *skb;
1867 u32 txlen, tx_blocks = 0, tries, len;
1868 u32 block_retry_cnt = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001869 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001870 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001871
1872 if (!firmware || !firmware_len) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301873 mwifiex_dbg(adapter, ERROR,
1874 "No firmware image found! Terminating download\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001875 return -1;
1876 }
1877
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301878 mwifiex_dbg(adapter, INFO,
1879 "info: Downloading FW image (%d bytes)\n",
1880 firmware_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001881
1882 if (mwifiex_pcie_disable_host_int(adapter)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301883 mwifiex_dbg(adapter, ERROR,
1884 "%s: Disabling interrupts failed.\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001885 return -1;
1886 }
1887
1888 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
1889 if (!skb) {
1890 ret = -ENOMEM;
1891 goto done;
1892 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001893
1894 /* Perform firmware data transfer */
1895 do {
1896 u32 ireg_intr = 0;
1897
1898 /* More data? */
1899 if (offset >= firmware_len)
1900 break;
1901
1902 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08001903 ret = mwifiex_read_reg(adapter, reg->cmd_size,
Amitkumar Karward930fae2011-10-11 17:41:21 -07001904 &len);
1905 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301906 mwifiex_dbg(adapter, FATAL,
1907 "Failed reading len from boot code\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001908 goto done;
1909 }
1910 if (len)
1911 break;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001912 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001913 }
1914
1915 if (!len) {
1916 break;
1917 } else if (len > MWIFIEX_UPLD_SIZE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301918 mwifiex_dbg(adapter, ERROR,
1919 "FW download failure @ %d, invalid length %d\n",
1920 offset, len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001921 ret = -1;
1922 goto done;
1923 }
1924
1925 txlen = len;
1926
1927 if (len & BIT(0)) {
1928 block_retry_cnt++;
1929 if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301930 mwifiex_dbg(adapter, ERROR,
1931 "FW download failure @ %d, over max\t"
1932 "retry count\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001933 ret = -1;
1934 goto done;
1935 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301936 mwifiex_dbg(adapter, ERROR,
1937 "FW CRC error indicated by the\t"
1938 "helper: len = 0x%04X, txlen = %d\n",
1939 len, txlen);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001940 len &= ~BIT(0);
1941 /* Setting this to 0 to resend from same offset */
1942 txlen = 0;
1943 } else {
1944 block_retry_cnt = 0;
1945 /* Set blocksize to transfer - checking for
1946 last block */
1947 if (firmware_len - offset < txlen)
1948 txlen = firmware_len - offset;
1949
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301950 mwifiex_dbg(adapter, INFO, ".");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001951
Avinash Patildd04e6a2013-02-08 18:18:06 -08001952 tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
1953 card->pcie.blksz_fw_dl;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001954
1955 /* Copy payload to buffer */
1956 memmove(skb->data, &firmware[offset], txlen);
1957 }
1958
1959 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001960 skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001961
1962 /* Send the boot command to device */
1963 if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301964 mwifiex_dbg(adapter, ERROR,
1965 "Failed to send firmware download command\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001966 ret = -1;
1967 goto done;
1968 }
Avinash Patilfc331462013-01-03 21:21:30 -08001969
Amitkumar Karward930fae2011-10-11 17:41:21 -07001970 /* Wait for the command done interrupt */
1971 do {
1972 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
1973 &ireg_intr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301974 mwifiex_dbg(adapter, ERROR,
1975 "%s: Failed to read\t"
1976 "interrupt status during fw dnld.\n",
1977 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001978 mwifiex_unmap_pci_memory(adapter, skb,
1979 PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001980 ret = -1;
1981 goto done;
1982 }
1983 } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
1984 CPU_INTR_DOOR_BELL);
Avinash Patilfc331462013-01-03 21:21:30 -08001985
Aaron Durbindbccc922014-02-07 16:25:50 -08001986 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001987
Amitkumar Karward930fae2011-10-11 17:41:21 -07001988 offset += txlen;
1989 } while (true);
1990
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301991 mwifiex_dbg(adapter, MSG,
1992 "info: FW download over, size %d bytes\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001993
1994 ret = 0;
1995
1996done:
1997 dev_kfree_skb_any(skb);
1998 return ret;
1999}
2000
2001/*
2002 * This function checks the firmware status in card.
Amitkumar Karward930fae2011-10-11 17:41:21 -07002003 */
2004static int
2005mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
2006{
2007 int ret = 0;
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002008 u32 firmware_stat;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002009 struct pcie_service_card *card = adapter->card;
2010 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002011 u32 tries;
2012
2013 /* Mask spurios interrupts */
2014 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002015 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302016 mwifiex_dbg(adapter, ERROR,
2017 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002018 return -1;
2019 }
2020
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302021 mwifiex_dbg(adapter, INFO,
2022 "Setting driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002023 if (mwifiex_write_reg(adapter, reg->drv_rdy,
2024 FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302025 mwifiex_dbg(adapter, ERROR,
2026 "Failed to write driver ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002027 return -1;
2028 }
2029
2030 /* Wait for firmware initialization event */
2031 for (tries = 0; tries < poll_num; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002032 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002033 &firmware_stat))
2034 ret = -1;
2035 else
2036 ret = 0;
2037 if (ret)
2038 continue;
2039 if (firmware_stat == FIRMWARE_READY_PCIE) {
2040 ret = 0;
2041 break;
2042 } else {
Amitkumar Karwara76b20e2013-07-22 19:17:53 -07002043 msleep(100);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002044 ret = -1;
2045 }
2046 }
2047
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002048 return ret;
2049}
2050
2051/* This function checks if WLAN is the winner.
2052 */
2053static int
2054mwifiex_check_winner_status(struct mwifiex_adapter *adapter)
2055{
2056 u32 winner = 0;
2057 int ret = 0;
2058 struct pcie_service_card *card = adapter->card;
2059 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2060
2061 if (mwifiex_read_reg(adapter, reg->fw_status, &winner)) {
2062 ret = -1;
2063 } else if (!winner) {
2064 mwifiex_dbg(adapter, INFO, "PCI-E is the winner\n");
2065 adapter->winner = 1;
2066 } else {
2067 mwifiex_dbg(adapter, ERROR,
2068 "PCI-E is not the winner <%#x,%d>, exit dnld\n",
2069 ret, adapter->winner);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002070 }
2071
2072 return ret;
2073}
2074
2075/*
2076 * This function reads the interrupt status from card.
2077 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002078static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter,
2079 int msg_id)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002080{
2081 u32 pcie_ireg;
2082 unsigned long flags;
Xinming Hu99074fc2016-01-11 02:16:40 -08002083 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002084
2085 if (!mwifiex_pcie_ok_to_access_hw(adapter))
2086 return;
2087
Xinming Hu99074fc2016-01-11 02:16:40 -08002088 if (card->msix_enable && msg_id >= 0) {
2089 pcie_ireg = BIT(msg_id);
2090 } else {
2091 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2092 &pcie_ireg)) {
2093 mwifiex_dbg(adapter, ERROR, "Read register failed\n");
2094 return;
2095 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002096
Xinming Hu99074fc2016-01-11 02:16:40 -08002097 if ((pcie_ireg == 0xFFFFFFFF) || !pcie_ireg)
2098 return;
2099
Amitkumar Karward930fae2011-10-11 17:41:21 -07002100
2101 mwifiex_pcie_disable_host_int(adapter);
2102
2103 /* Clear the pending interrupts */
2104 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
2105 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302106 mwifiex_dbg(adapter, ERROR,
2107 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002108 return;
2109 }
Xinming Hu99074fc2016-01-11 02:16:40 -08002110 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002111
Xinming Hu99074fc2016-01-11 02:16:40 -08002112 if (!adapter->pps_uapsd_mode &&
2113 adapter->ps_state == PS_STATE_SLEEP &&
2114 mwifiex_pcie_ok_to_access_hw(adapter)) {
2115 /* Potentially for PCIe we could get other
2116 * interrupts like shared. Don't change power
2117 * state until cookie is set
2118 */
2119 adapter->ps_state = PS_STATE_AWAKE;
2120 adapter->pm_wakeup_fw_try = false;
2121 del_timer(&adapter->wakeup_timer);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002122 }
Shengzhen Lidc896b12016-01-12 05:43:16 -08002123
2124 spin_lock_irqsave(&adapter->int_lock, flags);
2125 adapter->int_status |= pcie_ireg;
2126 spin_unlock_irqrestore(&adapter->int_lock, flags);
2127 mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002128}
2129
2130/*
2131 * Interrupt handler for PCIe root port
2132 *
2133 * This function reads the interrupt status from firmware and assigns
2134 * the main process in workqueue which will handle the interrupt.
2135 */
2136static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
2137{
Xinming Hu99074fc2016-01-11 02:16:40 -08002138 struct mwifiex_msix_context *ctx = context;
2139 struct pci_dev *pdev = ctx->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002140 struct pcie_service_card *card;
2141 struct mwifiex_adapter *adapter;
2142
2143 if (!pdev) {
Xinming Hu91442432015-12-31 06:24:14 -08002144 pr_err("info: %s: pdev is NULL\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002145 goto exit;
2146 }
2147
Jingoo Hanb2a31202013-09-09 14:26:51 +09002148 card = pci_get_drvdata(pdev);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002149 if (!card || !card->adapter) {
Xinming Hu91442432015-12-31 06:24:14 -08002150 pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
2151 card ? card->adapter : NULL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002152 goto exit;
2153 }
2154 adapter = card->adapter;
2155
2156 if (adapter->surprise_removed)
2157 goto exit;
2158
Xinming Hu99074fc2016-01-11 02:16:40 -08002159 if (card->msix_enable)
2160 mwifiex_interrupt_status(adapter, ctx->msg_id);
2161 else
2162 mwifiex_interrupt_status(adapter, -1);
2163
Shengzhen Lib2713f62015-03-13 17:37:54 +05302164 mwifiex_queue_main_work(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002165
2166exit:
2167 return IRQ_HANDLED;
2168}
2169
2170/*
2171 * This function checks the current interrupt status.
2172 *
2173 * The following interrupts are checked and handled by this function -
2174 * - Data sent
2175 * - Command sent
2176 * - Command received
2177 * - Packets received
2178 * - Events received
2179 *
2180 * In case of Rx packets received, the packets are uploaded from card to
2181 * host and processed accordingly.
2182 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002183static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002184{
2185 int ret;
Avinash Patil659c4782013-01-03 21:21:28 -08002186 u32 pcie_ireg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002187 unsigned long flags;
2188
2189 spin_lock_irqsave(&adapter->int_lock, flags);
2190 /* Clear out unused interrupts */
Avinash Patil659c4782013-01-03 21:21:28 -08002191 pcie_ireg = adapter->int_status;
2192 adapter->int_status = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002193 spin_unlock_irqrestore(&adapter->int_lock, flags);
2194
Avinash Patil659c4782013-01-03 21:21:28 -08002195 while (pcie_ireg & HOST_INTR_MASK) {
2196 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2197 pcie_ireg &= ~HOST_INTR_DNLD_DONE;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302198 mwifiex_dbg(adapter, INTR,
2199 "info: TX DNLD Done\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08002200 ret = mwifiex_pcie_send_data_complete(adapter);
2201 if (ret)
2202 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002203 }
Avinash Patil659c4782013-01-03 21:21:28 -08002204 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2205 pcie_ireg &= ~HOST_INTR_UPLD_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302206 mwifiex_dbg(adapter, INTR,
2207 "info: Rx DATA\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002208 ret = mwifiex_pcie_process_recv_data(adapter);
2209 if (ret)
2210 return ret;
2211 }
Avinash Patil659c4782013-01-03 21:21:28 -08002212 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2213 pcie_ireg &= ~HOST_INTR_EVENT_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302214 mwifiex_dbg(adapter, INTR,
2215 "info: Rx EVENT\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002216 ret = mwifiex_pcie_process_event_ready(adapter);
2217 if (ret)
2218 return ret;
2219 }
2220
Avinash Patil659c4782013-01-03 21:21:28 -08002221 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2222 pcie_ireg &= ~HOST_INTR_CMD_DONE;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002223 if (adapter->cmd_sent) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302224 mwifiex_dbg(adapter, INTR,
2225 "info: CMD sent Interrupt\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002226 adapter->cmd_sent = false;
2227 }
2228 /* Handle command response */
2229 ret = mwifiex_pcie_process_cmd_complete(adapter);
2230 if (ret)
2231 return ret;
2232 }
2233
2234 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2235 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2236 &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302237 mwifiex_dbg(adapter, ERROR,
2238 "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002239 return -1;
2240 }
2241
2242 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2243 if (mwifiex_write_reg(adapter,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002244 PCIE_HOST_INT_STATUS,
2245 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302246 mwifiex_dbg(adapter, ERROR,
2247 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002248 return -1;
2249 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002250 }
2251
2252 }
2253 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302254 mwifiex_dbg(adapter, INTR,
2255 "info: cmd_sent=%d data_sent=%d\n",
2256 adapter->cmd_sent, adapter->data_sent);
Avinash Patilb2fda1f2013-03-22 21:49:05 -07002257 if (adapter->ps_state != PS_STATE_SLEEP)
2258 mwifiex_pcie_enable_host_int(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002259
2260 return 0;
2261}
2262
Xinming Hu99074fc2016-01-11 02:16:40 -08002263static int mwifiex_process_msix_int(struct mwifiex_adapter *adapter)
2264{
2265 int ret;
2266 u32 pcie_ireg;
2267 unsigned long flags;
2268
2269 spin_lock_irqsave(&adapter->int_lock, flags);
2270 /* Clear out unused interrupts */
2271 pcie_ireg = adapter->int_status;
2272 adapter->int_status = 0;
2273 spin_unlock_irqrestore(&adapter->int_lock, flags);
2274
2275 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2276 mwifiex_dbg(adapter, INTR,
2277 "info: TX DNLD Done\n");
2278 ret = mwifiex_pcie_send_data_complete(adapter);
2279 if (ret)
2280 return ret;
2281 }
2282 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2283 mwifiex_dbg(adapter, INTR,
2284 "info: Rx DATA\n");
2285 ret = mwifiex_pcie_process_recv_data(adapter);
2286 if (ret)
2287 return ret;
2288 }
2289 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2290 mwifiex_dbg(adapter, INTR,
2291 "info: Rx EVENT\n");
2292 ret = mwifiex_pcie_process_event_ready(adapter);
2293 if (ret)
2294 return ret;
2295 }
2296
2297 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2298 if (adapter->cmd_sent) {
2299 mwifiex_dbg(adapter, INTR,
2300 "info: CMD sent Interrupt\n");
2301 adapter->cmd_sent = false;
2302 }
2303 /* Handle command response */
2304 ret = mwifiex_pcie_process_cmd_complete(adapter);
2305 if (ret)
2306 return ret;
2307 }
2308
2309 mwifiex_dbg(adapter, INTR,
2310 "info: cmd_sent=%d data_sent=%d\n",
2311 adapter->cmd_sent, adapter->data_sent);
2312
2313 return 0;
2314}
2315
2316static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
2317{
2318 struct pcie_service_card *card = adapter->card;
2319
2320 if (card->msix_enable)
2321 return mwifiex_process_msix_int(adapter);
2322 else
2323 return mwifiex_process_pcie_int(adapter);
2324}
2325
Amitkumar Karward930fae2011-10-11 17:41:21 -07002326/*
2327 * This function downloads data from driver to card.
2328 *
2329 * Both commands and data packets are transferred to the card by this
2330 * function.
2331 *
2332 * This function adds the PCIE specific header to the front of the buffer
2333 * before transferring. The header contains the length of the packet and
2334 * the type. The firmware handles the packets based upon this set type.
2335 */
2336static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
2337 struct sk_buff *skb,
2338 struct mwifiex_tx_param *tx_param)
2339{
Dan Carpenterfa161cb2011-11-07 19:31:45 -08002340 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302341 mwifiex_dbg(adapter, ERROR,
2342 "Passed NULL skb to %s\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002343 return -1;
2344 }
2345
2346 if (type == MWIFIEX_TYPE_DATA)
Avinash Patile7f767a2013-01-03 21:21:32 -08002347 return mwifiex_pcie_send_data(adapter, skb, tx_param);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002348 else if (type == MWIFIEX_TYPE_CMD)
2349 return mwifiex_pcie_send_cmd(adapter, skb);
2350
2351 return 0;
2352}
2353
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002354/* This function read/write firmware */
2355static enum rdwr_status
2356mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
2357{
2358 int ret, tries;
2359 u8 ctrl_data;
Xinming Hu01724042016-02-02 22:05:04 -08002360 u32 fw_status;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002361 struct pcie_service_card *card = adapter->card;
2362 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2363
Xinming Hu01724042016-02-02 22:05:04 -08002364 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status))
2365 return RDWR_STATUS_FAILURE;
2366
Xinming Hu50632092016-02-02 22:05:06 -08002367 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
2368 reg->fw_dump_host_ready);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002369 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302370 mwifiex_dbg(adapter, ERROR,
2371 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002372 return RDWR_STATUS_FAILURE;
2373 }
2374
2375 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2376 mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
2377 if (ctrl_data == FW_DUMP_DONE)
2378 return RDWR_STATUS_SUCCESS;
2379 if (doneflag && ctrl_data == doneflag)
2380 return RDWR_STATUS_DONE;
Xinming Hu50632092016-02-02 22:05:06 -08002381 if (ctrl_data != reg->fw_dump_host_ready) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302382 mwifiex_dbg(adapter, WARN,
2383 "The ctrl reg was changed, re-try again!\n");
Amitkumar Karwar24716872014-09-18 08:04:01 -04002384 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
Xinming Hu50632092016-02-02 22:05:06 -08002385 reg->fw_dump_host_ready);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002386 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302387 mwifiex_dbg(adapter, ERROR,
2388 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002389 return RDWR_STATUS_FAILURE;
2390 }
2391 }
2392 usleep_range(100, 200);
2393 }
2394
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302395 mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002396 return RDWR_STATUS_FAILURE;
2397}
2398
2399/* This function dump firmware memory to file */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002400static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002401{
2402 struct pcie_service_card *card = adapter->card;
2403 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2404 unsigned int reg, reg_start, reg_end;
Xinming Hu11e70822016-02-02 22:05:09 -08002405 u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num;
Xinming Hu56486022016-02-02 22:05:07 -08002406 u8 idx, i, read_reg, doneflag = 0;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002407 enum rdwr_status stat;
2408 u32 memory_size;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002409 int ret;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002410
Avinash Patilb4e8aeb2015-02-11 23:12:26 +05302411 if (!card->pcie.can_dump_fw)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002412 return;
2413
Xinming Hu50632092016-02-02 22:05:06 -08002414 for (idx = 0; idx < adapter->num_mem_types; idx++) {
2415 struct memory_type_mapping *entry =
2416 &adapter->mem_type_mapping_tbl[idx];
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002417
2418 if (entry->mem_ptr) {
2419 vfree(entry->mem_ptr);
2420 entry->mem_ptr = NULL;
2421 }
2422 entry->mem_size = 0;
2423 }
2424
Amitkumar Karwar03f0f7c2016-02-02 22:05:08 -08002425 mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002426
2427 /* Read the number of the memories which will dump */
2428 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2429 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002430 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002431
2432 reg = creg->fw_dump_start;
Xinming Hu11e70822016-02-02 22:05:09 -08002433 mwifiex_read_reg_byte(adapter, reg, &fw_dump_num);
2434
2435 /* W8997 chipset firmware dump will be restore in single region*/
2436 if (fw_dump_num == 0)
2437 dump_num = 1;
2438 else
2439 dump_num = fw_dump_num;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002440
2441 /* Read the length of every memory which will dump */
2442 for (idx = 0; idx < dump_num; idx++) {
Xinming Hu50632092016-02-02 22:05:06 -08002443 struct memory_type_mapping *entry =
2444 &adapter->mem_type_mapping_tbl[idx];
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002445 memory_size = 0;
Xinming Hu11e70822016-02-02 22:05:09 -08002446 if (fw_dump_num != 0) {
2447 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2448 if (stat == RDWR_STATUS_FAILURE)
2449 return;
2450
2451 reg = creg->fw_dump_start;
2452 for (i = 0; i < 4; i++) {
2453 mwifiex_read_reg_byte(adapter, reg, &read_reg);
2454 memory_size |= (read_reg << (i * 8));
Dan Carpenterccf5fa42016-02-09 14:15:36 +03002455 reg++;
Xinming Hu11e70822016-02-02 22:05:09 -08002456 }
2457 } else {
2458 memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002459 }
2460
2461 if (memory_size == 0) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302462 mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002463 ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
Xinming Hu50632092016-02-02 22:05:06 -08002464 creg->fw_dump_read_done);
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002465 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302466 mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002467 return;
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002468 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002469 break;
2470 }
2471
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302472 mwifiex_dbg(adapter, DUMP,
2473 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002474 entry->mem_ptr = vmalloc(memory_size + 1);
2475 entry->mem_size = memory_size;
2476 if (!entry->mem_ptr) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302477 mwifiex_dbg(adapter, ERROR,
2478 "Vmalloc %s failed\n", entry->mem_name);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002479 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002480 }
2481 dbg_ptr = entry->mem_ptr;
2482 end_ptr = dbg_ptr + memory_size;
2483
2484 doneflag = entry->done_flag;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302485 mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
2486 entry->mem_name);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002487
2488 do {
2489 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2490 if (RDWR_STATUS_FAILURE == stat)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002491 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002492
2493 reg_start = creg->fw_dump_start;
2494 reg_end = creg->fw_dump_end;
2495 for (reg = reg_start; reg <= reg_end; reg++) {
2496 mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
Amitkumar Karwar24716872014-09-18 08:04:01 -04002497 if (dbg_ptr < end_ptr) {
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002498 dbg_ptr++;
Xinming Hu56486022016-02-02 22:05:07 -08002499 continue;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002500 }
Xinming Hu56486022016-02-02 22:05:07 -08002501 mwifiex_dbg(adapter, ERROR,
2502 "pre-allocated buf not enough\n");
2503 tmp_ptr =
2504 vzalloc(memory_size + MWIFIEX_SIZE_4K);
2505 if (!tmp_ptr)
2506 return;
2507 memcpy(tmp_ptr, entry->mem_ptr, memory_size);
2508 vfree(entry->mem_ptr);
2509 entry->mem_ptr = tmp_ptr;
2510 tmp_ptr = NULL;
2511 dbg_ptr = entry->mem_ptr + memory_size;
2512 memory_size += MWIFIEX_SIZE_4K;
2513 end_ptr = entry->mem_ptr + memory_size;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002514 }
2515
2516 if (stat != RDWR_STATUS_DONE)
2517 continue;
2518
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302519 mwifiex_dbg(adapter, DUMP,
2520 "%s done: size=0x%tx\n",
2521 entry->mem_name, dbg_ptr - entry->mem_ptr);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002522 break;
2523 } while (true);
2524 }
Amitkumar Karwar03f0f7c2016-02-02 22:05:08 -08002525 mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002526}
2527
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002528static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
2529{
2530 mwifiex_drv_info_dump(adapter);
2531 mwifiex_pcie_fw_dump(adapter);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002532 mwifiex_upload_device_dump(adapter);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002533}
2534
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002535static unsigned long iface_work_flags;
2536static struct mwifiex_adapter *save_adapter;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002537static void mwifiex_pcie_work(struct work_struct *work)
2538{
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002539 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002540 &iface_work_flags))
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002541 mwifiex_pcie_device_dump_work(save_adapter);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002542}
2543
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002544static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002545/* This function dumps FW information */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002546static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002547{
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002548 save_adapter = adapter;
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002549 if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002550 return;
2551
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002552 set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002553
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002554 schedule_work(&pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002555}
2556
Amitkumar Karward930fae2011-10-11 17:41:21 -07002557/*
2558 * This function initializes the PCI-E host memory space, WCB rings, etc.
2559 *
2560 * The following initializations steps are followed -
2561 * - Allocate TXBD ring buffers
2562 * - Allocate RXBD ring buffers
2563 * - Allocate event BD ring buffers
2564 * - Allocate command response ring buffer
2565 * - Allocate sleep cookie buffer
2566 */
2567static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
2568{
2569 struct pcie_service_card *card = adapter->card;
2570 int ret;
2571 struct pci_dev *pdev = card->dev;
Avinash Patil52301a82013-02-12 14:38:32 -08002572 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002573
2574 pci_set_drvdata(pdev, card);
2575
2576 ret = pci_enable_device(pdev);
2577 if (ret)
2578 goto err_enable_dev;
2579
2580 pci_set_master(pdev);
2581
Xinming Hufdb1e282015-12-31 06:24:12 -08002582 pr_notice("try set_consistent_dma_mask(32)\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002583 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
2584 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002585 pr_err("set_dma_mask(32) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002586 goto err_set_dma_mask;
2587 }
2588
2589 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
2590 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002591 pr_err("set_consistent_dma_mask(64) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002592 goto err_set_dma_mask;
2593 }
2594
2595 ret = pci_request_region(pdev, 0, DRV_NAME);
2596 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002597 pr_err("req_reg(0) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002598 goto err_req_region0;
2599 }
2600 card->pci_mmap = pci_iomap(pdev, 0, 0);
2601 if (!card->pci_mmap) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002602 pr_err("iomap(0) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002603 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002604 goto err_iomap0;
2605 }
2606 ret = pci_request_region(pdev, 2, DRV_NAME);
2607 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002608 pr_err("req_reg(2) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002609 goto err_req_region2;
2610 }
2611 card->pci_mmap1 = pci_iomap(pdev, 2, 0);
2612 if (!card->pci_mmap1) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002613 pr_err("iomap(2) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002614 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002615 goto err_iomap2;
2616 }
2617
Xinming Hufdb1e282015-12-31 06:24:12 -08002618 pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
2619 card->pci_mmap, card->pci_mmap1);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002620
2621 card->cmdrsp_buf = NULL;
2622 ret = mwifiex_pcie_create_txbd_ring(adapter);
2623 if (ret)
2624 goto err_cre_txbd;
2625 ret = mwifiex_pcie_create_rxbd_ring(adapter);
2626 if (ret)
2627 goto err_cre_rxbd;
2628 ret = mwifiex_pcie_create_evtbd_ring(adapter);
2629 if (ret)
2630 goto err_cre_evtbd;
2631 ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
2632 if (ret)
2633 goto err_alloc_cmdbuf;
Avinash Patil52301a82013-02-12 14:38:32 -08002634 if (reg->sleep_cookie) {
2635 ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
2636 if (ret)
2637 goto err_alloc_cookie;
2638 } else {
2639 card->sleep_cookie_vbase = NULL;
2640 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002641 return ret;
2642
2643err_alloc_cookie:
2644 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2645err_alloc_cmdbuf:
2646 mwifiex_pcie_delete_evtbd_ring(adapter);
2647err_cre_evtbd:
2648 mwifiex_pcie_delete_rxbd_ring(adapter);
2649err_cre_rxbd:
2650 mwifiex_pcie_delete_txbd_ring(adapter);
2651err_cre_txbd:
2652 pci_iounmap(pdev, card->pci_mmap1);
2653err_iomap2:
2654 pci_release_region(pdev, 2);
2655err_req_region2:
2656 pci_iounmap(pdev, card->pci_mmap);
2657err_iomap0:
2658 pci_release_region(pdev, 0);
2659err_req_region0:
2660err_set_dma_mask:
2661 pci_disable_device(pdev);
2662err_enable_dev:
2663 pci_set_drvdata(pdev, NULL);
2664 return ret;
2665}
2666
2667/*
2668 * This function cleans up the allocated card buffers.
2669 *
2670 * The following are freed by this function -
2671 * - TXBD ring buffers
2672 * - RXBD ring buffers
2673 * - Event BD ring buffers
2674 * - Command response ring buffer
2675 * - Sleep cookie buffer
2676 */
2677static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
2678{
2679 struct pcie_service_card *card = adapter->card;
2680 struct pci_dev *pdev = card->dev;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002681 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002682
Amitkumar Karward930fae2011-10-11 17:41:21 -07002683 if (user_rmmod) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302684 mwifiex_dbg(adapter, INFO,
2685 "Clearing driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002686 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302687 mwifiex_dbg(adapter, ERROR,
2688 "Failed to write driver not-ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002689 }
2690
2691 if (pdev) {
2692 pci_iounmap(pdev, card->pci_mmap);
2693 pci_iounmap(pdev, card->pci_mmap1);
Yogesh Ashok Powar5b0d9b22013-04-23 16:49:48 -07002694 pci_disable_device(pdev);
Yogesh Ashok Powarc380aaf2013-04-23 16:49:47 -07002695 pci_release_region(pdev, 2);
2696 pci_release_region(pdev, 0);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002697 pci_set_drvdata(pdev, NULL);
2698 }
Amitkumar Karwar3c59e322013-11-14 19:10:41 -08002699 kfree(card);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002700}
2701
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002702static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
2703{
Xinming Hu99074fc2016-01-11 02:16:40 -08002704 int ret, i, j;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002705 struct pcie_service_card *card = adapter->card;
2706 struct pci_dev *pdev = card->dev;
2707
Xinming Hu99074fc2016-01-11 02:16:40 -08002708 if (card->pcie.reg->msix_support) {
2709 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2710 card->msix_entries[i].entry = i;
2711 ret = pci_enable_msix_exact(pdev, card->msix_entries,
2712 MWIFIEX_NUM_MSIX_VECTORS);
2713 if (!ret) {
2714 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) {
2715 card->msix_ctx[i].dev = pdev;
2716 card->msix_ctx[i].msg_id = i;
2717
2718 ret = request_irq(card->msix_entries[i].vector,
2719 mwifiex_pcie_interrupt, 0,
2720 "MWIFIEX_PCIE_MSIX",
2721 &card->msix_ctx[i]);
2722 if (ret)
2723 break;
2724 }
2725
2726 if (ret) {
2727 mwifiex_dbg(adapter, INFO, "request_irq fail: %d\n",
2728 ret);
2729 for (j = 0; j < i; j++)
2730 free_irq(card->msix_entries[j].vector,
2731 &card->msix_ctx[i]);
2732 pci_disable_msix(pdev);
2733 } else {
2734 mwifiex_dbg(adapter, MSG, "MSIx enabled!");
2735 card->msix_enable = 1;
2736 return 0;
2737 }
2738 }
2739 }
2740
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002741 if (pci_enable_msi(pdev) != 0)
2742 pci_disable_msi(pdev);
2743 else
2744 card->msi_enable = 1;
2745
2746 mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable);
2747
Xinming Hu99074fc2016-01-11 02:16:40 -08002748 card->share_irq_ctx.dev = pdev;
2749 card->share_irq_ctx.msg_id = -1;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002750 ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
Xinming Hu99074fc2016-01-11 02:16:40 -08002751 "MRVL_PCIE", &card->share_irq_ctx);
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002752 if (ret) {
2753 pr_err("request_irq failed: ret=%d\n", ret);
2754 adapter->card = NULL;
2755 return -1;
2756 }
2757
2758 return 0;
2759}
2760
Amitkumar Karward930fae2011-10-11 17:41:21 -07002761/*
2762 * This function registers the PCIE device.
2763 *
2764 * PCIE IRQ is claimed, block size is set and driver data is initialized.
2765 */
2766static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
2767{
Amitkumar Karward930fae2011-10-11 17:41:21 -07002768 struct pcie_service_card *card = adapter->card;
2769 struct pci_dev *pdev = card->dev;
2770
2771 /* save adapter pointer in card */
2772 card->adapter = adapter;
Xinming Hufdb1e282015-12-31 06:24:12 -08002773 adapter->dev = &pdev->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002774
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002775 if (mwifiex_pcie_request_irq(adapter))
Amitkumar Karward930fae2011-10-11 17:41:21 -07002776 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002777
Amitkumar Karwar828cf222014-02-27 19:35:13 -08002778 adapter->tx_buf_size = card->pcie.tx_buf_size;
Xinming Hu50632092016-02-02 22:05:06 -08002779 adapter->mem_type_mapping_tbl = card->pcie.mem_type_mapping_tbl;
2780 adapter->num_mem_types = card->pcie.num_mem_types;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002781 strcpy(adapter->fw_name, card->pcie.firmware);
Avinash Patil1fe192d2015-01-23 17:09:19 +05302782 adapter->ext_scan = card->pcie.can_ext_scan;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002783
2784 return 0;
2785}
2786
2787/*
2788 * This function unregisters the PCIE device.
2789 *
2790 * The PCIE IRQ is released, the function is disabled and driver
2791 * data is set to null.
2792 */
2793static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
2794{
2795 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -08002796 const struct mwifiex_pcie_card_reg *reg;
Xinming Hu99074fc2016-01-11 02:16:40 -08002797 struct pci_dev *pdev = card->dev;
2798 int i;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002799
2800 if (card) {
Xinming Hu99074fc2016-01-11 02:16:40 -08002801 if (card->msix_enable) {
2802 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2803 synchronize_irq(card->msix_entries[i].vector);
2804
2805 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2806 free_irq(card->msix_entries[i].vector,
2807 &card->msix_ctx[i]);
2808
2809 card->msix_enable = 0;
2810 pci_disable_msix(pdev);
2811 } else {
2812 mwifiex_dbg(adapter, INFO,
2813 "%s(): calling free_irq()\n", __func__);
2814 free_irq(card->dev->irq, &card->share_irq_ctx);
2815
2816 if (card->msi_enable)
2817 pci_disable_msi(pdev);
2818 }
Avinash Patilfc331462013-01-03 21:21:30 -08002819
Avinash Patil52301a82013-02-12 14:38:32 -08002820 reg = card->pcie.reg;
2821 if (reg->sleep_cookie)
2822 mwifiex_pcie_delete_sleep_cookie_buf(adapter);
2823
Avinash Patilfc331462013-01-03 21:21:30 -08002824 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2825 mwifiex_pcie_delete_evtbd_ring(adapter);
2826 mwifiex_pcie_delete_rxbd_ring(adapter);
2827 mwifiex_pcie_delete_txbd_ring(adapter);
2828 card->cmdrsp_buf = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002829 }
2830}
2831
2832static struct mwifiex_if_ops pcie_ops = {
2833 .init_if = mwifiex_pcie_init,
2834 .cleanup_if = mwifiex_pcie_cleanup,
2835 .check_fw_status = mwifiex_check_fw_status,
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002836 .check_winner_status = mwifiex_check_winner_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002837 .prog_fw = mwifiex_prog_fw_w_helper,
2838 .register_dev = mwifiex_register_dev,
2839 .unregister_dev = mwifiex_unregister_dev,
2840 .enable_int = mwifiex_pcie_enable_host_int,
2841 .process_int_status = mwifiex_process_int_status,
2842 .host_to_card = mwifiex_pcie_host_to_card,
2843 .wakeup = mwifiex_pm_wakeup_card,
2844 .wakeup_complete = mwifiex_pm_wakeup_card_complete,
2845
2846 /* PCIE specific */
2847 .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
2848 .event_complete = mwifiex_pcie_event_complete,
2849 .update_mp_end_port = NULL,
2850 .cleanup_mpa_buf = NULL,
Avinash Patilc6d1d872013-01-03 21:21:29 -08002851 .init_fw_port = mwifiex_pcie_init_fw_port,
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08002852 .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002853 .device_dump = mwifiex_pcie_device_dump,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002854};
2855
2856/*
2857 * This function initializes the PCIE driver module.
2858 *
2859 * This initiates the semaphore and registers the device with
2860 * PCIE bus.
2861 */
2862static int mwifiex_pcie_init_module(void)
2863{
2864 int ret;
2865
Avinash Patilca8f2112013-02-08 18:18:09 -08002866 pr_debug("Marvell PCIe Driver\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002867
2868 sema_init(&add_remove_card_sem, 1);
2869
2870 /* Clear the flag in case user removes the card. */
2871 user_rmmod = 0;
2872
2873 ret = pci_register_driver(&mwifiex_pcie);
2874 if (ret)
2875 pr_err("Driver register failed!\n");
2876 else
2877 pr_debug("info: Driver registered successfully!\n");
2878
2879 return ret;
2880}
2881
2882/*
2883 * This function cleans up the PCIE driver.
2884 *
2885 * The following major steps are followed for cleanup -
2886 * - Resume the device if its suspended
2887 * - Disconnect the device if connected
2888 * - Shutdown the firmware
2889 * - Unregister the device from PCIE bus.
2890 */
2891static void mwifiex_pcie_cleanup_module(void)
2892{
2893 if (!down_interruptible(&add_remove_card_sem))
2894 up(&add_remove_card_sem);
2895
2896 /* Set the flag as user is removing this module. */
2897 user_rmmod = 1;
2898
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002899 cancel_work_sync(&pcie_work);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002900 pci_unregister_driver(&mwifiex_pcie);
2901}
2902
2903module_init(mwifiex_pcie_init_module);
2904module_exit(mwifiex_pcie_cleanup_module);
2905
2906MODULE_AUTHOR("Marvell International Ltd.");
2907MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
2908MODULE_VERSION(PCIE_VERSION);
2909MODULE_LICENSE("GPL v2");
Avinash Patilca8f2112013-02-08 18:18:09 -08002910MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
2911MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07002912MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME);