blob: 453ab6ad478466c9a1fdf53cb14b3047ef9d92c2 [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;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800193 card->pcie.reg = data->reg;
194 card->pcie.blksz_fw_dl = data->blksz_fw_dl;
Amitkumar Karwar828cf222014-02-27 19:35:13 -0800195 card->pcie.tx_buf_size = data->tx_buf_size;
Avinash Patilb4e8aeb2015-02-11 23:12:26 +0530196 card->pcie.can_dump_fw = data->can_dump_fw;
Xinming Hu50632092016-02-02 22:05:06 -0800197 card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl;
198 card->pcie.num_mem_types = data->num_mem_types;
Avinash Patil1fe192d2015-01-23 17:09:19 +0530199 card->pcie.can_ext_scan = data->can_ext_scan;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800200 }
201
Amitkumar Karward930fae2011-10-11 17:41:21 -0700202 if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
203 MWIFIEX_PCIE)) {
204 pr_err("%s failed\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700205 return -1;
206 }
207
208 return 0;
209}
210
211/*
212 * This function removes the interface and frees up the card structure.
213 */
214static void mwifiex_pcie_remove(struct pci_dev *pdev)
215{
216 struct pcie_service_card *card;
217 struct mwifiex_adapter *adapter;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700218 struct mwifiex_private *priv;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700219
220 card = pci_get_drvdata(pdev);
221 if (!card)
222 return;
223
224 adapter = card->adapter;
225 if (!adapter || !adapter->priv_num)
226 return;
227
228 if (user_rmmod) {
Shuah Khan3266d732013-07-03 10:47:10 -0600229#ifdef CONFIG_PM_SLEEP
Amitkumar Karward930fae2011-10-11 17:41:21 -0700230 if (adapter->is_suspended)
Shuah Khan3266d732013-07-03 10:47:10 -0600231 mwifiex_pcie_resume(&pdev->dev);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700232#endif
233
Amitkumar Karwar848819f2014-02-27 19:35:17 -0800234 mwifiex_deauthenticate_all(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700235
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700236 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700237
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700238 mwifiex_disable_auto_ds(priv);
239
240 mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700241 }
242
243 mwifiex_remove_card(card->adapter, &add_remove_card_sem);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700244}
245
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700246static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
247{
248 user_rmmod = 1;
249 mwifiex_pcie_remove(pdev);
250
251 return;
252}
253
Benoit Taine9baa3c32014-08-08 15:56:03 +0200254static const struct pci_device_id mwifiex_ids[] = {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700255 {
256 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
257 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700258 .driver_data = (unsigned long)&mwifiex_pcie8766,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700259 },
Avinash Patilca8f2112013-02-08 18:18:09 -0800260 {
261 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
262 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700263 .driver_data = (unsigned long)&mwifiex_pcie8897,
264 },
265 {
266 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
267 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
268 .driver_data = (unsigned long)&mwifiex_pcie8997,
Avinash Patilca8f2112013-02-08 18:18:09 -0800269 },
Shengzhen Lia362e162016-04-05 01:04:36 -0700270 {
271 PCIE_VENDOR_ID_V2_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
272 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
273 .driver_data = (unsigned long)&mwifiex_pcie8997,
274 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700275 {},
276};
277
278MODULE_DEVICE_TABLE(pci, mwifiex_ids);
279
Shuah Khan3266d732013-07-03 10:47:10 -0600280#ifdef CONFIG_PM_SLEEP
281/* Power Management Hooks */
282static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
283 mwifiex_pcie_resume);
284#endif
285
Amitkumar Karward930fae2011-10-11 17:41:21 -0700286/* PCI Device Driver */
287static struct pci_driver __refdata mwifiex_pcie = {
288 .name = "mwifiex_pcie",
289 .id_table = mwifiex_ids,
290 .probe = mwifiex_pcie_probe,
291 .remove = mwifiex_pcie_remove,
Shuah Khan3266d732013-07-03 10:47:10 -0600292#ifdef CONFIG_PM_SLEEP
293 .driver = {
294 .pm = &mwifiex_pcie_pm_ops,
295 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700296#endif
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700297 .shutdown = mwifiex_pcie_shutdown,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700298};
299
300/*
301 * This function writes data into PCIE card register.
302 */
303static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
304{
305 struct pcie_service_card *card = adapter->card;
306
307 iowrite32(data, card->pci_mmap1 + reg);
308
309 return 0;
310}
311
312/*
313 * This function reads data from PCIE card register.
314 */
315static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
316{
317 struct pcie_service_card *card = adapter->card;
318
319 *data = ioread32(card->pci_mmap1 + reg);
Xinming Huaf051482016-02-02 22:05:03 -0800320 if (*data == 0xffffffff)
321 return 0xffffffff;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700322
323 return 0;
324}
325
Amitkumar Karwar92c25382014-06-19 21:38:52 -0700326/* This function reads u8 data from PCIE card register. */
327static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
328 int reg, u8 *data)
329{
330 struct pcie_service_card *card = adapter->card;
331
332 *data = ioread8(card->pci_mmap1 + reg);
333
334 return 0;
335}
336
Amitkumar Karward930fae2011-10-11 17:41:21 -0700337/*
Avinash Patilc0880a22013-03-22 21:49:07 -0700338 * This function adds delay loop to ensure FW is awake before proceeding.
Amitkumar Karward930fae2011-10-11 17:41:21 -0700339 */
Avinash Patilc0880a22013-03-22 21:49:07 -0700340static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700341{
342 int i = 0;
343
Avinash Patilc0880a22013-03-22 21:49:07 -0700344 while (mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700345 i++;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -0700346 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700347 /* 50ms max wait */
Avinash Patil3e7a4ff2013-02-25 16:01:34 -0800348 if (i == 5000)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700349 break;
350 }
351
Avinash Patilc0880a22013-03-22 21:49:07 -0700352 return;
353}
354
Avinash Patilc4bc9802014-03-18 22:19:17 -0700355static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
356 u32 max_delay_loop_cnt)
357{
358 struct pcie_service_card *card = adapter->card;
359 u8 *buffer;
360 u32 sleep_cookie, count;
361
362 for (count = 0; count < max_delay_loop_cnt; count++) {
363 buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
364 sleep_cookie = *(u32 *)buffer;
365
366 if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530367 mwifiex_dbg(adapter, INFO,
368 "sleep cookie found at count %d\n", count);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700369 break;
370 }
371 usleep_range(20, 30);
372 }
373
374 if (count >= max_delay_loop_cnt)
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530375 mwifiex_dbg(adapter, INFO,
376 "max count reached while accessing sleep cookie\n");
Avinash Patilc4bc9802014-03-18 22:19:17 -0700377}
378
Avinash Patilc0880a22013-03-22 21:49:07 -0700379/* This function wakes up the card by reading fw_status register. */
380static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
381{
382 u32 fw_status;
383 struct pcie_service_card *card = adapter->card;
384 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
385
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530386 mwifiex_dbg(adapter, EVENT,
387 "event: Wakeup device...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700388
Avinash Patilc0880a22013-03-22 21:49:07 -0700389 if (reg->sleep_cookie)
390 mwifiex_pcie_dev_wakeup_delay(adapter);
391
392 /* Reading fw_status register will wakeup device */
393 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530394 mwifiex_dbg(adapter, ERROR,
395 "Reading fw_status register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700396 return -1;
397 }
398
Avinash Patilc0880a22013-03-22 21:49:07 -0700399 if (reg->sleep_cookie) {
400 mwifiex_pcie_dev_wakeup_delay(adapter);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530401 mwifiex_dbg(adapter, INFO,
402 "PCIE wakeup: Setting PS_STATE_AWAKE\n");
Avinash Patilc0880a22013-03-22 21:49:07 -0700403 adapter->ps_state = PS_STATE_AWAKE;
404 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700405
406 return 0;
407}
408
409/*
410 * This function is called after the card has woken up.
411 *
412 * The card configuration register is reset.
413 */
414static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
415{
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530416 mwifiex_dbg(adapter, CMD,
417 "cmd: Wakeup device completed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700418
419 return 0;
420}
421
422/*
423 * This function disables the host interrupt.
424 *
425 * The host interrupt mask is read, the disable bit is reset and
426 * written back to the card host interrupt mask register.
427 */
428static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
429{
430 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
431 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
432 0x00000000)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530433 mwifiex_dbg(adapter, ERROR,
434 "Disable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700435 return -1;
436 }
437 }
438
439 return 0;
440}
441
Brian Norrisd41376c2016-06-30 15:21:02 -0700442static void mwifiex_pcie_disable_host_int_noerr(struct mwifiex_adapter *adapter)
443{
444 WARN_ON(mwifiex_pcie_disable_host_int(adapter));
445}
446
Amitkumar Karward930fae2011-10-11 17:41:21 -0700447/*
448 * This function enables the host interrupt.
449 *
450 * The host interrupt enable mask is written to the card
451 * host interrupt mask register.
452 */
453static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
454{
455 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
456 /* Simply write the mask to the register */
457 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
458 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530459 mwifiex_dbg(adapter, ERROR,
460 "Enable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700461 return -1;
462 }
463 }
464
465 return 0;
466}
467
468/*
Avinash Patil07324842013-02-08 18:18:07 -0800469 * This function initializes TX buffer ring descriptors
470 */
471static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
472{
473 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800474 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800475 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800476 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800477 int i;
478
479 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
480 card->tx_buf_list[i] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -0800481 if (reg->pfu_enabled) {
482 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
483 (sizeof(*desc2) * i);
484 desc2 = card->txbd_ring[i];
485 memset(desc2, 0, sizeof(*desc2));
486 } else {
487 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
488 (sizeof(*desc) * i);
489 desc = card->txbd_ring[i];
490 memset(desc, 0, sizeof(*desc));
491 }
Avinash Patil07324842013-02-08 18:18:07 -0800492 }
493
494 return 0;
495}
496
497/* This function initializes RX buffer ring descriptors. Each SKB is allocated
498 * here and after mapping PCI memory, its physical address is assigned to
499 * PCIE Rx buffer descriptor's physical address.
500 */
501static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
502{
503 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800504 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800505 struct sk_buff *skb;
506 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800507 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800508 dma_addr_t buf_pa;
509 int i;
510
511 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
512 /* Allocate skb here so that firmware can DMA data from it */
Avinash Patil62159942015-03-13 17:37:52 +0530513 skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
Mathias Krause5c87a552016-05-21 15:43:31 +0200514 GFP_KERNEL);
Avinash Patil07324842013-02-08 18:18:07 -0800515 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530516 mwifiex_dbg(adapter, ERROR,
517 "Unable to allocate skb for RX ring.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800518 kfree(card->rxbd_ring_vbase);
519 return -ENOMEM;
520 }
521
522 if (mwifiex_map_pci_memory(adapter, skb,
523 MWIFIEX_RX_DATA_BUF_SIZE,
524 PCI_DMA_FROMDEVICE))
525 return -1;
526
Aaron Durbindbccc922014-02-07 16:25:50 -0800527 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800528
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530529 mwifiex_dbg(adapter, INFO,
530 "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
531 skb, skb->len, skb->data, (u32)buf_pa,
532 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800533
534 card->rx_buf_list[i] = skb;
Avinash Patilca8f2112013-02-08 18:18:09 -0800535 if (reg->pfu_enabled) {
536 card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
537 (sizeof(*desc2) * i);
538 desc2 = card->rxbd_ring[i];
539 desc2->paddr = buf_pa;
540 desc2->len = (u16)skb->len;
541 desc2->frag_len = (u16)skb->len;
542 desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
543 desc2->offset = 0;
544 } else {
545 card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
546 (sizeof(*desc) * i));
547 desc = card->rxbd_ring[i];
548 desc->paddr = buf_pa;
549 desc->len = (u16)skb->len;
550 desc->flags = 0;
551 }
Avinash Patil07324842013-02-08 18:18:07 -0800552 }
553
554 return 0;
555}
556
557/* This function initializes event buffer ring descriptors. Each SKB is
558 * allocated here and after mapping PCI memory, its physical address is assigned
559 * to PCIE Rx buffer descriptor's physical address
560 */
561static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
562{
563 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800564 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800565 struct sk_buff *skb;
566 dma_addr_t buf_pa;
567 int i;
568
569 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
570 /* Allocate skb here so that firmware can DMA data from it */
571 skb = dev_alloc_skb(MAX_EVENT_SIZE);
572 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530573 mwifiex_dbg(adapter, ERROR,
574 "Unable to allocate skb for EVENT buf.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800575 kfree(card->evtbd_ring_vbase);
576 return -ENOMEM;
577 }
578 skb_put(skb, MAX_EVENT_SIZE);
579
580 if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
581 PCI_DMA_FROMDEVICE))
582 return -1;
583
Aaron Durbindbccc922014-02-07 16:25:50 -0800584 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800585
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530586 mwifiex_dbg(adapter, EVENT,
587 "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
588 skb, skb->len, skb->data, (u32)buf_pa,
589 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800590
591 card->evt_buf_list[i] = skb;
592 card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
593 (sizeof(*desc) * i));
Avinash Patil07324842013-02-08 18:18:07 -0800594 desc = card->evtbd_ring[i];
595 desc->paddr = buf_pa;
596 desc->len = (u16)skb->len;
597 desc->flags = 0;
598 }
599
600 return 0;
601}
602
603/* This function cleans up TX buffer rings. If any of the buffer list has valid
604 * SKB address, associated SKB is freed.
605 */
606static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
607{
608 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800609 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800610 struct sk_buff *skb;
611 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800612 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800613 int i;
614
615 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800616 if (reg->pfu_enabled) {
617 desc2 = card->txbd_ring[i];
618 if (card->tx_buf_list[i]) {
619 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800620 mwifiex_unmap_pci_memory(adapter, skb,
621 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800622 dev_kfree_skb_any(skb);
623 }
624 memset(desc2, 0, sizeof(*desc2));
625 } else {
626 desc = card->txbd_ring[i];
627 if (card->tx_buf_list[i]) {
628 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800629 mwifiex_unmap_pci_memory(adapter, skb,
630 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800631 dev_kfree_skb_any(skb);
632 }
633 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800634 }
635 card->tx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800636 }
637
638 return;
639}
640
641/* This function cleans up RX buffer rings. If any of the buffer list has valid
642 * SKB address, associated SKB is freed.
643 */
644static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
645{
646 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800647 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800648 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800649 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800650 struct sk_buff *skb;
651 int i;
652
653 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800654 if (reg->pfu_enabled) {
655 desc2 = card->rxbd_ring[i];
656 if (card->rx_buf_list[i]) {
657 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800658 mwifiex_unmap_pci_memory(adapter, skb,
659 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800660 dev_kfree_skb_any(skb);
661 }
662 memset(desc2, 0, sizeof(*desc2));
663 } else {
664 desc = card->rxbd_ring[i];
665 if (card->rx_buf_list[i]) {
666 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800667 mwifiex_unmap_pci_memory(adapter, skb,
668 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800669 dev_kfree_skb_any(skb);
670 }
671 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800672 }
Avinash Patilca8f2112013-02-08 18:18:09 -0800673 card->rx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800674 }
675
676 return;
677}
678
679/* This function cleans up event buffer rings. If any of the buffer list has
680 * valid SKB address, associated SKB is freed.
681 */
682static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
683{
684 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800685 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800686 struct sk_buff *skb;
687 int i;
688
689 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
690 desc = card->evtbd_ring[i];
691 if (card->evt_buf_list[i]) {
692 skb = card->evt_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800693 mwifiex_unmap_pci_memory(adapter, skb,
694 PCI_DMA_FROMDEVICE);
Avinash Patil07324842013-02-08 18:18:07 -0800695 dev_kfree_skb_any(skb);
696 }
697 card->evt_buf_list[i] = NULL;
698 memset(desc, 0, sizeof(*desc));
699 }
700
701 return;
702}
703
704/* This function creates buffer descriptor ring for TX
Amitkumar Karward930fae2011-10-11 17:41:21 -0700705 */
706static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
707{
708 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800709 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700710
711 /*
712 * driver maintaines the write pointer and firmware maintaines the read
713 * pointer. The write pointer starts at 0 (zero) while the read pointer
714 * starts at zero with rollover bit set
715 */
716 card->txbd_wrptr = 0;
Avinash Patilca8f2112013-02-08 18:18:09 -0800717
718 if (reg->pfu_enabled)
719 card->txbd_rdptr = 0;
720 else
721 card->txbd_rdptr |= reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700722
723 /* allocate shared memory for the BD ring and divide the same in to
724 several descriptors */
Avinash Patilca8f2112013-02-08 18:18:09 -0800725 if (reg->pfu_enabled)
726 card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
727 MWIFIEX_MAX_TXRX_BD;
728 else
729 card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
730 MWIFIEX_MAX_TXRX_BD;
731
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530732 mwifiex_dbg(adapter, INFO,
733 "info: txbd_ring: Allocating %d bytes\n",
734 card->txbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800735 card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
736 card->txbd_ring_size,
737 &card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700738 if (!card->txbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530739 mwifiex_dbg(adapter, ERROR,
740 "allocate consistent memory (%d bytes) failed!\n",
741 card->txbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800742 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700743 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530744 mwifiex_dbg(adapter, DATA,
745 "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
746 card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
747 (u32)((u64)card->txbd_ring_pbase >> 32),
748 card->txbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700749
Avinash Patil07324842013-02-08 18:18:07 -0800750 return mwifiex_init_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700751}
752
753static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
754{
755 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800756 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700757
Avinash Patil07324842013-02-08 18:18:07 -0800758 mwifiex_cleanup_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700759
Avinash Patilfc331462013-01-03 21:21:30 -0800760 if (card->txbd_ring_vbase)
761 pci_free_consistent(card->dev, card->txbd_ring_size,
762 card->txbd_ring_vbase,
763 card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700764 card->txbd_ring_size = 0;
765 card->txbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800766 card->txbd_rdptr = 0 | reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700767 card->txbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800768 card->txbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700769
770 return 0;
771}
772
773/*
774 * This function creates buffer descriptor ring for RX
775 */
776static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
777{
778 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800779 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700780
781 /*
782 * driver maintaines the read pointer and firmware maintaines the write
783 * pointer. The write pointer starts at 0 (zero) while the read pointer
784 * starts at zero with rollover bit set
785 */
786 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800787 card->rxbd_rdptr = reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700788
Avinash Patilca8f2112013-02-08 18:18:09 -0800789 if (reg->pfu_enabled)
790 card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
791 MWIFIEX_MAX_TXRX_BD;
792 else
793 card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
794 MWIFIEX_MAX_TXRX_BD;
795
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530796 mwifiex_dbg(adapter, INFO,
797 "info: rxbd_ring: Allocating %d bytes\n",
798 card->rxbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800799 card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
800 card->rxbd_ring_size,
801 &card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700802 if (!card->rxbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530803 mwifiex_dbg(adapter, ERROR,
804 "allocate consistent memory (%d bytes) failed!\n",
805 card->rxbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800806 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700807 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700808
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530809 mwifiex_dbg(adapter, DATA,
810 "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
811 card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
812 (u32)((u64)card->rxbd_ring_pbase >> 32),
813 card->rxbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700814
Avinash Patil07324842013-02-08 18:18:07 -0800815 return mwifiex_init_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700816}
817
818/*
819 * This function deletes Buffer descriptor ring for RX
820 */
821static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
822{
823 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800824 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700825
Avinash Patil07324842013-02-08 18:18:07 -0800826 mwifiex_cleanup_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700827
Avinash Patilfc331462013-01-03 21:21:30 -0800828 if (card->rxbd_ring_vbase)
829 pci_free_consistent(card->dev, card->rxbd_ring_size,
830 card->rxbd_ring_vbase,
831 card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700832 card->rxbd_ring_size = 0;
833 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800834 card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700835 card->rxbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800836 card->rxbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700837
838 return 0;
839}
840
841/*
842 * This function creates buffer descriptor ring for Events
843 */
844static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
845{
846 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800847 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700848
849 /*
850 * driver maintaines the read pointer and firmware maintaines the write
851 * pointer. The write pointer starts at 0 (zero) while the read pointer
852 * starts at zero with rollover bit set
853 */
854 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800855 card->evtbd_rdptr = reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700856
Avinash Patile05dc3e2013-02-08 18:18:08 -0800857 card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
Avinash Patilca8f2112013-02-08 18:18:09 -0800858 MWIFIEX_MAX_EVT_BD;
859
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530860 mwifiex_dbg(adapter, INFO,
861 "info: evtbd_ring: Allocating %d bytes\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700862 card->evtbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800863 card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
864 card->evtbd_ring_size,
865 &card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700866 if (!card->evtbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530867 mwifiex_dbg(adapter, ERROR,
868 "allocate consistent memory (%d bytes) failed!\n",
869 card->evtbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800870 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700871 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700872
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530873 mwifiex_dbg(adapter, EVENT,
874 "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
875 card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
876 (u32)((u64)card->evtbd_ring_pbase >> 32),
877 card->evtbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700878
Avinash Patil07324842013-02-08 18:18:07 -0800879 return mwifiex_pcie_init_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700880}
881
882/*
883 * This function deletes Buffer descriptor ring for Events
884 */
885static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
886{
887 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800888 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700889
Avinash Patil07324842013-02-08 18:18:07 -0800890 mwifiex_cleanup_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700891
Avinash Patilfc331462013-01-03 21:21:30 -0800892 if (card->evtbd_ring_vbase)
893 pci_free_consistent(card->dev, card->evtbd_ring_size,
894 card->evtbd_ring_vbase,
895 card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700896 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800897 card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700898 card->evtbd_ring_size = 0;
899 card->evtbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800900 card->evtbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700901
902 return 0;
903}
904
905/*
906 * This function allocates a buffer for CMDRSP
907 */
908static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
909{
910 struct pcie_service_card *card = adapter->card;
911 struct sk_buff *skb;
912
913 /* Allocate memory for receiving command response data */
914 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
915 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530916 mwifiex_dbg(adapter, ERROR,
917 "Unable to allocate skb for command response data.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700918 return -ENOMEM;
919 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700920 skb_put(skb, MWIFIEX_UPLD_SIZE);
Avinash Patilfc331462013-01-03 21:21:30 -0800921 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
922 PCI_DMA_FROMDEVICE))
923 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700924
Avinash Patilfc331462013-01-03 21:21:30 -0800925 card->cmdrsp_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700926
927 return 0;
928}
929
930/*
931 * This function deletes a buffer for CMDRSP
932 */
933static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
934{
935 struct pcie_service_card *card;
936
937 if (!adapter)
938 return 0;
939
940 card = adapter->card;
941
Avinash Patilfc331462013-01-03 21:21:30 -0800942 if (card && card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800943 mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
944 PCI_DMA_FROMDEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700945 dev_kfree_skb_any(card->cmdrsp_buf);
Avinash Patilfc331462013-01-03 21:21:30 -0800946 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700947
Avinash Patilfc331462013-01-03 21:21:30 -0800948 if (card && card->cmd_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800949 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
950 PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -0800951 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700952 return 0;
953}
954
955/*
956 * This function allocates a buffer for sleep cookie
957 */
958static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
959{
Amitkumar Karward930fae2011-10-11 17:41:21 -0700960 struct pcie_service_card *card = adapter->card;
961
Avinash Patilfc331462013-01-03 21:21:30 -0800962 card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
963 &card->sleep_cookie_pbase);
964 if (!card->sleep_cookie_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530965 mwifiex_dbg(adapter, ERROR,
966 "pci_alloc_consistent failed!\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700967 return -ENOMEM;
968 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700969 /* Init val of Sleep Cookie */
Avinash Patilfc331462013-01-03 21:21:30 -0800970 *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700971
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530972 mwifiex_dbg(adapter, INFO,
973 "alloc_scook: sleep cookie=0x%x\n",
974 *((u32 *)card->sleep_cookie_vbase));
Amitkumar Karward930fae2011-10-11 17:41:21 -0700975
976 return 0;
977}
978
979/*
980 * This function deletes buffer for sleep cookie
981 */
982static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
983{
984 struct pcie_service_card *card;
985
986 if (!adapter)
987 return 0;
988
989 card = adapter->card;
990
Avinash Patilfc331462013-01-03 21:21:30 -0800991 if (card && card->sleep_cookie_vbase) {
992 pci_free_consistent(card->dev, sizeof(u32),
993 card->sleep_cookie_vbase,
994 card->sleep_cookie_pbase);
995 card->sleep_cookie_vbase = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700996 }
997
998 return 0;
999}
1000
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001001/* This function flushes the TX buffer descriptor ring
1002 * This function defined as handler is also called while cleaning TXRX
1003 * during disconnect/ bss stop.
1004 */
1005static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
1006{
1007 struct pcie_service_card *card = adapter->card;
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001008
Avinash Patil48f4d912013-02-20 21:12:58 -08001009 if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001010 card->txbd_flush = 1;
1011 /* write pointer already set at last send
1012 * send dnld-rdy intr again, wait for completion.
1013 */
1014 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1015 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301016 mwifiex_dbg(adapter, ERROR,
1017 "failed to assert dnld-rdy interrupt.\n");
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001018 return -1;
1019 }
1020 }
1021 return 0;
1022}
1023
Amitkumar Karward930fae2011-10-11 17:41:21 -07001024/*
Avinash Patile7f767a2013-01-03 21:21:32 -08001025 * This function unmaps and frees downloaded data buffer
Amitkumar Karward930fae2011-10-11 17:41:21 -07001026 */
Avinash Patile7f767a2013-01-03 21:21:32 -08001027static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001028{
Avinash Patile7f767a2013-01-03 21:21:32 -08001029 struct sk_buff *skb;
Avinash Patilca8f2112013-02-08 18:18:09 -08001030 u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001031 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001032 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001033 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001034 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001035
1036 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1037 mwifiex_pm_wakeup_card(adapter);
1038
1039 /* Read the TX ring read pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001040 if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301041 mwifiex_dbg(adapter, ERROR,
1042 "SEND COMP: failed to read reg->tx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001043 return -1;
1044 }
1045
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301046 mwifiex_dbg(adapter, DATA,
1047 "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
1048 card->txbd_rdptr, rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001049
Avinash Patilca8f2112013-02-08 18:18:09 -08001050 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001051 /* free from previous txbd_rdptr to current txbd_rdptr */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001052 while (((card->txbd_rdptr & reg->tx_mask) !=
1053 (rdptr & reg->tx_mask)) ||
1054 ((card->txbd_rdptr & reg->tx_rollover_ind) !=
1055 (rdptr & reg->tx_rollover_ind))) {
Avinash Patilca8f2112013-02-08 18:18:09 -08001056 wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
1057 reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001058
1059 skb = card->tx_buf_list[wrdoneidx];
Aaron Durbindbccc922014-02-07 16:25:50 -08001060
Avinash Patile7f767a2013-01-03 21:21:32 -08001061 if (skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301062 mwifiex_dbg(adapter, DATA,
1063 "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
1064 skb, wrdoneidx);
Aaron Durbindbccc922014-02-07 16:25:50 -08001065 mwifiex_unmap_pci_memory(adapter, skb,
1066 PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001067
1068 unmap_count++;
1069
1070 if (card->txbd_flush)
1071 mwifiex_write_data_complete(adapter, skb, 0,
1072 -1);
1073 else
1074 mwifiex_write_data_complete(adapter, skb, 0, 0);
1075 }
1076
1077 card->tx_buf_list[wrdoneidx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001078
1079 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001080 desc2 = card->txbd_ring[wrdoneidx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001081 memset(desc2, 0, sizeof(*desc2));
1082 } else {
1083 desc = card->txbd_ring[wrdoneidx];
1084 memset(desc, 0, sizeof(*desc));
1085 }
1086 switch (card->dev->device) {
1087 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1088 card->txbd_rdptr++;
1089 break;
1090 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001091 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001092 card->txbd_rdptr += reg->ring_tx_start_ptr;
1093 break;
1094 }
1095
Avinash Patile7f767a2013-01-03 21:21:32 -08001096
Avinash Patildd04e6a2013-02-08 18:18:06 -08001097 if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
Avinash Patile7f767a2013-01-03 21:21:32 -08001098 card->txbd_rdptr = ((card->txbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001099 reg->tx_rollover_ind) ^
1100 reg->tx_rollover_ind);
Avinash Patile7f767a2013-01-03 21:21:32 -08001101 }
1102
1103 if (unmap_count)
1104 adapter->data_sent = false;
1105
1106 if (card->txbd_flush) {
Avinash Patil3d482032013-02-15 21:37:54 -08001107 if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
Avinash Patile7f767a2013-01-03 21:21:32 -08001108 card->txbd_flush = 0;
1109 else
1110 mwifiex_clean_pcie_ring_buf(adapter);
1111 }
1112
1113 return 0;
1114}
1115
1116/* This function sends data buffer to device. First 4 bytes of payload
1117 * are filled with payload length and payload type. Then this payload
1118 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
1119 * Download ready interrupt to FW is deffered if Tx ring is not full and
1120 * additional payload can be accomodated.
Avinash Patil8d767dc2014-05-13 19:50:13 -07001121 * Caller must ensure tx_param parameter to this function is not NULL.
Avinash Patile7f767a2013-01-03 21:21:32 -08001122 */
1123static int
1124mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
1125 struct mwifiex_tx_param *tx_param)
1126{
1127 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001128 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001129 u32 wrindx, num_tx_buffs, rx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001130 int ret;
1131 dma_addr_t buf_pa;
Bing Zhao99310782013-03-04 16:27:55 -08001132 struct mwifiex_pcie_buf_desc *desc = NULL;
1133 struct mwifiex_pfu_buf_desc *desc2 = NULL;
Avinash Patile7f767a2013-01-03 21:21:32 -08001134 __le16 *tmp;
1135
1136 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301137 mwifiex_dbg(adapter, ERROR,
1138 "%s(): invalid parameter <%p, %#x>\n",
1139 __func__, skb->data, skb->len);
Avinash Patile7f767a2013-01-03 21:21:32 -08001140 return -1;
1141 }
1142
1143 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1144 mwifiex_pm_wakeup_card(adapter);
1145
Avinash Patilca8f2112013-02-08 18:18:09 -08001146 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301147 mwifiex_dbg(adapter, DATA,
1148 "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
Avinash Patile7f767a2013-01-03 21:21:32 -08001149 card->txbd_rdptr, card->txbd_wrptr);
1150 if (mwifiex_pcie_txbd_not_full(card)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001151 u8 *payload;
1152
1153 adapter->data_sent = true;
Avinash Patile7f767a2013-01-03 21:21:32 -08001154 payload = skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001155 tmp = (__le16 *)&payload[0];
1156 *tmp = cpu_to_le16((u16)skb->len);
1157 tmp = (__le16 *)&payload[2];
1158 *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
Avinash Patile7f767a2013-01-03 21:21:32 -08001159
Aaron Durbindbccc922014-02-07 16:25:50 -08001160 if (mwifiex_map_pci_memory(adapter, skb, skb->len,
Avinash Patile7f767a2013-01-03 21:21:32 -08001161 PCI_DMA_TODEVICE))
1162 return -1;
1163
Avinash Patilca8f2112013-02-08 18:18:09 -08001164 wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
Aaron Durbindbccc922014-02-07 16:25:50 -08001165 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile7f767a2013-01-03 21:21:32 -08001166 card->tx_buf_list[wrindx] = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001167
Avinash Patilca8f2112013-02-08 18:18:09 -08001168 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001169 desc2 = card->txbd_ring[wrindx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001170 desc2->paddr = buf_pa;
1171 desc2->len = (u16)skb->len;
1172 desc2->frag_len = (u16)skb->len;
1173 desc2->offset = 0;
1174 desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1175 MWIFIEX_BD_FLAG_LAST_DESC;
1176 } else {
1177 desc = card->txbd_ring[wrindx];
1178 desc->paddr = buf_pa;
1179 desc->len = (u16)skb->len;
1180 desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1181 MWIFIEX_BD_FLAG_LAST_DESC;
1182 }
1183
1184 switch (card->dev->device) {
1185 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1186 card->txbd_wrptr++;
1187 break;
1188 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001189 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001190 card->txbd_wrptr += reg->ring_tx_start_ptr;
1191 break;
1192 }
1193
1194 if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001195 card->txbd_wrptr = ((card->txbd_wrptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001196 reg->tx_rollover_ind) ^
1197 reg->tx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001198
Avinash Patilca8f2112013-02-08 18:18:09 -08001199 rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001200 /* Write the TX ring write pointer in to reg->tx_wrptr */
1201 if (mwifiex_write_reg(adapter, reg->tx_wrptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001202 card->txbd_wrptr | rx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301203 mwifiex_dbg(adapter, ERROR,
1204 "SEND DATA: failed to write reg->tx_wrptr\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001205 ret = -1;
1206 goto done_unmap;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001207 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001208 if ((mwifiex_pcie_txbd_not_full(card)) &&
1209 tx_param->next_pkt_len) {
1210 /* have more packets and TxBD still can hold more */
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301211 mwifiex_dbg(adapter, DATA,
1212 "SEND DATA: delay dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001213 adapter->data_sent = false;
1214 } else {
1215 /* Send the TX ready interrupt */
1216 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1217 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301218 mwifiex_dbg(adapter, ERROR,
1219 "SEND DATA: failed to assert dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001220 ret = -1;
1221 goto done_unmap;
1222 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001223 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301224 mwifiex_dbg(adapter, DATA,
1225 "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
1226 "%#x> and sent packet to firmware successfully\n",
1227 card->txbd_rdptr, card->txbd_wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001228 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301229 mwifiex_dbg(adapter, DATA,
1230 "info: TX Ring full, can't send packets to fw\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001231 adapter->data_sent = true;
1232 /* Send the TX ready interrupt */
1233 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1234 CPU_INTR_DNLD_RDY))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301235 mwifiex_dbg(adapter, ERROR,
1236 "SEND DATA: failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001237 return -EBUSY;
1238 }
1239
Avinash Patile7f767a2013-01-03 21:21:32 -08001240 return -EINPROGRESS;
1241done_unmap:
Aaron Durbindbccc922014-02-07 16:25:50 -08001242 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001243 card->tx_buf_list[wrindx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001244 if (reg->pfu_enabled)
1245 memset(desc2, 0, sizeof(*desc2));
1246 else
1247 memset(desc, 0, sizeof(*desc));
1248
Avinash Patile7f767a2013-01-03 21:21:32 -08001249 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001250}
1251
1252/*
1253 * This function handles received buffer ring and
1254 * dispatches packets to upper
1255 */
1256static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
1257{
1258 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001259 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001260 u32 wrptr, rd_index, tx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001261 dma_addr_t buf_pa;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001262 int ret = 0;
1263 struct sk_buff *skb_tmp = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001264 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001265 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001266
Avinash Patile7f767a2013-01-03 21:21:32 -08001267 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1268 mwifiex_pm_wakeup_card(adapter);
1269
Amitkumar Karward930fae2011-10-11 17:41:21 -07001270 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001271 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301272 mwifiex_dbg(adapter, ERROR,
1273 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001274 ret = -1;
1275 goto done;
1276 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001277 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001278
Avinash Patildd04e6a2013-02-08 18:18:06 -08001279 while (((wrptr & reg->rx_mask) !=
1280 (card->rxbd_rdptr & reg->rx_mask)) ||
1281 ((wrptr & reg->rx_rollover_ind) ==
1282 (card->rxbd_rdptr & reg->rx_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001283 struct sk_buff *skb_data;
1284 u16 rx_len;
Avinash Patile7f767a2013-01-03 21:21:32 -08001285 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001286
Avinash Patildd04e6a2013-02-08 18:18:06 -08001287 rd_index = card->rxbd_rdptr & reg->rx_mask;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001288 skb_data = card->rx_buf_list[rd_index];
1289
Amitkumar Karwarbb8e6a12014-02-18 15:41:55 -08001290 /* If skb allocation was failed earlier for Rx packet,
1291 * rx_buf_list[rd_index] would have been left with a NULL.
1292 */
1293 if (!skb_data)
1294 return -ENOMEM;
1295
Aaron Durbindbccc922014-02-07 16:25:50 -08001296 mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001297 card->rx_buf_list[rd_index] = NULL;
1298
Amitkumar Karward930fae2011-10-11 17:41:21 -07001299 /* Get data length from interface header -
Avinash Patile7f767a2013-01-03 21:21:32 -08001300 * first 2 bytes for len, next 2 bytes is for type
1301 */
1302 pkt_len = *((__le16 *)skb_data->data);
1303 rx_len = le16_to_cpu(pkt_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301304 if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
1305 rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301306 mwifiex_dbg(adapter, ERROR,
1307 "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
1308 rx_len, card->rxbd_rdptr, wrptr);
Avinash Patil42a028a2014-09-12 20:08:47 +05301309 dev_kfree_skb_any(skb_data);
1310 } else {
1311 skb_put(skb_data, rx_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301312 mwifiex_dbg(adapter, DATA,
1313 "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
1314 card->rxbd_rdptr, wrptr, rx_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301315 skb_pull(skb_data, INTF_HEADER_LEN);
Avinash Patil6e251172014-09-12 20:08:59 +05301316 if (adapter->rx_work_enabled) {
Avinash Patil6e251172014-09-12 20:08:59 +05301317 skb_queue_tail(&adapter->rx_data_q, skb_data);
Avinash Patil6e251172014-09-12 20:08:59 +05301318 adapter->data_received = true;
1319 atomic_inc(&adapter->rx_pending);
1320 } else {
1321 mwifiex_handle_rx_packet(adapter, skb_data);
1322 }
Avinash Patil42a028a2014-09-12 20:08:47 +05301323 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001324
Avinash Patil62159942015-03-13 17:37:52 +05301325 skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
Mathias Krause5c87a552016-05-21 15:43:31 +02001326 GFP_KERNEL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001327 if (!skb_tmp) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301328 mwifiex_dbg(adapter, ERROR,
1329 "Unable to allocate skb.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001330 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001331 }
1332
Avinash Patile7f767a2013-01-03 21:21:32 -08001333 if (mwifiex_map_pci_memory(adapter, skb_tmp,
1334 MWIFIEX_RX_DATA_BUF_SIZE,
1335 PCI_DMA_FROMDEVICE))
1336 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001337
Aaron Durbindbccc922014-02-07 16:25:50 -08001338 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
Avinash Patile7f767a2013-01-03 21:21:32 -08001339
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301340 mwifiex_dbg(adapter, INFO,
1341 "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
1342 skb_tmp, rd_index);
Avinash Patile7f767a2013-01-03 21:21:32 -08001343 card->rx_buf_list[rd_index] = skb_tmp;
Avinash Patilca8f2112013-02-08 18:18:09 -08001344
1345 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001346 desc2 = card->rxbd_ring[rd_index];
Avinash Patilca8f2112013-02-08 18:18:09 -08001347 desc2->paddr = buf_pa;
1348 desc2->len = skb_tmp->len;
1349 desc2->frag_len = skb_tmp->len;
1350 desc2->offset = 0;
1351 desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
1352 } else {
1353 desc = card->rxbd_ring[rd_index];
1354 desc->paddr = buf_pa;
1355 desc->len = skb_tmp->len;
1356 desc->flags = 0;
1357 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001358
Avinash Patildd04e6a2013-02-08 18:18:06 -08001359 if ((++card->rxbd_rdptr & reg->rx_mask) ==
Amitkumar Karward930fae2011-10-11 17:41:21 -07001360 MWIFIEX_MAX_TXRX_BD) {
1361 card->rxbd_rdptr = ((card->rxbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001362 reg->rx_rollover_ind) ^
1363 reg->rx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001364 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301365 mwifiex_dbg(adapter, DATA,
1366 "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
1367 card->rxbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001368
Avinash Patilca8f2112013-02-08 18:18:09 -08001369 tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001370 /* Write the RX ring read pointer in to reg->rx_rdptr */
1371 if (mwifiex_write_reg(adapter, reg->rx_rdptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001372 card->rxbd_rdptr | tx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301373 mwifiex_dbg(adapter, DATA,
1374 "RECV DATA: failed to write reg->rx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001375 ret = -1;
1376 goto done;
1377 }
1378
1379 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001380 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301381 mwifiex_dbg(adapter, ERROR,
1382 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001383 ret = -1;
1384 goto done;
1385 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301386 mwifiex_dbg(adapter, DATA,
1387 "info: RECV DATA: Rcvd packet from fw successfully\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001388 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001389 }
1390
1391done:
Amitkumar Karward930fae2011-10-11 17:41:21 -07001392 return ret;
1393}
1394
1395/*
1396 * This function downloads the boot command to device
1397 */
1398static int
1399mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1400{
Avinash Patilfc331462013-01-03 21:21:30 -08001401 dma_addr_t buf_pa;
1402 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001403 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001404
Avinash Patilfc331462013-01-03 21:21:30 -08001405 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301406 mwifiex_dbg(adapter, ERROR,
1407 "Invalid parameter in %s <%p. len %d>\n",
1408 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001409 return -1;
1410 }
1411
Ujjal Roy3a968d72016-02-25 00:49:43 +05301412 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
Avinash Patilfc331462013-01-03 21:21:30 -08001413 return -1;
1414
Aaron Durbindbccc922014-02-07 16:25:50 -08001415 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patilfc331462013-01-03 21:21:30 -08001416
Avinash Patildd04e6a2013-02-08 18:18:06 -08001417 /* Write the lower 32bits of the physical address to low command
1418 * address scratch register
1419 */
1420 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301421 mwifiex_dbg(adapter, ERROR,
1422 "%s: failed to write download command to boot code.\n",
1423 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001424 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001425 return -1;
1426 }
1427
Avinash Patildd04e6a2013-02-08 18:18:06 -08001428 /* Write the upper 32bits of the physical address to high command
1429 * address scratch register
1430 */
1431 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001432 (u32)((u64)buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301433 mwifiex_dbg(adapter, ERROR,
1434 "%s: failed to write download command to boot code.\n",
1435 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001436 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001437 return -1;
1438 }
1439
Avinash Patildd04e6a2013-02-08 18:18:06 -08001440 /* Write the command length to cmd_size scratch register */
1441 if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301442 mwifiex_dbg(adapter, ERROR,
1443 "%s: failed to write command len to cmd_size scratch reg\n",
1444 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001445 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001446 return -1;
1447 }
1448
1449 /* Ring the door bell */
1450 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1451 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301452 mwifiex_dbg(adapter, ERROR,
1453 "%s: failed to assert door-bell intr\n", __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001454 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001455 return -1;
1456 }
1457
1458 return 0;
1459}
1460
Avinash Patilc6d1d872013-01-03 21:21:29 -08001461/* This function init rx port in firmware which in turn enables to receive data
1462 * from device before transmitting any packet.
1463 */
1464static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
1465{
1466 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001467 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001468 int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patilc6d1d872013-01-03 21:21:29 -08001469
Avinash Patildd04e6a2013-02-08 18:18:06 -08001470 /* Write the RX ring read pointer in to reg->rx_rdptr */
Avinash Patilca8f2112013-02-08 18:18:09 -08001471 if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
1472 tx_wrap)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301473 mwifiex_dbg(adapter, ERROR,
1474 "RECV DATA: failed to write reg->rx_rdptr\n");
Avinash Patilc6d1d872013-01-03 21:21:29 -08001475 return -1;
1476 }
1477 return 0;
1478}
1479
1480/* This function downloads commands to the device
Amitkumar Karward930fae2011-10-11 17:41:21 -07001481 */
1482static int
1483mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1484{
1485 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001486 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001487 int ret = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001488 dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
1489 u8 *payload = (u8 *)skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001490
1491 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301492 mwifiex_dbg(adapter, ERROR,
1493 "Invalid parameter in %s <%p, %#x>\n",
1494 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001495 return -1;
1496 }
1497
1498 /* Make sure a command response buffer is available */
1499 if (!card->cmdrsp_buf) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301500 mwifiex_dbg(adapter, ERROR,
1501 "No response buffer available, send command failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001502 return -EBUSY;
1503 }
1504
Avinash Patilfc331462013-01-03 21:21:30 -08001505 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1506 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001507
1508 adapter->cmd_sent = true;
Avinash Patilfc331462013-01-03 21:21:30 -08001509
1510 *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
1511 *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
1512
1513 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
1514 return -1;
1515
1516 card->cmd_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001517
1518 /* To send a command, the driver will:
1519 1. Write the 64bit physical address of the data buffer to
Avinash Patildd04e6a2013-02-08 18:18:06 -08001520 cmd response address low + cmd response address high
Amitkumar Karward930fae2011-10-11 17:41:21 -07001521 2. Ring the door bell (i.e. set the door bell interrupt)
1522
1523 In response to door bell interrupt, the firmware will perform
1524 the DMA of the command packet (first header to obtain the total
1525 length and then rest of the command).
1526 */
1527
1528 if (card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001529 cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001530 /* Write the lower 32bits of the cmdrsp buffer physical
1531 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001532 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
Avinash Patilfc331462013-01-03 21:21:30 -08001533 (u32)cmdrsp_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301534 mwifiex_dbg(adapter, ERROR,
1535 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001536 ret = -1;
1537 goto done;
1538 }
1539 /* Write the upper 32bits of the cmdrsp buffer physical
1540 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001541 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001542 (u32)((u64)cmdrsp_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301543 mwifiex_dbg(adapter, ERROR,
1544 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001545 ret = -1;
1546 goto done;
1547 }
1548 }
1549
Aaron Durbindbccc922014-02-07 16:25:50 -08001550 cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001551 /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
1552 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
1553 (u32)cmd_buf_pa)) {
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 }
Avinash Patildd04e6a2013-02-08 18:18:06 -08001559 /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
1560 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001561 (u32)((u64)cmd_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301562 mwifiex_dbg(adapter, ERROR,
1563 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001564 ret = -1;
1565 goto done;
1566 }
1567
Avinash Patildd04e6a2013-02-08 18:18:06 -08001568 /* Write the command length to reg->cmd_size */
1569 if (mwifiex_write_reg(adapter, reg->cmd_size,
1570 card->cmd_buf->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301571 mwifiex_dbg(adapter, ERROR,
1572 "Failed to write cmd len to reg->cmd_size\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001573 ret = -1;
1574 goto done;
1575 }
1576
1577 /* Ring the door bell */
1578 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1579 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301580 mwifiex_dbg(adapter, ERROR,
1581 "Failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001582 ret = -1;
1583 goto done;
1584 }
1585
1586done:
1587 if (ret)
1588 adapter->cmd_sent = false;
1589
1590 return 0;
1591}
1592
1593/*
1594 * This function handles command complete interrupt
1595 */
1596static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
1597{
1598 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001599 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001600 struct sk_buff *skb = card->cmdrsp_buf;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001601 int count = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001602 u16 rx_len;
1603 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001604
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301605 mwifiex_dbg(adapter, CMD,
1606 "info: Rx CMD Response\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001607
Aaron Durbindbccc922014-02-07 16:25:50 -08001608 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001609
Aaron Durbin189b3292014-02-07 16:25:51 -08001610 /* Unmap the command as a response has been received. */
1611 if (card->cmd_buf) {
1612 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1613 PCI_DMA_TODEVICE);
1614 card->cmd_buf = NULL;
1615 }
1616
Avinash Patilfc331462013-01-03 21:21:30 -08001617 pkt_len = *((__le16 *)skb->data);
1618 rx_len = le16_to_cpu(pkt_len);
Amitkumar Karwar2fd40d22016-07-15 19:07:05 +05301619 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001620 skb_trim(skb, rx_len);
1621 skb_pull(skb, INTF_HEADER_LEN);
1622
Amitkumar Karward930fae2011-10-11 17:41:21 -07001623 if (!adapter->curr_cmd) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001624 if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001625 mwifiex_process_sleep_confirm_resp(adapter, skb->data,
1626 skb->len);
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001627 mwifiex_pcie_enable_host_int(adapter);
1628 if (mwifiex_write_reg(adapter,
1629 PCIE_CPU_INT_EVENT,
1630 CPU_INTR_SLEEP_CFM_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301631 mwifiex_dbg(adapter, ERROR,
1632 "Write register failed\n");
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001633 return -1;
1634 }
Avinash Patilc4bc9802014-03-18 22:19:17 -07001635 mwifiex_delay_for_sleep_cookie(adapter,
1636 MWIFIEX_MAX_DELAY_COUNT);
Avinash Patil52301a82013-02-12 14:38:32 -08001637 while (reg->sleep_cookie && (count++ < 10) &&
1638 mwifiex_pcie_ok_to_access_hw(adapter))
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001639 usleep_range(50, 60);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001640 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301641 mwifiex_dbg(adapter, ERROR,
1642 "There is no command but got cmdrsp\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001643 }
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001644 memcpy(adapter->upld_buf, skb->data,
1645 min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
Avinash Patil0f49d642013-03-20 17:56:23 -07001646 skb_push(skb, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001647 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1648 PCI_DMA_FROMDEVICE))
1649 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001650 } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001651 adapter->curr_cmd->resp_skb = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001652 adapter->cmd_resp_received = true;
1653 /* Take the pointer and set it to CMD node and will
1654 return in the response complete callback */
1655 card->cmdrsp_buf = NULL;
1656
1657 /* Clear the cmd-rsp buffer address in scratch registers. This
1658 will prevent firmware from writing to the same response
1659 buffer again. */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001660 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301661 mwifiex_dbg(adapter, ERROR,
1662 "cmd_done: failed to clear cmd_rsp_addr_lo\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001663 return -1;
1664 }
1665 /* Write the upper 32bits of the cmdrsp buffer physical
1666 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001667 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301668 mwifiex_dbg(adapter, ERROR,
1669 "cmd_done: failed to clear cmd_rsp_addr_hi\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001670 return -1;
1671 }
1672 }
1673
1674 return 0;
1675}
1676
1677/*
1678 * Command Response processing complete handler
1679 */
1680static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
1681 struct sk_buff *skb)
1682{
1683 struct pcie_service_card *card = adapter->card;
1684
1685 if (skb) {
1686 card->cmdrsp_buf = skb;
1687 skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001688 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1689 PCI_DMA_FROMDEVICE))
1690 return -1;
1691 }
1692
Amitkumar Karward930fae2011-10-11 17:41:21 -07001693 return 0;
1694}
1695
1696/*
1697 * This function handles firmware event ready interrupt
1698 */
1699static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
1700{
1701 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001702 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001703 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1704 u32 wrptr, event;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001705 struct mwifiex_evt_buf_desc *desc;
Avinash Patilfc331462013-01-03 21:21:30 -08001706
1707 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1708 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001709
1710 if (adapter->event_received) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301711 mwifiex_dbg(adapter, EVENT,
1712 "info: Event being processed,\t"
1713 "do not process this interrupt just yet\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001714 return 0;
1715 }
1716
1717 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301718 mwifiex_dbg(adapter, ERROR,
1719 "info: Invalid read pointer...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001720 return -1;
1721 }
1722
1723 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001724 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301725 mwifiex_dbg(adapter, ERROR,
1726 "EventReady: failed to read reg->evt_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001727 return -1;
1728 }
1729
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301730 mwifiex_dbg(adapter, EVENT,
1731 "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
1732 card->evtbd_rdptr, wrptr);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001733 if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
1734 & MWIFIEX_EVTBD_MASK)) ||
Avinash Patildd04e6a2013-02-08 18:18:06 -08001735 ((wrptr & reg->evt_rollover_ind) ==
1736 (card->evtbd_rdptr & reg->evt_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001737 struct sk_buff *skb_cmd;
1738 __le16 data_len = 0;
1739 u16 evt_len;
1740
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301741 mwifiex_dbg(adapter, INFO,
1742 "info: Read Index: %d\n", rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001743 skb_cmd = card->evt_buf_list[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001744 mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001745
Amitkumar Karward930fae2011-10-11 17:41:21 -07001746 /* Take the pointer and set it to event pointer in adapter
1747 and will return back after event handling callback */
1748 card->evt_buf_list[rdptr] = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001749 desc = card->evtbd_ring[rdptr];
1750 memset(desc, 0, sizeof(*desc));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001751
1752 event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
1753 adapter->event_cause = event;
1754 /* The first 4bytes will be the event transfer header
1755 len is 2 bytes followed by type which is 2 bytes */
1756 memcpy(&data_len, skb_cmd->data, sizeof(__le16));
1757 evt_len = le16_to_cpu(data_len);
Zhaoyang Liu868093a2015-05-12 00:48:19 +05301758 skb_trim(skb_cmd, evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001759 skb_pull(skb_cmd, INTF_HEADER_LEN);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301760 mwifiex_dbg(adapter, EVENT,
1761 "info: Event length: %d\n", evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001762
1763 if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
1764 memcpy(adapter->event_body, skb_cmd->data +
1765 MWIFIEX_EVENT_HEADER_LEN, evt_len -
1766 MWIFIEX_EVENT_HEADER_LEN);
1767
1768 adapter->event_received = true;
1769 adapter->event_skb = skb_cmd;
1770
1771 /* Do not update the event read pointer here, wait till the
1772 buffer is released. This is just to make things simpler,
1773 we need to find a better method of managing these buffers.
1774 */
Avinash Patil2703a662014-09-12 20:08:49 +05301775 } else {
1776 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1777 CPU_INTR_EVENT_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301778 mwifiex_dbg(adapter, ERROR,
1779 "Write register failed\n");
Avinash Patil2703a662014-09-12 20:08:49 +05301780 return -1;
1781 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001782 }
1783
1784 return 0;
1785}
1786
1787/*
1788 * Event processing complete handler
1789 */
1790static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
1791 struct sk_buff *skb)
1792{
1793 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001794 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001795 int ret = 0;
1796 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1797 u32 wrptr;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001798 struct mwifiex_evt_buf_desc *desc;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001799
1800 if (!skb)
1801 return 0;
1802
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001803 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301804 mwifiex_dbg(adapter, ERROR,
1805 "event_complete: Invalid rdptr 0x%x\n",
1806 rdptr);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001807 return -EINVAL;
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001808 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001809
1810 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001811 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301812 mwifiex_dbg(adapter, ERROR,
1813 "event_complete: failed to read reg->evt_wrptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001814 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001815 }
1816
1817 if (!card->evt_buf_list[rdptr]) {
1818 skb_push(skb, INTF_HEADER_LEN);
Amitkumar Karwar2728cec2015-07-22 04:53:45 -07001819 skb_put(skb, MAX_EVENT_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001820 if (mwifiex_map_pci_memory(adapter, skb,
1821 MAX_EVENT_SIZE,
1822 PCI_DMA_FROMDEVICE))
1823 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001824 card->evt_buf_list[rdptr] = skb;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001825 desc = card->evtbd_ring[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001826 desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile05dc3e2013-02-08 18:18:08 -08001827 desc->len = (u16)skb->len;
1828 desc->flags = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001829 skb = NULL;
1830 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301831 mwifiex_dbg(adapter, ERROR,
1832 "info: ERROR: buf still valid at index %d, <%p, %p>\n",
1833 rdptr, card->evt_buf_list[rdptr], skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001834 }
1835
1836 if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
1837 card->evtbd_rdptr = ((card->evtbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001838 reg->evt_rollover_ind) ^
1839 reg->evt_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001840 }
1841
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301842 mwifiex_dbg(adapter, EVENT,
1843 "info: Updated <Rd: 0x%x, Wr: 0x%x>",
1844 card->evtbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001845
Avinash Patildd04e6a2013-02-08 18:18:06 -08001846 /* Write the event ring read pointer in to reg->evt_rdptr */
1847 if (mwifiex_write_reg(adapter, reg->evt_rdptr,
1848 card->evtbd_rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301849 mwifiex_dbg(adapter, ERROR,
1850 "event_complete: failed to read reg->evt_rdptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001851 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001852 }
1853
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301854 mwifiex_dbg(adapter, EVENT,
1855 "info: Check Events Again\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001856 ret = mwifiex_pcie_process_event_ready(adapter);
1857
1858 return ret;
1859}
1860
1861/*
1862 * This function downloads the firmware to the card.
1863 *
1864 * Firmware is downloaded to the card in blocks. Every block download
1865 * is tested for CRC errors, and retried a number of times before
1866 * returning failure.
1867 */
1868static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
1869 struct mwifiex_fw_image *fw)
1870{
1871 int ret;
1872 u8 *firmware = fw->fw_buf;
1873 u32 firmware_len = fw->fw_len;
1874 u32 offset = 0;
1875 struct sk_buff *skb;
1876 u32 txlen, tx_blocks = 0, tries, len;
1877 u32 block_retry_cnt = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001878 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001879 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001880
1881 if (!firmware || !firmware_len) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301882 mwifiex_dbg(adapter, ERROR,
1883 "No firmware image found! Terminating download\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001884 return -1;
1885 }
1886
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301887 mwifiex_dbg(adapter, INFO,
1888 "info: Downloading FW image (%d bytes)\n",
1889 firmware_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001890
1891 if (mwifiex_pcie_disable_host_int(adapter)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301892 mwifiex_dbg(adapter, ERROR,
1893 "%s: Disabling interrupts failed.\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001894 return -1;
1895 }
1896
1897 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
1898 if (!skb) {
1899 ret = -ENOMEM;
1900 goto done;
1901 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001902
1903 /* Perform firmware data transfer */
1904 do {
1905 u32 ireg_intr = 0;
1906
1907 /* More data? */
1908 if (offset >= firmware_len)
1909 break;
1910
1911 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08001912 ret = mwifiex_read_reg(adapter, reg->cmd_size,
Amitkumar Karward930fae2011-10-11 17:41:21 -07001913 &len);
1914 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301915 mwifiex_dbg(adapter, FATAL,
1916 "Failed reading len from boot code\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001917 goto done;
1918 }
1919 if (len)
1920 break;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001921 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001922 }
1923
1924 if (!len) {
1925 break;
1926 } else if (len > MWIFIEX_UPLD_SIZE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301927 mwifiex_dbg(adapter, ERROR,
1928 "FW download failure @ %d, invalid length %d\n",
1929 offset, len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001930 ret = -1;
1931 goto done;
1932 }
1933
1934 txlen = len;
1935
1936 if (len & BIT(0)) {
1937 block_retry_cnt++;
1938 if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301939 mwifiex_dbg(adapter, ERROR,
1940 "FW download failure @ %d, over max\t"
1941 "retry count\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001942 ret = -1;
1943 goto done;
1944 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301945 mwifiex_dbg(adapter, ERROR,
1946 "FW CRC error indicated by the\t"
1947 "helper: len = 0x%04X, txlen = %d\n",
1948 len, txlen);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001949 len &= ~BIT(0);
1950 /* Setting this to 0 to resend from same offset */
1951 txlen = 0;
1952 } else {
1953 block_retry_cnt = 0;
1954 /* Set blocksize to transfer - checking for
1955 last block */
1956 if (firmware_len - offset < txlen)
1957 txlen = firmware_len - offset;
1958
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301959 mwifiex_dbg(adapter, INFO, ".");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001960
Avinash Patildd04e6a2013-02-08 18:18:06 -08001961 tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
1962 card->pcie.blksz_fw_dl;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001963
1964 /* Copy payload to buffer */
1965 memmove(skb->data, &firmware[offset], txlen);
1966 }
1967
1968 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001969 skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001970
1971 /* Send the boot command to device */
1972 if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301973 mwifiex_dbg(adapter, ERROR,
1974 "Failed to send firmware download command\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001975 ret = -1;
1976 goto done;
1977 }
Avinash Patilfc331462013-01-03 21:21:30 -08001978
Amitkumar Karward930fae2011-10-11 17:41:21 -07001979 /* Wait for the command done interrupt */
1980 do {
1981 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
1982 &ireg_intr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301983 mwifiex_dbg(adapter, ERROR,
1984 "%s: Failed to read\t"
1985 "interrupt status during fw dnld.\n",
1986 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001987 mwifiex_unmap_pci_memory(adapter, skb,
1988 PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001989 ret = -1;
1990 goto done;
1991 }
1992 } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
1993 CPU_INTR_DOOR_BELL);
Avinash Patilfc331462013-01-03 21:21:30 -08001994
Aaron Durbindbccc922014-02-07 16:25:50 -08001995 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001996
Amitkumar Karward930fae2011-10-11 17:41:21 -07001997 offset += txlen;
1998 } while (true);
1999
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302000 mwifiex_dbg(adapter, MSG,
2001 "info: FW download over, size %d bytes\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002002
2003 ret = 0;
2004
2005done:
2006 dev_kfree_skb_any(skb);
2007 return ret;
2008}
2009
2010/*
2011 * This function checks the firmware status in card.
Amitkumar Karward930fae2011-10-11 17:41:21 -07002012 */
2013static int
2014mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
2015{
2016 int ret = 0;
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002017 u32 firmware_stat;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002018 struct pcie_service_card *card = adapter->card;
2019 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002020 u32 tries;
2021
2022 /* Mask spurios interrupts */
2023 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002024 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302025 mwifiex_dbg(adapter, ERROR,
2026 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002027 return -1;
2028 }
2029
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302030 mwifiex_dbg(adapter, INFO,
2031 "Setting driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002032 if (mwifiex_write_reg(adapter, reg->drv_rdy,
2033 FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302034 mwifiex_dbg(adapter, ERROR,
2035 "Failed to write driver ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002036 return -1;
2037 }
2038
2039 /* Wait for firmware initialization event */
2040 for (tries = 0; tries < poll_num; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002041 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002042 &firmware_stat))
2043 ret = -1;
2044 else
2045 ret = 0;
2046 if (ret)
2047 continue;
2048 if (firmware_stat == FIRMWARE_READY_PCIE) {
2049 ret = 0;
2050 break;
2051 } else {
Amitkumar Karwara76b20e2013-07-22 19:17:53 -07002052 msleep(100);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002053 ret = -1;
2054 }
2055 }
2056
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002057 return ret;
2058}
2059
2060/* This function checks if WLAN is the winner.
2061 */
2062static int
2063mwifiex_check_winner_status(struct mwifiex_adapter *adapter)
2064{
2065 u32 winner = 0;
2066 int ret = 0;
2067 struct pcie_service_card *card = adapter->card;
2068 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2069
2070 if (mwifiex_read_reg(adapter, reg->fw_status, &winner)) {
2071 ret = -1;
2072 } else if (!winner) {
2073 mwifiex_dbg(adapter, INFO, "PCI-E is the winner\n");
2074 adapter->winner = 1;
2075 } else {
2076 mwifiex_dbg(adapter, ERROR,
2077 "PCI-E is not the winner <%#x,%d>, exit dnld\n",
2078 ret, adapter->winner);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002079 }
2080
2081 return ret;
2082}
2083
2084/*
2085 * This function reads the interrupt status from card.
2086 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002087static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter,
2088 int msg_id)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002089{
2090 u32 pcie_ireg;
2091 unsigned long flags;
Xinming Hu99074fc2016-01-11 02:16:40 -08002092 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002093
Shengzhen Li5781fc22016-07-01 18:26:52 +05302094 if (card->msi_enable) {
2095 spin_lock_irqsave(&adapter->int_lock, flags);
2096 adapter->int_status = 1;
2097 spin_unlock_irqrestore(&adapter->int_lock, flags);
2098 return;
2099 }
2100
Amitkumar Karward930fae2011-10-11 17:41:21 -07002101 if (!mwifiex_pcie_ok_to_access_hw(adapter))
2102 return;
2103
Xinming Hu99074fc2016-01-11 02:16:40 -08002104 if (card->msix_enable && msg_id >= 0) {
2105 pcie_ireg = BIT(msg_id);
2106 } else {
2107 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2108 &pcie_ireg)) {
2109 mwifiex_dbg(adapter, ERROR, "Read register failed\n");
2110 return;
2111 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002112
Xinming Hu99074fc2016-01-11 02:16:40 -08002113 if ((pcie_ireg == 0xFFFFFFFF) || !pcie_ireg)
2114 return;
2115
Amitkumar Karward930fae2011-10-11 17:41:21 -07002116
2117 mwifiex_pcie_disable_host_int(adapter);
2118
2119 /* Clear the pending interrupts */
2120 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
2121 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302122 mwifiex_dbg(adapter, ERROR,
2123 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002124 return;
2125 }
Xinming Hu99074fc2016-01-11 02:16:40 -08002126 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002127
Xinming Hu99074fc2016-01-11 02:16:40 -08002128 if (!adapter->pps_uapsd_mode &&
2129 adapter->ps_state == PS_STATE_SLEEP &&
2130 mwifiex_pcie_ok_to_access_hw(adapter)) {
2131 /* Potentially for PCIe we could get other
2132 * interrupts like shared. Don't change power
2133 * state until cookie is set
2134 */
2135 adapter->ps_state = PS_STATE_AWAKE;
2136 adapter->pm_wakeup_fw_try = false;
2137 del_timer(&adapter->wakeup_timer);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002138 }
Shengzhen Lidc896b12016-01-12 05:43:16 -08002139
2140 spin_lock_irqsave(&adapter->int_lock, flags);
2141 adapter->int_status |= pcie_ireg;
2142 spin_unlock_irqrestore(&adapter->int_lock, flags);
2143 mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002144}
2145
2146/*
2147 * Interrupt handler for PCIe root port
2148 *
2149 * This function reads the interrupt status from firmware and assigns
2150 * the main process in workqueue which will handle the interrupt.
2151 */
2152static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
2153{
Xinming Hu99074fc2016-01-11 02:16:40 -08002154 struct mwifiex_msix_context *ctx = context;
2155 struct pci_dev *pdev = ctx->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002156 struct pcie_service_card *card;
2157 struct mwifiex_adapter *adapter;
2158
2159 if (!pdev) {
Xinming Hu91442432015-12-31 06:24:14 -08002160 pr_err("info: %s: pdev is NULL\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002161 goto exit;
2162 }
2163
Jingoo Hanb2a31202013-09-09 14:26:51 +09002164 card = pci_get_drvdata(pdev);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002165 if (!card || !card->adapter) {
Xinming Hu91442432015-12-31 06:24:14 -08002166 pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
2167 card ? card->adapter : NULL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002168 goto exit;
2169 }
2170 adapter = card->adapter;
2171
2172 if (adapter->surprise_removed)
2173 goto exit;
2174
Xinming Hu99074fc2016-01-11 02:16:40 -08002175 if (card->msix_enable)
2176 mwifiex_interrupt_status(adapter, ctx->msg_id);
2177 else
2178 mwifiex_interrupt_status(adapter, -1);
2179
Shengzhen Lib2713f62015-03-13 17:37:54 +05302180 mwifiex_queue_main_work(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002181
2182exit:
2183 return IRQ_HANDLED;
2184}
2185
2186/*
2187 * This function checks the current interrupt status.
2188 *
2189 * The following interrupts are checked and handled by this function -
2190 * - Data sent
2191 * - Command sent
2192 * - Command received
2193 * - Packets received
2194 * - Events received
2195 *
2196 * In case of Rx packets received, the packets are uploaded from card to
2197 * host and processed accordingly.
2198 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002199static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002200{
2201 int ret;
Shengzhen Li5781fc22016-07-01 18:26:52 +05302202 u32 pcie_ireg = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002203 unsigned long flags;
Shengzhen Li5781fc22016-07-01 18:26:52 +05302204 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002205
2206 spin_lock_irqsave(&adapter->int_lock, flags);
Shengzhen Li5781fc22016-07-01 18:26:52 +05302207 if (!card->msi_enable) {
2208 /* Clear out unused interrupts */
2209 pcie_ireg = adapter->int_status;
2210 }
Avinash Patil659c4782013-01-03 21:21:28 -08002211 adapter->int_status = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002212 spin_unlock_irqrestore(&adapter->int_lock, flags);
2213
Shengzhen Li5781fc22016-07-01 18:26:52 +05302214 if (card->msi_enable) {
2215 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2216 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2217 &pcie_ireg)) {
2218 mwifiex_dbg(adapter, ERROR,
2219 "Read register failed\n");
2220 return -1;
2221 }
2222
2223 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2224 if (mwifiex_write_reg(adapter,
2225 PCIE_HOST_INT_STATUS,
2226 ~pcie_ireg)) {
2227 mwifiex_dbg(adapter, ERROR,
2228 "Write register failed\n");
2229 return -1;
2230 }
2231 if (!adapter->pps_uapsd_mode &&
2232 adapter->ps_state == PS_STATE_SLEEP) {
2233 adapter->ps_state = PS_STATE_AWAKE;
2234 adapter->pm_wakeup_fw_try = false;
2235 del_timer(&adapter->wakeup_timer);
2236 }
2237 }
2238 }
2239 }
Avinash Patil659c4782013-01-03 21:21:28 -08002240 while (pcie_ireg & HOST_INTR_MASK) {
2241 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2242 pcie_ireg &= ~HOST_INTR_DNLD_DONE;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302243 mwifiex_dbg(adapter, INTR,
2244 "info: TX DNLD Done\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08002245 ret = mwifiex_pcie_send_data_complete(adapter);
2246 if (ret)
2247 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002248 }
Avinash Patil659c4782013-01-03 21:21:28 -08002249 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2250 pcie_ireg &= ~HOST_INTR_UPLD_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302251 mwifiex_dbg(adapter, INTR,
2252 "info: Rx DATA\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002253 ret = mwifiex_pcie_process_recv_data(adapter);
2254 if (ret)
2255 return ret;
2256 }
Avinash Patil659c4782013-01-03 21:21:28 -08002257 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2258 pcie_ireg &= ~HOST_INTR_EVENT_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302259 mwifiex_dbg(adapter, INTR,
2260 "info: Rx EVENT\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002261 ret = mwifiex_pcie_process_event_ready(adapter);
2262 if (ret)
2263 return ret;
2264 }
2265
Avinash Patil659c4782013-01-03 21:21:28 -08002266 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2267 pcie_ireg &= ~HOST_INTR_CMD_DONE;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002268 if (adapter->cmd_sent) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302269 mwifiex_dbg(adapter, INTR,
2270 "info: CMD sent Interrupt\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002271 adapter->cmd_sent = false;
2272 }
2273 /* Handle command response */
2274 ret = mwifiex_pcie_process_cmd_complete(adapter);
2275 if (ret)
2276 return ret;
2277 }
2278
Shengzhen Li5781fc22016-07-01 18:26:52 +05302279 if (card->msi_enable) {
2280 spin_lock_irqsave(&adapter->int_lock, flags);
2281 adapter->int_status = 0;
2282 spin_unlock_irqrestore(&adapter->int_lock, flags);
2283 }
2284
Amitkumar Karward930fae2011-10-11 17:41:21 -07002285 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2286 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2287 &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302288 mwifiex_dbg(adapter, ERROR,
2289 "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002290 return -1;
2291 }
2292
2293 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2294 if (mwifiex_write_reg(adapter,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002295 PCIE_HOST_INT_STATUS,
2296 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302297 mwifiex_dbg(adapter, ERROR,
2298 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002299 return -1;
2300 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002301 }
2302
2303 }
Amitkumar Karwar51495282016-07-15 19:07:04 +05302304 if (!card->msi_enable) {
2305 spin_lock_irqsave(&adapter->int_lock, flags);
2306 pcie_ireg |= adapter->int_status;
2307 adapter->int_status = 0;
2308 spin_unlock_irqrestore(&adapter->int_lock, flags);
2309 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002310 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302311 mwifiex_dbg(adapter, INTR,
2312 "info: cmd_sent=%d data_sent=%d\n",
2313 adapter->cmd_sent, adapter->data_sent);
Shengzhen Li5781fc22016-07-01 18:26:52 +05302314 if (!card->msi_enable && adapter->ps_state != PS_STATE_SLEEP)
Avinash Patilb2fda1f2013-03-22 21:49:05 -07002315 mwifiex_pcie_enable_host_int(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002316
2317 return 0;
2318}
2319
Xinming Hu99074fc2016-01-11 02:16:40 -08002320static int mwifiex_process_msix_int(struct mwifiex_adapter *adapter)
2321{
2322 int ret;
2323 u32 pcie_ireg;
2324 unsigned long flags;
2325
2326 spin_lock_irqsave(&adapter->int_lock, flags);
2327 /* Clear out unused interrupts */
2328 pcie_ireg = adapter->int_status;
2329 adapter->int_status = 0;
2330 spin_unlock_irqrestore(&adapter->int_lock, flags);
2331
2332 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2333 mwifiex_dbg(adapter, INTR,
2334 "info: TX DNLD Done\n");
2335 ret = mwifiex_pcie_send_data_complete(adapter);
2336 if (ret)
2337 return ret;
2338 }
2339 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2340 mwifiex_dbg(adapter, INTR,
2341 "info: Rx DATA\n");
2342 ret = mwifiex_pcie_process_recv_data(adapter);
2343 if (ret)
2344 return ret;
2345 }
2346 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2347 mwifiex_dbg(adapter, INTR,
2348 "info: Rx EVENT\n");
2349 ret = mwifiex_pcie_process_event_ready(adapter);
2350 if (ret)
2351 return ret;
2352 }
2353
2354 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2355 if (adapter->cmd_sent) {
2356 mwifiex_dbg(adapter, INTR,
2357 "info: CMD sent Interrupt\n");
2358 adapter->cmd_sent = false;
2359 }
2360 /* Handle command response */
2361 ret = mwifiex_pcie_process_cmd_complete(adapter);
2362 if (ret)
2363 return ret;
2364 }
2365
2366 mwifiex_dbg(adapter, INTR,
2367 "info: cmd_sent=%d data_sent=%d\n",
2368 adapter->cmd_sent, adapter->data_sent);
2369
2370 return 0;
2371}
2372
2373static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
2374{
2375 struct pcie_service_card *card = adapter->card;
2376
2377 if (card->msix_enable)
2378 return mwifiex_process_msix_int(adapter);
2379 else
2380 return mwifiex_process_pcie_int(adapter);
2381}
2382
Amitkumar Karward930fae2011-10-11 17:41:21 -07002383/*
2384 * This function downloads data from driver to card.
2385 *
2386 * Both commands and data packets are transferred to the card by this
2387 * function.
2388 *
2389 * This function adds the PCIE specific header to the front of the buffer
2390 * before transferring. The header contains the length of the packet and
2391 * the type. The firmware handles the packets based upon this set type.
2392 */
2393static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
2394 struct sk_buff *skb,
2395 struct mwifiex_tx_param *tx_param)
2396{
Dan Carpenterfa161cb2011-11-07 19:31:45 -08002397 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302398 mwifiex_dbg(adapter, ERROR,
2399 "Passed NULL skb to %s\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002400 return -1;
2401 }
2402
2403 if (type == MWIFIEX_TYPE_DATA)
Avinash Patile7f767a2013-01-03 21:21:32 -08002404 return mwifiex_pcie_send_data(adapter, skb, tx_param);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002405 else if (type == MWIFIEX_TYPE_CMD)
2406 return mwifiex_pcie_send_cmd(adapter, skb);
2407
2408 return 0;
2409}
2410
Xinming Hu46469682016-04-05 01:04:40 -07002411/* Function to dump PCIE scratch registers in case of FW crash
2412 */
2413static int
2414mwifiex_pcie_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
2415{
2416 char *p = drv_buf;
2417 char buf[256], *ptr;
2418 int i;
2419 u32 value;
2420 struct pcie_service_card *card = adapter->card;
2421 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2422 int pcie_scratch_reg[] = {PCIE_SCRATCH_12_REG,
2423 PCIE_SCRATCH_13_REG,
2424 PCIE_SCRATCH_14_REG};
2425
2426 if (!p)
2427 return 0;
2428
2429 mwifiex_dbg(adapter, MSG, "PCIE register dump start\n");
2430
2431 if (mwifiex_read_reg(adapter, reg->fw_status, &value)) {
2432 mwifiex_dbg(adapter, ERROR, "failed to read firmware status");
2433 return 0;
2434 }
2435
2436 ptr = buf;
2437 mwifiex_dbg(adapter, MSG, "pcie scratch register:");
2438 for (i = 0; i < ARRAY_SIZE(pcie_scratch_reg); i++) {
2439 mwifiex_read_reg(adapter, pcie_scratch_reg[i], &value);
2440 ptr += sprintf(ptr, "reg:0x%x, value=0x%x\n",
2441 pcie_scratch_reg[i], value);
2442 }
2443
2444 mwifiex_dbg(adapter, MSG, "%s\n", buf);
2445 p += sprintf(p, "%s\n", buf);
2446
2447 mwifiex_dbg(adapter, MSG, "PCIE register dump end\n");
2448
2449 return p - drv_buf;
2450}
2451
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002452/* This function read/write firmware */
2453static enum rdwr_status
2454mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
2455{
2456 int ret, tries;
2457 u8 ctrl_data;
Xinming Hu01724042016-02-02 22:05:04 -08002458 u32 fw_status;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002459 struct pcie_service_card *card = adapter->card;
2460 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2461
Xinming Hu01724042016-02-02 22:05:04 -08002462 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status))
2463 return RDWR_STATUS_FAILURE;
2464
Xinming Hu50632092016-02-02 22:05:06 -08002465 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
2466 reg->fw_dump_host_ready);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002467 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302468 mwifiex_dbg(adapter, ERROR,
2469 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002470 return RDWR_STATUS_FAILURE;
2471 }
2472
2473 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2474 mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
2475 if (ctrl_data == FW_DUMP_DONE)
2476 return RDWR_STATUS_SUCCESS;
2477 if (doneflag && ctrl_data == doneflag)
2478 return RDWR_STATUS_DONE;
Xinming Hu50632092016-02-02 22:05:06 -08002479 if (ctrl_data != reg->fw_dump_host_ready) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302480 mwifiex_dbg(adapter, WARN,
2481 "The ctrl reg was changed, re-try again!\n");
Amitkumar Karwar24716872014-09-18 08:04:01 -04002482 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
Xinming Hu50632092016-02-02 22:05:06 -08002483 reg->fw_dump_host_ready);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002484 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302485 mwifiex_dbg(adapter, ERROR,
2486 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002487 return RDWR_STATUS_FAILURE;
2488 }
2489 }
2490 usleep_range(100, 200);
2491 }
2492
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302493 mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002494 return RDWR_STATUS_FAILURE;
2495}
2496
2497/* This function dump firmware memory to file */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002498static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002499{
2500 struct pcie_service_card *card = adapter->card;
2501 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2502 unsigned int reg, reg_start, reg_end;
Xinming Hu11e70822016-02-02 22:05:09 -08002503 u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num;
Xinming Hu56486022016-02-02 22:05:07 -08002504 u8 idx, i, read_reg, doneflag = 0;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002505 enum rdwr_status stat;
2506 u32 memory_size;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002507 int ret;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002508
Avinash Patilb4e8aeb2015-02-11 23:12:26 +05302509 if (!card->pcie.can_dump_fw)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002510 return;
2511
Xinming Hu50632092016-02-02 22:05:06 -08002512 for (idx = 0; idx < adapter->num_mem_types; idx++) {
2513 struct memory_type_mapping *entry =
2514 &adapter->mem_type_mapping_tbl[idx];
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002515
2516 if (entry->mem_ptr) {
2517 vfree(entry->mem_ptr);
2518 entry->mem_ptr = NULL;
2519 }
2520 entry->mem_size = 0;
2521 }
2522
Amitkumar Karwar03f0f7c2016-02-02 22:05:08 -08002523 mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002524
2525 /* Read the number of the memories which will dump */
2526 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2527 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002528 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002529
2530 reg = creg->fw_dump_start;
Xinming Hu11e70822016-02-02 22:05:09 -08002531 mwifiex_read_reg_byte(adapter, reg, &fw_dump_num);
2532
2533 /* W8997 chipset firmware dump will be restore in single region*/
2534 if (fw_dump_num == 0)
2535 dump_num = 1;
2536 else
2537 dump_num = fw_dump_num;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002538
2539 /* Read the length of every memory which will dump */
2540 for (idx = 0; idx < dump_num; idx++) {
Xinming Hu50632092016-02-02 22:05:06 -08002541 struct memory_type_mapping *entry =
2542 &adapter->mem_type_mapping_tbl[idx];
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002543 memory_size = 0;
Xinming Hu11e70822016-02-02 22:05:09 -08002544 if (fw_dump_num != 0) {
2545 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2546 if (stat == RDWR_STATUS_FAILURE)
2547 return;
2548
2549 reg = creg->fw_dump_start;
2550 for (i = 0; i < 4; i++) {
2551 mwifiex_read_reg_byte(adapter, reg, &read_reg);
2552 memory_size |= (read_reg << (i * 8));
Dan Carpenterccf5fa42016-02-09 14:15:36 +03002553 reg++;
Xinming Hu11e70822016-02-02 22:05:09 -08002554 }
2555 } else {
2556 memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002557 }
2558
2559 if (memory_size == 0) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302560 mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002561 ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
Xinming Hu50632092016-02-02 22:05:06 -08002562 creg->fw_dump_read_done);
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002563 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302564 mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002565 return;
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002566 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002567 break;
2568 }
2569
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302570 mwifiex_dbg(adapter, DUMP,
2571 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002572 entry->mem_ptr = vmalloc(memory_size + 1);
2573 entry->mem_size = memory_size;
2574 if (!entry->mem_ptr) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302575 mwifiex_dbg(adapter, ERROR,
2576 "Vmalloc %s failed\n", entry->mem_name);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002577 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002578 }
2579 dbg_ptr = entry->mem_ptr;
2580 end_ptr = dbg_ptr + memory_size;
2581
2582 doneflag = entry->done_flag;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302583 mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
2584 entry->mem_name);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002585
2586 do {
2587 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2588 if (RDWR_STATUS_FAILURE == stat)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002589 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002590
2591 reg_start = creg->fw_dump_start;
2592 reg_end = creg->fw_dump_end;
2593 for (reg = reg_start; reg <= reg_end; reg++) {
2594 mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
Amitkumar Karwar24716872014-09-18 08:04:01 -04002595 if (dbg_ptr < end_ptr) {
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002596 dbg_ptr++;
Xinming Hu56486022016-02-02 22:05:07 -08002597 continue;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002598 }
Xinming Hu56486022016-02-02 22:05:07 -08002599 mwifiex_dbg(adapter, ERROR,
2600 "pre-allocated buf not enough\n");
2601 tmp_ptr =
2602 vzalloc(memory_size + MWIFIEX_SIZE_4K);
2603 if (!tmp_ptr)
2604 return;
2605 memcpy(tmp_ptr, entry->mem_ptr, memory_size);
2606 vfree(entry->mem_ptr);
2607 entry->mem_ptr = tmp_ptr;
2608 tmp_ptr = NULL;
2609 dbg_ptr = entry->mem_ptr + memory_size;
2610 memory_size += MWIFIEX_SIZE_4K;
2611 end_ptr = entry->mem_ptr + memory_size;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002612 }
2613
2614 if (stat != RDWR_STATUS_DONE)
2615 continue;
2616
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302617 mwifiex_dbg(adapter, DUMP,
2618 "%s done: size=0x%tx\n",
2619 entry->mem_name, dbg_ptr - entry->mem_ptr);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002620 break;
2621 } while (true);
2622 }
Amitkumar Karwar03f0f7c2016-02-02 22:05:08 -08002623 mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002624}
2625
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002626static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
2627{
2628 mwifiex_drv_info_dump(adapter);
2629 mwifiex_pcie_fw_dump(adapter);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002630 mwifiex_upload_device_dump(adapter);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002631}
2632
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002633static unsigned long iface_work_flags;
2634static struct mwifiex_adapter *save_adapter;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002635static void mwifiex_pcie_work(struct work_struct *work)
2636{
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002637 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002638 &iface_work_flags))
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002639 mwifiex_pcie_device_dump_work(save_adapter);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002640}
2641
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002642static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002643/* This function dumps FW information */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002644static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002645{
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002646 save_adapter = adapter;
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002647 if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002648 return;
2649
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002650 set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002651
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002652 schedule_work(&pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002653}
2654
Amitkumar Karward930fae2011-10-11 17:41:21 -07002655/*
2656 * This function initializes the PCI-E host memory space, WCB rings, etc.
2657 *
2658 * The following initializations steps are followed -
2659 * - Allocate TXBD ring buffers
2660 * - Allocate RXBD ring buffers
2661 * - Allocate event BD ring buffers
2662 * - Allocate command response ring buffer
2663 * - Allocate sleep cookie buffer
2664 */
2665static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
2666{
2667 struct pcie_service_card *card = adapter->card;
2668 int ret;
2669 struct pci_dev *pdev = card->dev;
Avinash Patil52301a82013-02-12 14:38:32 -08002670 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002671
2672 pci_set_drvdata(pdev, card);
2673
2674 ret = pci_enable_device(pdev);
2675 if (ret)
2676 goto err_enable_dev;
2677
2678 pci_set_master(pdev);
2679
Xinming Hufdb1e282015-12-31 06:24:12 -08002680 pr_notice("try set_consistent_dma_mask(32)\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002681 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
2682 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002683 pr_err("set_dma_mask(32) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002684 goto err_set_dma_mask;
2685 }
2686
2687 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
2688 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002689 pr_err("set_consistent_dma_mask(64) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002690 goto err_set_dma_mask;
2691 }
2692
2693 ret = pci_request_region(pdev, 0, DRV_NAME);
2694 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002695 pr_err("req_reg(0) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002696 goto err_req_region0;
2697 }
2698 card->pci_mmap = pci_iomap(pdev, 0, 0);
2699 if (!card->pci_mmap) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002700 pr_err("iomap(0) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002701 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002702 goto err_iomap0;
2703 }
2704 ret = pci_request_region(pdev, 2, DRV_NAME);
2705 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002706 pr_err("req_reg(2) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002707 goto err_req_region2;
2708 }
2709 card->pci_mmap1 = pci_iomap(pdev, 2, 0);
2710 if (!card->pci_mmap1) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002711 pr_err("iomap(2) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002712 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002713 goto err_iomap2;
2714 }
2715
Xinming Hufdb1e282015-12-31 06:24:12 -08002716 pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
2717 card->pci_mmap, card->pci_mmap1);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002718
2719 card->cmdrsp_buf = NULL;
2720 ret = mwifiex_pcie_create_txbd_ring(adapter);
2721 if (ret)
2722 goto err_cre_txbd;
2723 ret = mwifiex_pcie_create_rxbd_ring(adapter);
2724 if (ret)
2725 goto err_cre_rxbd;
2726 ret = mwifiex_pcie_create_evtbd_ring(adapter);
2727 if (ret)
2728 goto err_cre_evtbd;
2729 ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
2730 if (ret)
2731 goto err_alloc_cmdbuf;
Avinash Patil52301a82013-02-12 14:38:32 -08002732 if (reg->sleep_cookie) {
2733 ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
2734 if (ret)
2735 goto err_alloc_cookie;
2736 } else {
2737 card->sleep_cookie_vbase = NULL;
2738 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002739 return ret;
2740
2741err_alloc_cookie:
2742 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2743err_alloc_cmdbuf:
2744 mwifiex_pcie_delete_evtbd_ring(adapter);
2745err_cre_evtbd:
2746 mwifiex_pcie_delete_rxbd_ring(adapter);
2747err_cre_rxbd:
2748 mwifiex_pcie_delete_txbd_ring(adapter);
2749err_cre_txbd:
2750 pci_iounmap(pdev, card->pci_mmap1);
2751err_iomap2:
2752 pci_release_region(pdev, 2);
2753err_req_region2:
2754 pci_iounmap(pdev, card->pci_mmap);
2755err_iomap0:
2756 pci_release_region(pdev, 0);
2757err_req_region0:
2758err_set_dma_mask:
2759 pci_disable_device(pdev);
2760err_enable_dev:
2761 pci_set_drvdata(pdev, NULL);
2762 return ret;
2763}
2764
2765/*
2766 * This function cleans up the allocated card buffers.
2767 *
2768 * The following are freed by this function -
2769 * - TXBD ring buffers
2770 * - RXBD ring buffers
2771 * - Event BD ring buffers
2772 * - Command response ring buffer
2773 * - Sleep cookie buffer
2774 */
2775static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
2776{
2777 struct pcie_service_card *card = adapter->card;
2778 struct pci_dev *pdev = card->dev;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002779 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002780
Amitkumar Karward930fae2011-10-11 17:41:21 -07002781 if (user_rmmod) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302782 mwifiex_dbg(adapter, INFO,
2783 "Clearing driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002784 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302785 mwifiex_dbg(adapter, ERROR,
2786 "Failed to write driver not-ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002787 }
2788
2789 if (pdev) {
2790 pci_iounmap(pdev, card->pci_mmap);
2791 pci_iounmap(pdev, card->pci_mmap1);
Yogesh Ashok Powar5b0d9b22013-04-23 16:49:48 -07002792 pci_disable_device(pdev);
Yogesh Ashok Powarc380aaf2013-04-23 16:49:47 -07002793 pci_release_region(pdev, 2);
2794 pci_release_region(pdev, 0);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002795 pci_set_drvdata(pdev, NULL);
2796 }
Amitkumar Karwar3c59e322013-11-14 19:10:41 -08002797 kfree(card);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002798}
2799
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002800static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
2801{
Xinming Hu99074fc2016-01-11 02:16:40 -08002802 int ret, i, j;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002803 struct pcie_service_card *card = adapter->card;
2804 struct pci_dev *pdev = card->dev;
2805
Xinming Hu99074fc2016-01-11 02:16:40 -08002806 if (card->pcie.reg->msix_support) {
2807 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2808 card->msix_entries[i].entry = i;
2809 ret = pci_enable_msix_exact(pdev, card->msix_entries,
2810 MWIFIEX_NUM_MSIX_VECTORS);
2811 if (!ret) {
2812 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) {
2813 card->msix_ctx[i].dev = pdev;
2814 card->msix_ctx[i].msg_id = i;
2815
2816 ret = request_irq(card->msix_entries[i].vector,
2817 mwifiex_pcie_interrupt, 0,
2818 "MWIFIEX_PCIE_MSIX",
2819 &card->msix_ctx[i]);
2820 if (ret)
2821 break;
2822 }
2823
2824 if (ret) {
2825 mwifiex_dbg(adapter, INFO, "request_irq fail: %d\n",
2826 ret);
2827 for (j = 0; j < i; j++)
2828 free_irq(card->msix_entries[j].vector,
2829 &card->msix_ctx[i]);
2830 pci_disable_msix(pdev);
2831 } else {
2832 mwifiex_dbg(adapter, MSG, "MSIx enabled!");
2833 card->msix_enable = 1;
2834 return 0;
2835 }
2836 }
2837 }
2838
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002839 if (pci_enable_msi(pdev) != 0)
2840 pci_disable_msi(pdev);
2841 else
2842 card->msi_enable = 1;
2843
2844 mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable);
2845
Xinming Hu99074fc2016-01-11 02:16:40 -08002846 card->share_irq_ctx.dev = pdev;
2847 card->share_irq_ctx.msg_id = -1;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002848 ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
Xinming Hu99074fc2016-01-11 02:16:40 -08002849 "MRVL_PCIE", &card->share_irq_ctx);
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002850 if (ret) {
2851 pr_err("request_irq failed: ret=%d\n", ret);
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002852 return -1;
2853 }
2854
2855 return 0;
2856}
2857
Amitkumar Karward930fae2011-10-11 17:41:21 -07002858/*
Julia Lawall47ce90f2016-05-17 16:38:46 +02002859 * This function gets the firmware name for downloading by revision id
Shengzhen Lia362e162016-04-05 01:04:36 -07002860 *
2861 * Read revision id register to get revision id
2862 */
2863static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
2864{
2865 int revision_id = 0;
Shengzhen Lie87650b2016-04-11 07:52:38 -07002866 int version;
Shengzhen Lia362e162016-04-05 01:04:36 -07002867 struct pcie_service_card *card = adapter->card;
2868
2869 switch (card->dev->device) {
2870 case PCIE_DEVICE_ID_MARVELL_88W8766P:
2871 strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME);
2872 break;
2873 case PCIE_DEVICE_ID_MARVELL_88W8897:
2874 mwifiex_write_reg(adapter, 0x0c58, 0x80c00000);
2875 mwifiex_read_reg(adapter, 0x0c58, &revision_id);
2876 revision_id &= 0xff00;
2877 switch (revision_id) {
2878 case PCIE8897_A0:
2879 strcpy(adapter->fw_name, PCIE8897_A0_FW_NAME);
2880 break;
2881 case PCIE8897_B0:
2882 strcpy(adapter->fw_name, PCIE8897_B0_FW_NAME);
2883 break;
2884 default:
Shengzhen Lib9db3972016-04-11 07:52:39 -07002885 strcpy(adapter->fw_name, PCIE8897_DEFAULT_FW_NAME);
2886
Shengzhen Lia362e162016-04-05 01:04:36 -07002887 break;
2888 }
Amitkumar Karwarc865a702016-04-11 07:52:37 -07002889 break;
Shengzhen Lia362e162016-04-05 01:04:36 -07002890 case PCIE_DEVICE_ID_MARVELL_88W8997:
2891 mwifiex_read_reg(adapter, 0x0c48, &revision_id);
Shengzhen Lie87650b2016-04-11 07:52:38 -07002892 mwifiex_read_reg(adapter, 0x0cd0, &version);
2893 version &= 0x7;
Shengzhen Lia362e162016-04-05 01:04:36 -07002894 switch (revision_id) {
2895 case PCIE8997_V2:
Amitkumar Karwar473dfbf2016-06-30 22:24:57 +05302896 if (version == CHIP_VER_PCIEUART)
Shengzhen Lie87650b2016-04-11 07:52:38 -07002897 strcpy(adapter->fw_name,
2898 PCIEUART8997_FW_NAME_V2);
Shengzhen Lie87650b2016-04-11 07:52:38 -07002899 else
2900 strcpy(adapter->fw_name,
Amitkumar Karwar473dfbf2016-06-30 22:24:57 +05302901 PCIEUSB8997_FW_NAME_V2);
2902 break;
2903 case PCIE8997_Z:
2904 if (version == CHIP_VER_PCIEUART)
2905 strcpy(adapter->fw_name,
Shengzhen Lie87650b2016-04-11 07:52:38 -07002906 PCIEUART8997_FW_NAME_Z);
Amitkumar Karwar473dfbf2016-06-30 22:24:57 +05302907 else
2908 strcpy(adapter->fw_name,
2909 PCIEUSB8997_FW_NAME_Z);
Shengzhen Lia362e162016-04-05 01:04:36 -07002910 break;
2911 default:
Shengzhen Lib9db3972016-04-11 07:52:39 -07002912 strcpy(adapter->fw_name, PCIE8997_DEFAULT_FW_NAME);
Shengzhen Lia362e162016-04-05 01:04:36 -07002913 break;
2914 }
2915 default:
2916 break;
2917 }
2918}
2919
2920/*
Amitkumar Karward930fae2011-10-11 17:41:21 -07002921 * This function registers the PCIE device.
2922 *
2923 * PCIE IRQ is claimed, block size is set and driver data is initialized.
2924 */
2925static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
2926{
Amitkumar Karward930fae2011-10-11 17:41:21 -07002927 struct pcie_service_card *card = adapter->card;
2928 struct pci_dev *pdev = card->dev;
2929
2930 /* save adapter pointer in card */
2931 card->adapter = adapter;
Xinming Hufdb1e282015-12-31 06:24:12 -08002932 adapter->dev = &pdev->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002933
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002934 if (mwifiex_pcie_request_irq(adapter))
Amitkumar Karward930fae2011-10-11 17:41:21 -07002935 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002936
Amitkumar Karwar828cf222014-02-27 19:35:13 -08002937 adapter->tx_buf_size = card->pcie.tx_buf_size;
Xinming Hu50632092016-02-02 22:05:06 -08002938 adapter->mem_type_mapping_tbl = card->pcie.mem_type_mapping_tbl;
2939 adapter->num_mem_types = card->pcie.num_mem_types;
Avinash Patil1fe192d2015-01-23 17:09:19 +05302940 adapter->ext_scan = card->pcie.can_ext_scan;
Shengzhen Lia362e162016-04-05 01:04:36 -07002941 mwifiex_pcie_get_fw_name(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002942
2943 return 0;
2944}
2945
2946/*
2947 * This function unregisters the PCIE device.
2948 *
2949 * The PCIE IRQ is released, the function is disabled and driver
2950 * data is set to null.
2951 */
2952static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
2953{
2954 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -08002955 const struct mwifiex_pcie_card_reg *reg;
Heinrich Schuchardt141bcf02016-05-18 01:16:01 +02002956 struct pci_dev *pdev;
Xinming Hu99074fc2016-01-11 02:16:40 -08002957 int i;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002958
2959 if (card) {
Heinrich Schuchardt141bcf02016-05-18 01:16:01 +02002960 pdev = card->dev;
Xinming Hu99074fc2016-01-11 02:16:40 -08002961 if (card->msix_enable) {
2962 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2963 synchronize_irq(card->msix_entries[i].vector);
2964
2965 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2966 free_irq(card->msix_entries[i].vector,
2967 &card->msix_ctx[i]);
2968
2969 card->msix_enable = 0;
2970 pci_disable_msix(pdev);
2971 } else {
2972 mwifiex_dbg(adapter, INFO,
2973 "%s(): calling free_irq()\n", __func__);
2974 free_irq(card->dev->irq, &card->share_irq_ctx);
2975
2976 if (card->msi_enable)
2977 pci_disable_msi(pdev);
2978 }
Avinash Patilfc331462013-01-03 21:21:30 -08002979
Avinash Patil52301a82013-02-12 14:38:32 -08002980 reg = card->pcie.reg;
2981 if (reg->sleep_cookie)
2982 mwifiex_pcie_delete_sleep_cookie_buf(adapter);
2983
Avinash Patilfc331462013-01-03 21:21:30 -08002984 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2985 mwifiex_pcie_delete_evtbd_ring(adapter);
2986 mwifiex_pcie_delete_rxbd_ring(adapter);
2987 mwifiex_pcie_delete_txbd_ring(adapter);
2988 card->cmdrsp_buf = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002989 }
2990}
2991
2992static struct mwifiex_if_ops pcie_ops = {
2993 .init_if = mwifiex_pcie_init,
2994 .cleanup_if = mwifiex_pcie_cleanup,
2995 .check_fw_status = mwifiex_check_fw_status,
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002996 .check_winner_status = mwifiex_check_winner_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002997 .prog_fw = mwifiex_prog_fw_w_helper,
2998 .register_dev = mwifiex_register_dev,
2999 .unregister_dev = mwifiex_unregister_dev,
3000 .enable_int = mwifiex_pcie_enable_host_int,
Brian Norrisd41376c2016-06-30 15:21:02 -07003001 .disable_int = mwifiex_pcie_disable_host_int_noerr,
Amitkumar Karward930fae2011-10-11 17:41:21 -07003002 .process_int_status = mwifiex_process_int_status,
3003 .host_to_card = mwifiex_pcie_host_to_card,
3004 .wakeup = mwifiex_pm_wakeup_card,
3005 .wakeup_complete = mwifiex_pm_wakeup_card_complete,
3006
3007 /* PCIE specific */
3008 .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
3009 .event_complete = mwifiex_pcie_event_complete,
3010 .update_mp_end_port = NULL,
3011 .cleanup_mpa_buf = NULL,
Avinash Patilc6d1d872013-01-03 21:21:29 -08003012 .init_fw_port = mwifiex_pcie_init_fw_port,
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08003013 .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
Xinming Hu46469682016-04-05 01:04:40 -07003014 .reg_dump = mwifiex_pcie_reg_dump,
Amitkumar Karwarfc697152015-05-26 06:34:31 -07003015 .device_dump = mwifiex_pcie_device_dump,
Amitkumar Karward930fae2011-10-11 17:41:21 -07003016};
3017
3018/*
3019 * This function initializes the PCIE driver module.
3020 *
3021 * This initiates the semaphore and registers the device with
3022 * PCIE bus.
3023 */
3024static int mwifiex_pcie_init_module(void)
3025{
3026 int ret;
3027
Avinash Patilca8f2112013-02-08 18:18:09 -08003028 pr_debug("Marvell PCIe Driver\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07003029
3030 sema_init(&add_remove_card_sem, 1);
3031
3032 /* Clear the flag in case user removes the card. */
3033 user_rmmod = 0;
3034
3035 ret = pci_register_driver(&mwifiex_pcie);
3036 if (ret)
3037 pr_err("Driver register failed!\n");
3038 else
3039 pr_debug("info: Driver registered successfully!\n");
3040
3041 return ret;
3042}
3043
3044/*
3045 * This function cleans up the PCIE driver.
3046 *
3047 * The following major steps are followed for cleanup -
3048 * - Resume the device if its suspended
3049 * - Disconnect the device if connected
3050 * - Shutdown the firmware
3051 * - Unregister the device from PCIE bus.
3052 */
3053static void mwifiex_pcie_cleanup_module(void)
3054{
3055 if (!down_interruptible(&add_remove_card_sem))
3056 up(&add_remove_card_sem);
3057
3058 /* Set the flag as user is removing this module. */
3059 user_rmmod = 1;
3060
Maithili Hinge2f5872b2015-03-22 23:01:25 -07003061 cancel_work_sync(&pcie_work);
Amitkumar Karward930fae2011-10-11 17:41:21 -07003062 pci_unregister_driver(&mwifiex_pcie);
3063}
3064
3065module_init(mwifiex_pcie_init_module);
3066module_exit(mwifiex_pcie_cleanup_module);
3067
3068MODULE_AUTHOR("Marvell International Ltd.");
3069MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
3070MODULE_VERSION(PCIE_VERSION);
3071MODULE_LICENSE("GPL v2");