blob: 77b9055a2d147411515b5875f67b90210938ac9b [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
Amitkumar Karwar92c25382014-06-19 21:38:52 -070040static struct memory_type_mapping mem_type_mapping_tbl[] = {
41 {"ITCM", NULL, 0, 0xF0},
42 {"DTCM", NULL, 0, 0xF1},
43 {"SQRAM", NULL, 0, 0xF2},
44 {"IRAM", NULL, 0, 0xF3},
Amitkumar Karwar7e174832014-09-18 07:18:50 -040045 {"APU", NULL, 0, 0xF4},
46 {"CIU", NULL, 0, 0xF5},
47 {"ICU", NULL, 0, 0xF6},
48 {"MAC", NULL, 0, 0xF7},
Amitkumar Karwar92c25382014-06-19 21:38:52 -070049};
50
Avinash Patilfc331462013-01-03 21:21:30 -080051static int
52mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
Aaron Durbindbccc922014-02-07 16:25:50 -080053 size_t size, int flags)
Amitkumar Karward930fae2011-10-11 17:41:21 -070054{
Avinash Patilfc331462013-01-03 21:21:30 -080055 struct pcie_service_card *card = adapter->card;
Aaron Durbindbccc922014-02-07 16:25:50 -080056 struct mwifiex_dma_mapping mapping;
Amitkumar Karward930fae2011-10-11 17:41:21 -070057
Aaron Durbindbccc922014-02-07 16:25:50 -080058 mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
59 if (pci_dma_mapping_error(card->dev, mapping.addr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +053060 mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
Avinash Patilfc331462013-01-03 21:21:30 -080061 return -1;
62 }
Aaron Durbindbccc922014-02-07 16:25:50 -080063 mapping.len = size;
Chin-Ran Lobca463e2014-06-06 19:37:10 -070064 mwifiex_store_mapping(skb, &mapping);
Avinash Patilfc331462013-01-03 21:21:30 -080065 return 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -070066}
67
Aaron Durbindbccc922014-02-07 16:25:50 -080068static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
69 struct sk_buff *skb, int flags)
70{
71 struct pcie_service_card *card = adapter->card;
72 struct mwifiex_dma_mapping mapping;
73
Chin-Ran Lobca463e2014-06-06 19:37:10 -070074 mwifiex_get_mapping(skb, &mapping);
Aaron Durbindbccc922014-02-07 16:25:50 -080075 pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
76}
77
Amitkumar Karward930fae2011-10-11 17:41:21 -070078/*
79 * This function reads sleep cookie and checks if FW is ready
80 */
81static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
82{
83 u32 *cookie_addr;
84 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -080085 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
86
87 if (!reg->sleep_cookie)
88 return true;
Amitkumar Karward930fae2011-10-11 17:41:21 -070089
Avinash Patilfc331462013-01-03 21:21:30 -080090 if (card->sleep_cookie_vbase) {
91 cookie_addr = (u32 *)card->sleep_cookie_vbase;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +053092 mwifiex_dbg(adapter, INFO,
93 "info: ACCESS_HW: sleep cookie=0x%x\n",
94 *cookie_addr);
Amitkumar Karward930fae2011-10-11 17:41:21 -070095 if (*cookie_addr == FW_AWAKE_COOKIE)
96 return true;
97 }
98
99 return false;
100}
101
Shuah Khan3266d732013-07-03 10:47:10 -0600102#ifdef CONFIG_PM_SLEEP
Amitkumar Karward930fae2011-10-11 17:41:21 -0700103/*
Bing Zhaofcca8d52013-03-04 16:27:53 -0800104 * Kernel needs to suspend all functions separately. Therefore all
105 * registered functions must have drivers with suspend and resume
106 * methods. Failing that the kernel simply removes the whole card.
107 *
108 * If already not suspended, this function allocates and sends a host
109 * sleep activate request to the firmware and turns off the traffic.
110 */
Shuah Khan3266d732013-07-03 10:47:10 -0600111static int mwifiex_pcie_suspend(struct device *dev)
Bing Zhaofcca8d52013-03-04 16:27:53 -0800112{
113 struct mwifiex_adapter *adapter;
114 struct pcie_service_card *card;
115 int hs_actived;
Shuah Khan3266d732013-07-03 10:47:10 -0600116 struct pci_dev *pdev = to_pci_dev(dev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800117
118 if (pdev) {
Jingoo Hanb2a31202013-09-09 14:26:51 +0900119 card = pci_get_drvdata(pdev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800120 if (!card || !card->adapter) {
121 pr_err("Card or adapter structure is not valid\n");
122 return 0;
123 }
124 } else {
125 pr_err("PCIE device is not specified\n");
126 return 0;
127 }
128
129 adapter = card->adapter;
130
131 hs_actived = mwifiex_enable_hs(adapter);
132
133 /* Indicate device suspended */
134 adapter->is_suspended = true;
Amitkumar Karwarc0dbba62014-03-25 19:01:20 -0700135 adapter->hs_enabling = false;
Bing Zhaofcca8d52013-03-04 16:27:53 -0800136
137 return 0;
138}
139
140/*
141 * Kernel needs to suspend all functions separately. Therefore all
142 * registered functions must have drivers with suspend and resume
143 * methods. Failing that the kernel simply removes the whole card.
144 *
145 * If already not resumed, this function turns on the traffic and
146 * sends a host sleep cancel request to the firmware.
147 */
Shuah Khan3266d732013-07-03 10:47:10 -0600148static int mwifiex_pcie_resume(struct device *dev)
Bing Zhaofcca8d52013-03-04 16:27:53 -0800149{
150 struct mwifiex_adapter *adapter;
151 struct pcie_service_card *card;
Shuah Khan3266d732013-07-03 10:47:10 -0600152 struct pci_dev *pdev = to_pci_dev(dev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800153
154 if (pdev) {
Jingoo Hanb2a31202013-09-09 14:26:51 +0900155 card = pci_get_drvdata(pdev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800156 if (!card || !card->adapter) {
157 pr_err("Card or adapter structure is not valid\n");
158 return 0;
159 }
160 } else {
161 pr_err("PCIE device is not specified\n");
162 return 0;
163 }
164
165 adapter = card->adapter;
166
167 if (!adapter->is_suspended) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530168 mwifiex_dbg(adapter, WARN,
169 "Device already resumed\n");
Bing Zhaofcca8d52013-03-04 16:27:53 -0800170 return 0;
171 }
172
173 adapter->is_suspended = false;
174
175 mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
176 MWIFIEX_ASYNC_CMD);
177
178 return 0;
179}
Bing Zhao8509e822013-03-04 16:27:54 -0800180#endif
Bing Zhaofcca8d52013-03-04 16:27:53 -0800181
182/*
Amitkumar Karward930fae2011-10-11 17:41:21 -0700183 * This function probes an mwifiex device and registers it. It allocates
184 * the card structure, enables PCIE function number and initiates the
185 * device registration and initialization procedure by adding a logical
186 * interface.
187 */
188static int mwifiex_pcie_probe(struct pci_dev *pdev,
189 const struct pci_device_id *ent)
190{
191 struct pcie_service_card *card;
192
193 pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700194 pdev->vendor, pdev->device, pdev->revision);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700195
196 card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL);
Joe Perchese404dec2012-01-29 12:56:23 +0000197 if (!card)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700198 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700199
200 card->dev = pdev;
201
Avinash Patildd04e6a2013-02-08 18:18:06 -0800202 if (ent->driver_data) {
203 struct mwifiex_pcie_device *data = (void *)ent->driver_data;
204 card->pcie.firmware = data->firmware;
205 card->pcie.reg = data->reg;
206 card->pcie.blksz_fw_dl = data->blksz_fw_dl;
Amitkumar Karwar828cf222014-02-27 19:35:13 -0800207 card->pcie.tx_buf_size = data->tx_buf_size;
Avinash Patilb4e8aeb2015-02-11 23:12:26 +0530208 card->pcie.can_dump_fw = data->can_dump_fw;
Avinash Patil1fe192d2015-01-23 17:09:19 +0530209 card->pcie.can_ext_scan = data->can_ext_scan;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800210 }
211
Amitkumar Karward930fae2011-10-11 17:41:21 -0700212 if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
213 MWIFIEX_PCIE)) {
214 pr_err("%s failed\n", __func__);
215 kfree(card);
216 return -1;
217 }
218
219 return 0;
220}
221
222/*
223 * This function removes the interface and frees up the card structure.
224 */
225static void mwifiex_pcie_remove(struct pci_dev *pdev)
226{
227 struct pcie_service_card *card;
228 struct mwifiex_adapter *adapter;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700229 struct mwifiex_private *priv;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700230
231 card = pci_get_drvdata(pdev);
232 if (!card)
233 return;
234
235 adapter = card->adapter;
236 if (!adapter || !adapter->priv_num)
237 return;
238
239 if (user_rmmod) {
Shuah Khan3266d732013-07-03 10:47:10 -0600240#ifdef CONFIG_PM_SLEEP
Amitkumar Karward930fae2011-10-11 17:41:21 -0700241 if (adapter->is_suspended)
Shuah Khan3266d732013-07-03 10:47:10 -0600242 mwifiex_pcie_resume(&pdev->dev);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700243#endif
244
Amitkumar Karwar848819f2014-02-27 19:35:17 -0800245 mwifiex_deauthenticate_all(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700246
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700247 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700248
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700249 mwifiex_disable_auto_ds(priv);
250
251 mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700252 }
253
254 mwifiex_remove_card(card->adapter, &add_remove_card_sem);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700255}
256
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700257static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
258{
259 user_rmmod = 1;
260 mwifiex_pcie_remove(pdev);
261
262 return;
263}
264
Benoit Taine9baa3c32014-08-08 15:56:03 +0200265static const struct pci_device_id mwifiex_ids[] = {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700266 {
267 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
268 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Avinash Patildd04e6a2013-02-08 18:18:06 -0800269 .driver_data = (unsigned long) &mwifiex_pcie8766,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700270 },
Avinash Patilca8f2112013-02-08 18:18:09 -0800271 {
272 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
273 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
274 .driver_data = (unsigned long) &mwifiex_pcie8897,
275 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700276 {},
277};
278
279MODULE_DEVICE_TABLE(pci, mwifiex_ids);
280
Shuah Khan3266d732013-07-03 10:47:10 -0600281#ifdef CONFIG_PM_SLEEP
282/* Power Management Hooks */
283static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
284 mwifiex_pcie_resume);
285#endif
286
Amitkumar Karward930fae2011-10-11 17:41:21 -0700287/* PCI Device Driver */
288static struct pci_driver __refdata mwifiex_pcie = {
289 .name = "mwifiex_pcie",
290 .id_table = mwifiex_ids,
291 .probe = mwifiex_pcie_probe,
292 .remove = mwifiex_pcie_remove,
Shuah Khan3266d732013-07-03 10:47:10 -0600293#ifdef CONFIG_PM_SLEEP
294 .driver = {
295 .pm = &mwifiex_pcie_pm_ops,
296 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700297#endif
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700298 .shutdown = mwifiex_pcie_shutdown,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700299};
300
301/*
302 * This function writes data into PCIE card register.
303 */
304static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
305{
306 struct pcie_service_card *card = adapter->card;
307
308 iowrite32(data, card->pci_mmap1 + reg);
309
310 return 0;
311}
312
313/*
314 * This function reads data from PCIE card register.
315 */
316static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
317{
318 struct pcie_service_card *card = adapter->card;
319
320 *data = ioread32(card->pci_mmap1 + reg);
321
322 return 0;
323}
324
Amitkumar Karwar92c25382014-06-19 21:38:52 -0700325/* This function reads u8 data from PCIE card register. */
326static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
327 int reg, u8 *data)
328{
329 struct pcie_service_card *card = adapter->card;
330
331 *data = ioread8(card->pci_mmap1 + reg);
332
333 return 0;
334}
335
Amitkumar Karward930fae2011-10-11 17:41:21 -0700336/*
Avinash Patilc0880a22013-03-22 21:49:07 -0700337 * This function adds delay loop to ensure FW is awake before proceeding.
Amitkumar Karward930fae2011-10-11 17:41:21 -0700338 */
Avinash Patilc0880a22013-03-22 21:49:07 -0700339static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700340{
341 int i = 0;
342
Avinash Patilc0880a22013-03-22 21:49:07 -0700343 while (mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700344 i++;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -0700345 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700346 /* 50ms max wait */
Avinash Patil3e7a4ff2013-02-25 16:01:34 -0800347 if (i == 5000)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700348 break;
349 }
350
Avinash Patilc0880a22013-03-22 21:49:07 -0700351 return;
352}
353
Avinash Patilc4bc9802014-03-18 22:19:17 -0700354static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
355 u32 max_delay_loop_cnt)
356{
357 struct pcie_service_card *card = adapter->card;
358 u8 *buffer;
359 u32 sleep_cookie, count;
360
361 for (count = 0; count < max_delay_loop_cnt; count++) {
362 buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
363 sleep_cookie = *(u32 *)buffer;
364
365 if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530366 mwifiex_dbg(adapter, INFO,
367 "sleep cookie found at count %d\n", count);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700368 break;
369 }
370 usleep_range(20, 30);
371 }
372
373 if (count >= max_delay_loop_cnt)
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530374 mwifiex_dbg(adapter, INFO,
375 "max count reached while accessing sleep cookie\n");
Avinash Patilc4bc9802014-03-18 22:19:17 -0700376}
377
Avinash Patilc0880a22013-03-22 21:49:07 -0700378/* This function wakes up the card by reading fw_status register. */
379static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
380{
381 u32 fw_status;
382 struct pcie_service_card *card = adapter->card;
383 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
384
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530385 mwifiex_dbg(adapter, EVENT,
386 "event: Wakeup device...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700387
Avinash Patilc0880a22013-03-22 21:49:07 -0700388 if (reg->sleep_cookie)
389 mwifiex_pcie_dev_wakeup_delay(adapter);
390
391 /* Reading fw_status register will wakeup device */
392 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530393 mwifiex_dbg(adapter, ERROR,
394 "Reading fw_status register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700395 return -1;
396 }
397
Avinash Patilc0880a22013-03-22 21:49:07 -0700398 if (reg->sleep_cookie) {
399 mwifiex_pcie_dev_wakeup_delay(adapter);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530400 mwifiex_dbg(adapter, INFO,
401 "PCIE wakeup: Setting PS_STATE_AWAKE\n");
Avinash Patilc0880a22013-03-22 21:49:07 -0700402 adapter->ps_state = PS_STATE_AWAKE;
403 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700404
405 return 0;
406}
407
408/*
409 * This function is called after the card has woken up.
410 *
411 * The card configuration register is reset.
412 */
413static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
414{
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530415 mwifiex_dbg(adapter, CMD,
416 "cmd: Wakeup device completed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700417
418 return 0;
419}
420
421/*
422 * This function disables the host interrupt.
423 *
424 * The host interrupt mask is read, the disable bit is reset and
425 * written back to the card host interrupt mask register.
426 */
427static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
428{
429 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
430 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
431 0x00000000)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530432 mwifiex_dbg(adapter, ERROR,
433 "Disable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700434 return -1;
435 }
436 }
437
438 return 0;
439}
440
441/*
442 * This function enables the host interrupt.
443 *
444 * The host interrupt enable mask is written to the card
445 * host interrupt mask register.
446 */
447static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
448{
449 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
450 /* Simply write the mask to the register */
451 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
452 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530453 mwifiex_dbg(adapter, ERROR,
454 "Enable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700455 return -1;
456 }
457 }
458
459 return 0;
460}
461
462/*
Avinash Patil07324842013-02-08 18:18:07 -0800463 * This function initializes TX buffer ring descriptors
464 */
465static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
466{
467 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800468 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800469 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800470 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800471 int i;
472
473 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
474 card->tx_buf_list[i] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -0800475 if (reg->pfu_enabled) {
476 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
477 (sizeof(*desc2) * i);
478 desc2 = card->txbd_ring[i];
479 memset(desc2, 0, sizeof(*desc2));
480 } else {
481 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
482 (sizeof(*desc) * i);
483 desc = card->txbd_ring[i];
484 memset(desc, 0, sizeof(*desc));
485 }
Avinash Patil07324842013-02-08 18:18:07 -0800486 }
487
488 return 0;
489}
490
491/* This function initializes RX buffer ring descriptors. Each SKB is allocated
492 * here and after mapping PCI memory, its physical address is assigned to
493 * PCIE Rx buffer descriptor's physical address.
494 */
495static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
496{
497 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800498 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800499 struct sk_buff *skb;
500 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800501 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800502 dma_addr_t buf_pa;
503 int i;
504
505 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
506 /* Allocate skb here so that firmware can DMA data from it */
Avinash Patil62159942015-03-13 17:37:52 +0530507 skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
508 GFP_KERNEL | GFP_DMA);
Avinash Patil07324842013-02-08 18:18:07 -0800509 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530510 mwifiex_dbg(adapter, ERROR,
511 "Unable to allocate skb for RX ring.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800512 kfree(card->rxbd_ring_vbase);
513 return -ENOMEM;
514 }
515
516 if (mwifiex_map_pci_memory(adapter, skb,
517 MWIFIEX_RX_DATA_BUF_SIZE,
518 PCI_DMA_FROMDEVICE))
519 return -1;
520
Aaron Durbindbccc922014-02-07 16:25:50 -0800521 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800522
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530523 mwifiex_dbg(adapter, INFO,
524 "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
525 skb, skb->len, skb->data, (u32)buf_pa,
526 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800527
528 card->rx_buf_list[i] = skb;
Avinash Patilca8f2112013-02-08 18:18:09 -0800529 if (reg->pfu_enabled) {
530 card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
531 (sizeof(*desc2) * i);
532 desc2 = card->rxbd_ring[i];
533 desc2->paddr = buf_pa;
534 desc2->len = (u16)skb->len;
535 desc2->frag_len = (u16)skb->len;
536 desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
537 desc2->offset = 0;
538 } else {
539 card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
540 (sizeof(*desc) * i));
541 desc = card->rxbd_ring[i];
542 desc->paddr = buf_pa;
543 desc->len = (u16)skb->len;
544 desc->flags = 0;
545 }
Avinash Patil07324842013-02-08 18:18:07 -0800546 }
547
548 return 0;
549}
550
551/* This function initializes event buffer ring descriptors. Each SKB is
552 * allocated here and after mapping PCI memory, its physical address is assigned
553 * to PCIE Rx buffer descriptor's physical address
554 */
555static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
556{
557 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800558 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800559 struct sk_buff *skb;
560 dma_addr_t buf_pa;
561 int i;
562
563 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
564 /* Allocate skb here so that firmware can DMA data from it */
565 skb = dev_alloc_skb(MAX_EVENT_SIZE);
566 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530567 mwifiex_dbg(adapter, ERROR,
568 "Unable to allocate skb for EVENT buf.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800569 kfree(card->evtbd_ring_vbase);
570 return -ENOMEM;
571 }
572 skb_put(skb, MAX_EVENT_SIZE);
573
574 if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
575 PCI_DMA_FROMDEVICE))
576 return -1;
577
Aaron Durbindbccc922014-02-07 16:25:50 -0800578 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800579
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530580 mwifiex_dbg(adapter, EVENT,
581 "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
582 skb, skb->len, skb->data, (u32)buf_pa,
583 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800584
585 card->evt_buf_list[i] = skb;
586 card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
587 (sizeof(*desc) * i));
Avinash Patil07324842013-02-08 18:18:07 -0800588 desc = card->evtbd_ring[i];
589 desc->paddr = buf_pa;
590 desc->len = (u16)skb->len;
591 desc->flags = 0;
592 }
593
594 return 0;
595}
596
597/* This function cleans up TX buffer rings. If any of the buffer list has valid
598 * SKB address, associated SKB is freed.
599 */
600static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
601{
602 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800603 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800604 struct sk_buff *skb;
605 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800606 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800607 int i;
608
609 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800610 if (reg->pfu_enabled) {
611 desc2 = card->txbd_ring[i];
612 if (card->tx_buf_list[i]) {
613 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800614 mwifiex_unmap_pci_memory(adapter, skb,
615 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800616 dev_kfree_skb_any(skb);
617 }
618 memset(desc2, 0, sizeof(*desc2));
619 } else {
620 desc = card->txbd_ring[i];
621 if (card->tx_buf_list[i]) {
622 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800623 mwifiex_unmap_pci_memory(adapter, skb,
624 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800625 dev_kfree_skb_any(skb);
626 }
627 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800628 }
629 card->tx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800630 }
631
632 return;
633}
634
635/* This function cleans up RX buffer rings. If any of the buffer list has valid
636 * SKB address, associated SKB is freed.
637 */
638static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
639{
640 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800641 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800642 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800643 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800644 struct sk_buff *skb;
645 int i;
646
647 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800648 if (reg->pfu_enabled) {
649 desc2 = card->rxbd_ring[i];
650 if (card->rx_buf_list[i]) {
651 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800652 mwifiex_unmap_pci_memory(adapter, skb,
653 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800654 dev_kfree_skb_any(skb);
655 }
656 memset(desc2, 0, sizeof(*desc2));
657 } else {
658 desc = card->rxbd_ring[i];
659 if (card->rx_buf_list[i]) {
660 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800661 mwifiex_unmap_pci_memory(adapter, skb,
662 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800663 dev_kfree_skb_any(skb);
664 }
665 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800666 }
Avinash Patilca8f2112013-02-08 18:18:09 -0800667 card->rx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800668 }
669
670 return;
671}
672
673/* This function cleans up event buffer rings. If any of the buffer list has
674 * valid SKB address, associated SKB is freed.
675 */
676static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
677{
678 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800679 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800680 struct sk_buff *skb;
681 int i;
682
683 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
684 desc = card->evtbd_ring[i];
685 if (card->evt_buf_list[i]) {
686 skb = card->evt_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800687 mwifiex_unmap_pci_memory(adapter, skb,
688 PCI_DMA_FROMDEVICE);
Avinash Patil07324842013-02-08 18:18:07 -0800689 dev_kfree_skb_any(skb);
690 }
691 card->evt_buf_list[i] = NULL;
692 memset(desc, 0, sizeof(*desc));
693 }
694
695 return;
696}
697
698/* This function creates buffer descriptor ring for TX
Amitkumar Karward930fae2011-10-11 17:41:21 -0700699 */
700static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
701{
702 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800703 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700704
705 /*
706 * driver maintaines the write pointer and firmware maintaines the read
707 * pointer. The write pointer starts at 0 (zero) while the read pointer
708 * starts at zero with rollover bit set
709 */
710 card->txbd_wrptr = 0;
Avinash Patilca8f2112013-02-08 18:18:09 -0800711
712 if (reg->pfu_enabled)
713 card->txbd_rdptr = 0;
714 else
715 card->txbd_rdptr |= reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700716
717 /* allocate shared memory for the BD ring and divide the same in to
718 several descriptors */
Avinash Patilca8f2112013-02-08 18:18:09 -0800719 if (reg->pfu_enabled)
720 card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
721 MWIFIEX_MAX_TXRX_BD;
722 else
723 card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
724 MWIFIEX_MAX_TXRX_BD;
725
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530726 mwifiex_dbg(adapter, INFO,
727 "info: txbd_ring: Allocating %d bytes\n",
728 card->txbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800729 card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
730 card->txbd_ring_size,
731 &card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700732 if (!card->txbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530733 mwifiex_dbg(adapter, ERROR,
734 "allocate consistent memory (%d bytes) failed!\n",
735 card->txbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800736 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700737 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530738 mwifiex_dbg(adapter, DATA,
739 "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
740 card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
741 (u32)((u64)card->txbd_ring_pbase >> 32),
742 card->txbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700743
Avinash Patil07324842013-02-08 18:18:07 -0800744 return mwifiex_init_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700745}
746
747static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
748{
749 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800750 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700751
Avinash Patil07324842013-02-08 18:18:07 -0800752 mwifiex_cleanup_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700753
Avinash Patilfc331462013-01-03 21:21:30 -0800754 if (card->txbd_ring_vbase)
755 pci_free_consistent(card->dev, card->txbd_ring_size,
756 card->txbd_ring_vbase,
757 card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700758 card->txbd_ring_size = 0;
759 card->txbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800760 card->txbd_rdptr = 0 | reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700761 card->txbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800762 card->txbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700763
764 return 0;
765}
766
767/*
768 * This function creates buffer descriptor ring for RX
769 */
770static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
771{
772 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800773 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700774
775 /*
776 * driver maintaines the read pointer and firmware maintaines the write
777 * pointer. The write pointer starts at 0 (zero) while the read pointer
778 * starts at zero with rollover bit set
779 */
780 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800781 card->rxbd_rdptr = reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700782
Avinash Patilca8f2112013-02-08 18:18:09 -0800783 if (reg->pfu_enabled)
784 card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
785 MWIFIEX_MAX_TXRX_BD;
786 else
787 card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
788 MWIFIEX_MAX_TXRX_BD;
789
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530790 mwifiex_dbg(adapter, INFO,
791 "info: rxbd_ring: Allocating %d bytes\n",
792 card->rxbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800793 card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
794 card->rxbd_ring_size,
795 &card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700796 if (!card->rxbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530797 mwifiex_dbg(adapter, ERROR,
798 "allocate consistent memory (%d bytes) failed!\n",
799 card->rxbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800800 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700801 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700802
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530803 mwifiex_dbg(adapter, DATA,
804 "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
805 card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
806 (u32)((u64)card->rxbd_ring_pbase >> 32),
807 card->rxbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700808
Avinash Patil07324842013-02-08 18:18:07 -0800809 return mwifiex_init_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700810}
811
812/*
813 * This function deletes Buffer descriptor ring for RX
814 */
815static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
816{
817 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800818 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700819
Avinash Patil07324842013-02-08 18:18:07 -0800820 mwifiex_cleanup_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700821
Avinash Patilfc331462013-01-03 21:21:30 -0800822 if (card->rxbd_ring_vbase)
823 pci_free_consistent(card->dev, card->rxbd_ring_size,
824 card->rxbd_ring_vbase,
825 card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700826 card->rxbd_ring_size = 0;
827 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800828 card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700829 card->rxbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800830 card->rxbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700831
832 return 0;
833}
834
835/*
836 * This function creates buffer descriptor ring for Events
837 */
838static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
839{
840 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800841 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700842
843 /*
844 * driver maintaines the read pointer and firmware maintaines the write
845 * pointer. The write pointer starts at 0 (zero) while the read pointer
846 * starts at zero with rollover bit set
847 */
848 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800849 card->evtbd_rdptr = reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700850
Avinash Patile05dc3e2013-02-08 18:18:08 -0800851 card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
Avinash Patilca8f2112013-02-08 18:18:09 -0800852 MWIFIEX_MAX_EVT_BD;
853
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530854 mwifiex_dbg(adapter, INFO,
855 "info: evtbd_ring: Allocating %d bytes\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700856 card->evtbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800857 card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
858 card->evtbd_ring_size,
859 &card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700860 if (!card->evtbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530861 mwifiex_dbg(adapter, ERROR,
862 "allocate consistent memory (%d bytes) failed!\n",
863 card->evtbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800864 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700865 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700866
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530867 mwifiex_dbg(adapter, EVENT,
868 "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
869 card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
870 (u32)((u64)card->evtbd_ring_pbase >> 32),
871 card->evtbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700872
Avinash Patil07324842013-02-08 18:18:07 -0800873 return mwifiex_pcie_init_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700874}
875
876/*
877 * This function deletes Buffer descriptor ring for Events
878 */
879static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
880{
881 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800882 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700883
Avinash Patil07324842013-02-08 18:18:07 -0800884 mwifiex_cleanup_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700885
Avinash Patilfc331462013-01-03 21:21:30 -0800886 if (card->evtbd_ring_vbase)
887 pci_free_consistent(card->dev, card->evtbd_ring_size,
888 card->evtbd_ring_vbase,
889 card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700890 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800891 card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700892 card->evtbd_ring_size = 0;
893 card->evtbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800894 card->evtbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700895
896 return 0;
897}
898
899/*
900 * This function allocates a buffer for CMDRSP
901 */
902static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
903{
904 struct pcie_service_card *card = adapter->card;
905 struct sk_buff *skb;
906
907 /* Allocate memory for receiving command response data */
908 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
909 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530910 mwifiex_dbg(adapter, ERROR,
911 "Unable to allocate skb for command response data.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700912 return -ENOMEM;
913 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700914 skb_put(skb, MWIFIEX_UPLD_SIZE);
Avinash Patilfc331462013-01-03 21:21:30 -0800915 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
916 PCI_DMA_FROMDEVICE))
917 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700918
Avinash Patilfc331462013-01-03 21:21:30 -0800919 card->cmdrsp_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700920
921 return 0;
922}
923
924/*
925 * This function deletes a buffer for CMDRSP
926 */
927static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
928{
929 struct pcie_service_card *card;
930
931 if (!adapter)
932 return 0;
933
934 card = adapter->card;
935
Avinash Patilfc331462013-01-03 21:21:30 -0800936 if (card && card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800937 mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
938 PCI_DMA_FROMDEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700939 dev_kfree_skb_any(card->cmdrsp_buf);
Avinash Patilfc331462013-01-03 21:21:30 -0800940 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700941
Avinash Patilfc331462013-01-03 21:21:30 -0800942 if (card && card->cmd_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800943 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
944 PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -0800945 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700946 return 0;
947}
948
949/*
950 * This function allocates a buffer for sleep cookie
951 */
952static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
953{
Amitkumar Karward930fae2011-10-11 17:41:21 -0700954 struct pcie_service_card *card = adapter->card;
955
Avinash Patilfc331462013-01-03 21:21:30 -0800956 card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
957 &card->sleep_cookie_pbase);
958 if (!card->sleep_cookie_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530959 mwifiex_dbg(adapter, ERROR,
960 "pci_alloc_consistent failed!\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700961 return -ENOMEM;
962 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700963 /* Init val of Sleep Cookie */
Avinash Patilfc331462013-01-03 21:21:30 -0800964 *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700965
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530966 mwifiex_dbg(adapter, INFO,
967 "alloc_scook: sleep cookie=0x%x\n",
968 *((u32 *)card->sleep_cookie_vbase));
Amitkumar Karward930fae2011-10-11 17:41:21 -0700969
970 return 0;
971}
972
973/*
974 * This function deletes buffer for sleep cookie
975 */
976static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
977{
978 struct pcie_service_card *card;
979
980 if (!adapter)
981 return 0;
982
983 card = adapter->card;
984
Avinash Patilfc331462013-01-03 21:21:30 -0800985 if (card && card->sleep_cookie_vbase) {
986 pci_free_consistent(card->dev, sizeof(u32),
987 card->sleep_cookie_vbase,
988 card->sleep_cookie_pbase);
989 card->sleep_cookie_vbase = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700990 }
991
992 return 0;
993}
994
Avinash Patilfbd7e7a2013-01-03 21:21:31 -0800995/* This function flushes the TX buffer descriptor ring
996 * This function defined as handler is also called while cleaning TXRX
997 * during disconnect/ bss stop.
998 */
999static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
1000{
1001 struct pcie_service_card *card = adapter->card;
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001002
Avinash Patil48f4d912013-02-20 21:12:58 -08001003 if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001004 card->txbd_flush = 1;
1005 /* write pointer already set at last send
1006 * send dnld-rdy intr again, wait for completion.
1007 */
1008 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1009 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301010 mwifiex_dbg(adapter, ERROR,
1011 "failed to assert dnld-rdy interrupt.\n");
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001012 return -1;
1013 }
1014 }
1015 return 0;
1016}
1017
Amitkumar Karward930fae2011-10-11 17:41:21 -07001018/*
Avinash Patile7f767a2013-01-03 21:21:32 -08001019 * This function unmaps and frees downloaded data buffer
Amitkumar Karward930fae2011-10-11 17:41:21 -07001020 */
Avinash Patile7f767a2013-01-03 21:21:32 -08001021static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001022{
Avinash Patile7f767a2013-01-03 21:21:32 -08001023 struct sk_buff *skb;
Avinash Patilca8f2112013-02-08 18:18:09 -08001024 u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001025 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001026 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001027 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001028 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001029
1030 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1031 mwifiex_pm_wakeup_card(adapter);
1032
1033 /* Read the TX ring read pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001034 if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301035 mwifiex_dbg(adapter, ERROR,
1036 "SEND COMP: failed to read reg->tx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001037 return -1;
1038 }
1039
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301040 mwifiex_dbg(adapter, DATA,
1041 "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
1042 card->txbd_rdptr, rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001043
Avinash Patilca8f2112013-02-08 18:18:09 -08001044 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001045 /* free from previous txbd_rdptr to current txbd_rdptr */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001046 while (((card->txbd_rdptr & reg->tx_mask) !=
1047 (rdptr & reg->tx_mask)) ||
1048 ((card->txbd_rdptr & reg->tx_rollover_ind) !=
1049 (rdptr & reg->tx_rollover_ind))) {
Avinash Patilca8f2112013-02-08 18:18:09 -08001050 wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
1051 reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001052
1053 skb = card->tx_buf_list[wrdoneidx];
Aaron Durbindbccc922014-02-07 16:25:50 -08001054
Avinash Patile7f767a2013-01-03 21:21:32 -08001055 if (skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301056 mwifiex_dbg(adapter, DATA,
1057 "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
1058 skb, wrdoneidx);
Aaron Durbindbccc922014-02-07 16:25:50 -08001059 mwifiex_unmap_pci_memory(adapter, skb,
1060 PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001061
1062 unmap_count++;
1063
1064 if (card->txbd_flush)
1065 mwifiex_write_data_complete(adapter, skb, 0,
1066 -1);
1067 else
1068 mwifiex_write_data_complete(adapter, skb, 0, 0);
1069 }
1070
1071 card->tx_buf_list[wrdoneidx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001072
1073 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001074 desc2 = card->txbd_ring[wrdoneidx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001075 memset(desc2, 0, sizeof(*desc2));
1076 } else {
1077 desc = card->txbd_ring[wrdoneidx];
1078 memset(desc, 0, sizeof(*desc));
1079 }
1080 switch (card->dev->device) {
1081 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1082 card->txbd_rdptr++;
1083 break;
1084 case PCIE_DEVICE_ID_MARVELL_88W8897:
1085 card->txbd_rdptr += reg->ring_tx_start_ptr;
1086 break;
1087 }
1088
Avinash Patile7f767a2013-01-03 21:21:32 -08001089
Avinash Patildd04e6a2013-02-08 18:18:06 -08001090 if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
Avinash Patile7f767a2013-01-03 21:21:32 -08001091 card->txbd_rdptr = ((card->txbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001092 reg->tx_rollover_ind) ^
1093 reg->tx_rollover_ind);
Avinash Patile7f767a2013-01-03 21:21:32 -08001094 }
1095
1096 if (unmap_count)
1097 adapter->data_sent = false;
1098
1099 if (card->txbd_flush) {
Avinash Patil3d482032013-02-15 21:37:54 -08001100 if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
Avinash Patile7f767a2013-01-03 21:21:32 -08001101 card->txbd_flush = 0;
1102 else
1103 mwifiex_clean_pcie_ring_buf(adapter);
1104 }
1105
1106 return 0;
1107}
1108
1109/* This function sends data buffer to device. First 4 bytes of payload
1110 * are filled with payload length and payload type. Then this payload
1111 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
1112 * Download ready interrupt to FW is deffered if Tx ring is not full and
1113 * additional payload can be accomodated.
Avinash Patil8d767dc2014-05-13 19:50:13 -07001114 * Caller must ensure tx_param parameter to this function is not NULL.
Avinash Patile7f767a2013-01-03 21:21:32 -08001115 */
1116static int
1117mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
1118 struct mwifiex_tx_param *tx_param)
1119{
1120 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001121 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001122 u32 wrindx, num_tx_buffs, rx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001123 int ret;
1124 dma_addr_t buf_pa;
Bing Zhao99310782013-03-04 16:27:55 -08001125 struct mwifiex_pcie_buf_desc *desc = NULL;
1126 struct mwifiex_pfu_buf_desc *desc2 = NULL;
Avinash Patile7f767a2013-01-03 21:21:32 -08001127 __le16 *tmp;
1128
1129 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301130 mwifiex_dbg(adapter, ERROR,
1131 "%s(): invalid parameter <%p, %#x>\n",
1132 __func__, skb->data, skb->len);
Avinash Patile7f767a2013-01-03 21:21:32 -08001133 return -1;
1134 }
1135
1136 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1137 mwifiex_pm_wakeup_card(adapter);
1138
Avinash Patilca8f2112013-02-08 18:18:09 -08001139 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301140 mwifiex_dbg(adapter, DATA,
1141 "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
Avinash Patile7f767a2013-01-03 21:21:32 -08001142 card->txbd_rdptr, card->txbd_wrptr);
1143 if (mwifiex_pcie_txbd_not_full(card)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001144 u8 *payload;
1145
1146 adapter->data_sent = true;
Avinash Patile7f767a2013-01-03 21:21:32 -08001147 payload = skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001148 tmp = (__le16 *)&payload[0];
1149 *tmp = cpu_to_le16((u16)skb->len);
1150 tmp = (__le16 *)&payload[2];
1151 *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
Avinash Patile7f767a2013-01-03 21:21:32 -08001152
Aaron Durbindbccc922014-02-07 16:25:50 -08001153 if (mwifiex_map_pci_memory(adapter, skb, skb->len,
Avinash Patile7f767a2013-01-03 21:21:32 -08001154 PCI_DMA_TODEVICE))
1155 return -1;
1156
Avinash Patilca8f2112013-02-08 18:18:09 -08001157 wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
Aaron Durbindbccc922014-02-07 16:25:50 -08001158 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile7f767a2013-01-03 21:21:32 -08001159 card->tx_buf_list[wrindx] = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001160
Avinash Patilca8f2112013-02-08 18:18:09 -08001161 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001162 desc2 = card->txbd_ring[wrindx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001163 desc2->paddr = buf_pa;
1164 desc2->len = (u16)skb->len;
1165 desc2->frag_len = (u16)skb->len;
1166 desc2->offset = 0;
1167 desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1168 MWIFIEX_BD_FLAG_LAST_DESC;
1169 } else {
1170 desc = card->txbd_ring[wrindx];
1171 desc->paddr = buf_pa;
1172 desc->len = (u16)skb->len;
1173 desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1174 MWIFIEX_BD_FLAG_LAST_DESC;
1175 }
1176
1177 switch (card->dev->device) {
1178 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1179 card->txbd_wrptr++;
1180 break;
1181 case PCIE_DEVICE_ID_MARVELL_88W8897:
1182 card->txbd_wrptr += reg->ring_tx_start_ptr;
1183 break;
1184 }
1185
1186 if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001187 card->txbd_wrptr = ((card->txbd_wrptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001188 reg->tx_rollover_ind) ^
1189 reg->tx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001190
Avinash Patilca8f2112013-02-08 18:18:09 -08001191 rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001192 /* Write the TX ring write pointer in to reg->tx_wrptr */
1193 if (mwifiex_write_reg(adapter, reg->tx_wrptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001194 card->txbd_wrptr | rx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301195 mwifiex_dbg(adapter, ERROR,
1196 "SEND DATA: failed to write reg->tx_wrptr\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001197 ret = -1;
1198 goto done_unmap;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001199 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001200 if ((mwifiex_pcie_txbd_not_full(card)) &&
1201 tx_param->next_pkt_len) {
1202 /* have more packets and TxBD still can hold more */
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301203 mwifiex_dbg(adapter, DATA,
1204 "SEND DATA: delay dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001205 adapter->data_sent = false;
1206 } else {
1207 /* Send the TX ready interrupt */
1208 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1209 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301210 mwifiex_dbg(adapter, ERROR,
1211 "SEND DATA: failed to assert dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001212 ret = -1;
1213 goto done_unmap;
1214 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001215 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301216 mwifiex_dbg(adapter, DATA,
1217 "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
1218 "%#x> and sent packet to firmware successfully\n",
1219 card->txbd_rdptr, card->txbd_wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001220 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301221 mwifiex_dbg(adapter, DATA,
1222 "info: TX Ring full, can't send packets to fw\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001223 adapter->data_sent = true;
1224 /* Send the TX ready interrupt */
1225 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1226 CPU_INTR_DNLD_RDY))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301227 mwifiex_dbg(adapter, ERROR,
1228 "SEND DATA: failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001229 return -EBUSY;
1230 }
1231
Avinash Patile7f767a2013-01-03 21:21:32 -08001232 return -EINPROGRESS;
1233done_unmap:
Aaron Durbindbccc922014-02-07 16:25:50 -08001234 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001235 card->tx_buf_list[wrindx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001236 if (reg->pfu_enabled)
1237 memset(desc2, 0, sizeof(*desc2));
1238 else
1239 memset(desc, 0, sizeof(*desc));
1240
Avinash Patile7f767a2013-01-03 21:21:32 -08001241 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001242}
1243
1244/*
1245 * This function handles received buffer ring and
1246 * dispatches packets to upper
1247 */
1248static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
1249{
1250 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001251 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001252 u32 wrptr, rd_index, tx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001253 dma_addr_t buf_pa;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001254 int ret = 0;
1255 struct sk_buff *skb_tmp = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001256 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001257 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001258
Avinash Patile7f767a2013-01-03 21:21:32 -08001259 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1260 mwifiex_pm_wakeup_card(adapter);
1261
Amitkumar Karward930fae2011-10-11 17:41:21 -07001262 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001263 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301264 mwifiex_dbg(adapter, ERROR,
1265 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001266 ret = -1;
1267 goto done;
1268 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001269 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001270
Avinash Patildd04e6a2013-02-08 18:18:06 -08001271 while (((wrptr & reg->rx_mask) !=
1272 (card->rxbd_rdptr & reg->rx_mask)) ||
1273 ((wrptr & reg->rx_rollover_ind) ==
1274 (card->rxbd_rdptr & reg->rx_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001275 struct sk_buff *skb_data;
1276 u16 rx_len;
Avinash Patile7f767a2013-01-03 21:21:32 -08001277 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001278
Avinash Patildd04e6a2013-02-08 18:18:06 -08001279 rd_index = card->rxbd_rdptr & reg->rx_mask;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001280 skb_data = card->rx_buf_list[rd_index];
1281
Amitkumar Karwarbb8e6a12014-02-18 15:41:55 -08001282 /* If skb allocation was failed earlier for Rx packet,
1283 * rx_buf_list[rd_index] would have been left with a NULL.
1284 */
1285 if (!skb_data)
1286 return -ENOMEM;
1287
Aaron Durbindbccc922014-02-07 16:25:50 -08001288 mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001289 card->rx_buf_list[rd_index] = NULL;
1290
Amitkumar Karward930fae2011-10-11 17:41:21 -07001291 /* Get data length from interface header -
Avinash Patile7f767a2013-01-03 21:21:32 -08001292 * first 2 bytes for len, next 2 bytes is for type
1293 */
1294 pkt_len = *((__le16 *)skb_data->data);
1295 rx_len = le16_to_cpu(pkt_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301296 if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
1297 rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301298 mwifiex_dbg(adapter, ERROR,
1299 "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
1300 rx_len, card->rxbd_rdptr, wrptr);
Avinash Patil42a028a2014-09-12 20:08:47 +05301301 dev_kfree_skb_any(skb_data);
1302 } else {
1303 skb_put(skb_data, rx_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301304 mwifiex_dbg(adapter, DATA,
1305 "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
1306 card->rxbd_rdptr, wrptr, rx_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301307 skb_pull(skb_data, INTF_HEADER_LEN);
Avinash Patil6e251172014-09-12 20:08:59 +05301308 if (adapter->rx_work_enabled) {
Avinash Patil6e251172014-09-12 20:08:59 +05301309 skb_queue_tail(&adapter->rx_data_q, skb_data);
Avinash Patil6e251172014-09-12 20:08:59 +05301310 adapter->data_received = true;
1311 atomic_inc(&adapter->rx_pending);
1312 } else {
1313 mwifiex_handle_rx_packet(adapter, skb_data);
1314 }
Avinash Patil42a028a2014-09-12 20:08:47 +05301315 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001316
Avinash Patil62159942015-03-13 17:37:52 +05301317 skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
1318 GFP_KERNEL | GFP_DMA);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001319 if (!skb_tmp) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301320 mwifiex_dbg(adapter, ERROR,
1321 "Unable to allocate skb.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001322 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001323 }
1324
Avinash Patile7f767a2013-01-03 21:21:32 -08001325 if (mwifiex_map_pci_memory(adapter, skb_tmp,
1326 MWIFIEX_RX_DATA_BUF_SIZE,
1327 PCI_DMA_FROMDEVICE))
1328 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001329
Aaron Durbindbccc922014-02-07 16:25:50 -08001330 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
Avinash Patile7f767a2013-01-03 21:21:32 -08001331
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301332 mwifiex_dbg(adapter, INFO,
1333 "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
1334 skb_tmp, rd_index);
Avinash Patile7f767a2013-01-03 21:21:32 -08001335 card->rx_buf_list[rd_index] = skb_tmp;
Avinash Patilca8f2112013-02-08 18:18:09 -08001336
1337 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001338 desc2 = card->rxbd_ring[rd_index];
Avinash Patilca8f2112013-02-08 18:18:09 -08001339 desc2->paddr = buf_pa;
1340 desc2->len = skb_tmp->len;
1341 desc2->frag_len = skb_tmp->len;
1342 desc2->offset = 0;
1343 desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
1344 } else {
1345 desc = card->rxbd_ring[rd_index];
1346 desc->paddr = buf_pa;
1347 desc->len = skb_tmp->len;
1348 desc->flags = 0;
1349 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001350
Avinash Patildd04e6a2013-02-08 18:18:06 -08001351 if ((++card->rxbd_rdptr & reg->rx_mask) ==
Amitkumar Karward930fae2011-10-11 17:41:21 -07001352 MWIFIEX_MAX_TXRX_BD) {
1353 card->rxbd_rdptr = ((card->rxbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001354 reg->rx_rollover_ind) ^
1355 reg->rx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001356 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301357 mwifiex_dbg(adapter, DATA,
1358 "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
1359 card->rxbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001360
Avinash Patilca8f2112013-02-08 18:18:09 -08001361 tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001362 /* Write the RX ring read pointer in to reg->rx_rdptr */
1363 if (mwifiex_write_reg(adapter, reg->rx_rdptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001364 card->rxbd_rdptr | tx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301365 mwifiex_dbg(adapter, DATA,
1366 "RECV DATA: failed to write reg->rx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001367 ret = -1;
1368 goto done;
1369 }
1370
1371 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001372 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301373 mwifiex_dbg(adapter, ERROR,
1374 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001375 ret = -1;
1376 goto done;
1377 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301378 mwifiex_dbg(adapter, DATA,
1379 "info: RECV DATA: Rcvd packet from fw successfully\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001380 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001381 }
1382
1383done:
Amitkumar Karward930fae2011-10-11 17:41:21 -07001384 return ret;
1385}
1386
1387/*
1388 * This function downloads the boot command to device
1389 */
1390static int
1391mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1392{
Avinash Patilfc331462013-01-03 21:21:30 -08001393 dma_addr_t buf_pa;
1394 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001395 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001396
Avinash Patilfc331462013-01-03 21:21:30 -08001397 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301398 mwifiex_dbg(adapter, ERROR,
1399 "Invalid parameter in %s <%p. len %d>\n",
1400 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001401 return -1;
1402 }
1403
Avinash Patilfc331462013-01-03 21:21:30 -08001404 if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
1405 return -1;
1406
Aaron Durbindbccc922014-02-07 16:25:50 -08001407 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patilfc331462013-01-03 21:21:30 -08001408
Avinash Patildd04e6a2013-02-08 18:18:06 -08001409 /* Write the lower 32bits of the physical address to low command
1410 * address scratch register
1411 */
1412 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301413 mwifiex_dbg(adapter, ERROR,
1414 "%s: failed to write download command to boot code.\n",
1415 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001416 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001417 return -1;
1418 }
1419
Avinash Patildd04e6a2013-02-08 18:18:06 -08001420 /* Write the upper 32bits of the physical address to high command
1421 * address scratch register
1422 */
1423 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001424 (u32)((u64)buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301425 mwifiex_dbg(adapter, ERROR,
1426 "%s: failed to write download command to boot code.\n",
1427 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001428 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001429 return -1;
1430 }
1431
Avinash Patildd04e6a2013-02-08 18:18:06 -08001432 /* Write the command length to cmd_size scratch register */
1433 if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301434 mwifiex_dbg(adapter, ERROR,
1435 "%s: failed to write command len to cmd_size scratch reg\n",
1436 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001437 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001438 return -1;
1439 }
1440
1441 /* Ring the door bell */
1442 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1443 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301444 mwifiex_dbg(adapter, ERROR,
1445 "%s: failed to assert door-bell intr\n", __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001446 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001447 return -1;
1448 }
1449
1450 return 0;
1451}
1452
Avinash Patilc6d1d872013-01-03 21:21:29 -08001453/* This function init rx port in firmware which in turn enables to receive data
1454 * from device before transmitting any packet.
1455 */
1456static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
1457{
1458 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001459 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001460 int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patilc6d1d872013-01-03 21:21:29 -08001461
Avinash Patildd04e6a2013-02-08 18:18:06 -08001462 /* Write the RX ring read pointer in to reg->rx_rdptr */
Avinash Patilca8f2112013-02-08 18:18:09 -08001463 if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
1464 tx_wrap)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301465 mwifiex_dbg(adapter, ERROR,
1466 "RECV DATA: failed to write reg->rx_rdptr\n");
Avinash Patilc6d1d872013-01-03 21:21:29 -08001467 return -1;
1468 }
1469 return 0;
1470}
1471
1472/* This function downloads commands to the device
Amitkumar Karward930fae2011-10-11 17:41:21 -07001473 */
1474static int
1475mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1476{
1477 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001478 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001479 int ret = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001480 dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
1481 u8 *payload = (u8 *)skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001482
1483 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301484 mwifiex_dbg(adapter, ERROR,
1485 "Invalid parameter in %s <%p, %#x>\n",
1486 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001487 return -1;
1488 }
1489
1490 /* Make sure a command response buffer is available */
1491 if (!card->cmdrsp_buf) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301492 mwifiex_dbg(adapter, ERROR,
1493 "No response buffer available, send command failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001494 return -EBUSY;
1495 }
1496
Avinash Patilfc331462013-01-03 21:21:30 -08001497 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1498 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001499
1500 adapter->cmd_sent = true;
Avinash Patilfc331462013-01-03 21:21:30 -08001501
1502 *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
1503 *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
1504
1505 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
1506 return -1;
1507
1508 card->cmd_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001509
1510 /* To send a command, the driver will:
1511 1. Write the 64bit physical address of the data buffer to
Avinash Patildd04e6a2013-02-08 18:18:06 -08001512 cmd response address low + cmd response address high
Amitkumar Karward930fae2011-10-11 17:41:21 -07001513 2. Ring the door bell (i.e. set the door bell interrupt)
1514
1515 In response to door bell interrupt, the firmware will perform
1516 the DMA of the command packet (first header to obtain the total
1517 length and then rest of the command).
1518 */
1519
1520 if (card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001521 cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001522 /* Write the lower 32bits of the cmdrsp buffer physical
1523 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001524 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
Avinash Patilfc331462013-01-03 21:21:30 -08001525 (u32)cmdrsp_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301526 mwifiex_dbg(adapter, ERROR,
1527 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001528 ret = -1;
1529 goto done;
1530 }
1531 /* Write the upper 32bits of the cmdrsp buffer physical
1532 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001533 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001534 (u32)((u64)cmdrsp_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301535 mwifiex_dbg(adapter, ERROR,
1536 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001537 ret = -1;
1538 goto done;
1539 }
1540 }
1541
Aaron Durbindbccc922014-02-07 16:25:50 -08001542 cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001543 /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
1544 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
1545 (u32)cmd_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301546 mwifiex_dbg(adapter, ERROR,
1547 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001548 ret = -1;
1549 goto done;
1550 }
Avinash Patildd04e6a2013-02-08 18:18:06 -08001551 /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
1552 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001553 (u32)((u64)cmd_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301554 mwifiex_dbg(adapter, ERROR,
1555 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001556 ret = -1;
1557 goto done;
1558 }
1559
Avinash Patildd04e6a2013-02-08 18:18:06 -08001560 /* Write the command length to reg->cmd_size */
1561 if (mwifiex_write_reg(adapter, reg->cmd_size,
1562 card->cmd_buf->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301563 mwifiex_dbg(adapter, ERROR,
1564 "Failed to write cmd len to reg->cmd_size\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001565 ret = -1;
1566 goto done;
1567 }
1568
1569 /* Ring the door bell */
1570 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1571 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301572 mwifiex_dbg(adapter, ERROR,
1573 "Failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001574 ret = -1;
1575 goto done;
1576 }
1577
1578done:
1579 if (ret)
1580 adapter->cmd_sent = false;
1581
1582 return 0;
1583}
1584
1585/*
1586 * This function handles command complete interrupt
1587 */
1588static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
1589{
1590 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001591 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001592 struct sk_buff *skb = card->cmdrsp_buf;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001593 int count = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001594 u16 rx_len;
1595 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001596
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301597 mwifiex_dbg(adapter, CMD,
1598 "info: Rx CMD Response\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001599
Aaron Durbindbccc922014-02-07 16:25:50 -08001600 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001601
Aaron Durbin189b3292014-02-07 16:25:51 -08001602 /* Unmap the command as a response has been received. */
1603 if (card->cmd_buf) {
1604 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1605 PCI_DMA_TODEVICE);
1606 card->cmd_buf = NULL;
1607 }
1608
Avinash Patilfc331462013-01-03 21:21:30 -08001609 pkt_len = *((__le16 *)skb->data);
1610 rx_len = le16_to_cpu(pkt_len);
1611 skb_trim(skb, rx_len);
1612 skb_pull(skb, INTF_HEADER_LEN);
1613
Amitkumar Karward930fae2011-10-11 17:41:21 -07001614 if (!adapter->curr_cmd) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001615 if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001616 mwifiex_process_sleep_confirm_resp(adapter, skb->data,
1617 skb->len);
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001618 mwifiex_pcie_enable_host_int(adapter);
1619 if (mwifiex_write_reg(adapter,
1620 PCIE_CPU_INT_EVENT,
1621 CPU_INTR_SLEEP_CFM_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301622 mwifiex_dbg(adapter, ERROR,
1623 "Write register failed\n");
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001624 return -1;
1625 }
Avinash Patilc4bc9802014-03-18 22:19:17 -07001626 mwifiex_delay_for_sleep_cookie(adapter,
1627 MWIFIEX_MAX_DELAY_COUNT);
Avinash Patil52301a82013-02-12 14:38:32 -08001628 while (reg->sleep_cookie && (count++ < 10) &&
1629 mwifiex_pcie_ok_to_access_hw(adapter))
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001630 usleep_range(50, 60);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001631 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301632 mwifiex_dbg(adapter, ERROR,
1633 "There is no command but got cmdrsp\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001634 }
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001635 memcpy(adapter->upld_buf, skb->data,
1636 min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
Avinash Patil0f49d642013-03-20 17:56:23 -07001637 skb_push(skb, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001638 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1639 PCI_DMA_FROMDEVICE))
1640 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001641 } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001642 adapter->curr_cmd->resp_skb = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001643 adapter->cmd_resp_received = true;
1644 /* Take the pointer and set it to CMD node and will
1645 return in the response complete callback */
1646 card->cmdrsp_buf = NULL;
1647
1648 /* Clear the cmd-rsp buffer address in scratch registers. This
1649 will prevent firmware from writing to the same response
1650 buffer again. */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001651 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301652 mwifiex_dbg(adapter, ERROR,
1653 "cmd_done: failed to clear cmd_rsp_addr_lo\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001654 return -1;
1655 }
1656 /* Write the upper 32bits of the cmdrsp buffer physical
1657 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001658 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301659 mwifiex_dbg(adapter, ERROR,
1660 "cmd_done: failed to clear cmd_rsp_addr_hi\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001661 return -1;
1662 }
1663 }
1664
1665 return 0;
1666}
1667
1668/*
1669 * Command Response processing complete handler
1670 */
1671static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
1672 struct sk_buff *skb)
1673{
1674 struct pcie_service_card *card = adapter->card;
1675
1676 if (skb) {
1677 card->cmdrsp_buf = skb;
1678 skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001679 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1680 PCI_DMA_FROMDEVICE))
1681 return -1;
1682 }
1683
Amitkumar Karward930fae2011-10-11 17:41:21 -07001684 return 0;
1685}
1686
1687/*
1688 * This function handles firmware event ready interrupt
1689 */
1690static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
1691{
1692 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001693 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001694 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1695 u32 wrptr, event;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001696 struct mwifiex_evt_buf_desc *desc;
Avinash Patilfc331462013-01-03 21:21:30 -08001697
1698 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1699 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001700
1701 if (adapter->event_received) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301702 mwifiex_dbg(adapter, EVENT,
1703 "info: Event being processed,\t"
1704 "do not process this interrupt just yet\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001705 return 0;
1706 }
1707
1708 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301709 mwifiex_dbg(adapter, ERROR,
1710 "info: Invalid read pointer...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001711 return -1;
1712 }
1713
1714 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001715 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301716 mwifiex_dbg(adapter, ERROR,
1717 "EventReady: failed to read reg->evt_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001718 return -1;
1719 }
1720
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301721 mwifiex_dbg(adapter, EVENT,
1722 "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
1723 card->evtbd_rdptr, wrptr);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001724 if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
1725 & MWIFIEX_EVTBD_MASK)) ||
Avinash Patildd04e6a2013-02-08 18:18:06 -08001726 ((wrptr & reg->evt_rollover_ind) ==
1727 (card->evtbd_rdptr & reg->evt_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001728 struct sk_buff *skb_cmd;
1729 __le16 data_len = 0;
1730 u16 evt_len;
1731
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301732 mwifiex_dbg(adapter, INFO,
1733 "info: Read Index: %d\n", rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001734 skb_cmd = card->evt_buf_list[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001735 mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001736
Amitkumar Karward930fae2011-10-11 17:41:21 -07001737 /* Take the pointer and set it to event pointer in adapter
1738 and will return back after event handling callback */
1739 card->evt_buf_list[rdptr] = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001740 desc = card->evtbd_ring[rdptr];
1741 memset(desc, 0, sizeof(*desc));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001742
1743 event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
1744 adapter->event_cause = event;
1745 /* The first 4bytes will be the event transfer header
1746 len is 2 bytes followed by type which is 2 bytes */
1747 memcpy(&data_len, skb_cmd->data, sizeof(__le16));
1748 evt_len = le16_to_cpu(data_len);
Zhaoyang Liu868093a2015-05-12 00:48:19 +05301749 skb_trim(skb_cmd, evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001750 skb_pull(skb_cmd, INTF_HEADER_LEN);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301751 mwifiex_dbg(adapter, EVENT,
1752 "info: Event length: %d\n", evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001753
1754 if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
1755 memcpy(adapter->event_body, skb_cmd->data +
1756 MWIFIEX_EVENT_HEADER_LEN, evt_len -
1757 MWIFIEX_EVENT_HEADER_LEN);
1758
1759 adapter->event_received = true;
1760 adapter->event_skb = skb_cmd;
1761
1762 /* Do not update the event read pointer here, wait till the
1763 buffer is released. This is just to make things simpler,
1764 we need to find a better method of managing these buffers.
1765 */
Avinash Patil2703a662014-09-12 20:08:49 +05301766 } else {
1767 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1768 CPU_INTR_EVENT_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301769 mwifiex_dbg(adapter, ERROR,
1770 "Write register failed\n");
Avinash Patil2703a662014-09-12 20:08:49 +05301771 return -1;
1772 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001773 }
1774
1775 return 0;
1776}
1777
1778/*
1779 * Event processing complete handler
1780 */
1781static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
1782 struct sk_buff *skb)
1783{
1784 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001785 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001786 int ret = 0;
1787 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1788 u32 wrptr;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001789 struct mwifiex_evt_buf_desc *desc;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001790
1791 if (!skb)
1792 return 0;
1793
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001794 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301795 mwifiex_dbg(adapter, ERROR,
1796 "event_complete: Invalid rdptr 0x%x\n",
1797 rdptr);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001798 return -EINVAL;
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001799 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001800
1801 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001802 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301803 mwifiex_dbg(adapter, ERROR,
1804 "event_complete: failed to read reg->evt_wrptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001805 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001806 }
1807
1808 if (!card->evt_buf_list[rdptr]) {
1809 skb_push(skb, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001810 if (mwifiex_map_pci_memory(adapter, skb,
1811 MAX_EVENT_SIZE,
1812 PCI_DMA_FROMDEVICE))
1813 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001814 card->evt_buf_list[rdptr] = skb;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001815 desc = card->evtbd_ring[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001816 desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile05dc3e2013-02-08 18:18:08 -08001817 desc->len = (u16)skb->len;
1818 desc->flags = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001819 skb = NULL;
1820 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301821 mwifiex_dbg(adapter, ERROR,
1822 "info: ERROR: buf still valid at index %d, <%p, %p>\n",
1823 rdptr, card->evt_buf_list[rdptr], skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001824 }
1825
1826 if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
1827 card->evtbd_rdptr = ((card->evtbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001828 reg->evt_rollover_ind) ^
1829 reg->evt_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001830 }
1831
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301832 mwifiex_dbg(adapter, EVENT,
1833 "info: Updated <Rd: 0x%x, Wr: 0x%x>",
1834 card->evtbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001835
Avinash Patildd04e6a2013-02-08 18:18:06 -08001836 /* Write the event ring read pointer in to reg->evt_rdptr */
1837 if (mwifiex_write_reg(adapter, reg->evt_rdptr,
1838 card->evtbd_rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301839 mwifiex_dbg(adapter, ERROR,
1840 "event_complete: failed to read reg->evt_rdptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001841 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001842 }
1843
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301844 mwifiex_dbg(adapter, EVENT,
1845 "info: Check Events Again\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001846 ret = mwifiex_pcie_process_event_ready(adapter);
1847
1848 return ret;
1849}
1850
1851/*
1852 * This function downloads the firmware to the card.
1853 *
1854 * Firmware is downloaded to the card in blocks. Every block download
1855 * is tested for CRC errors, and retried a number of times before
1856 * returning failure.
1857 */
1858static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
1859 struct mwifiex_fw_image *fw)
1860{
1861 int ret;
1862 u8 *firmware = fw->fw_buf;
1863 u32 firmware_len = fw->fw_len;
1864 u32 offset = 0;
1865 struct sk_buff *skb;
1866 u32 txlen, tx_blocks = 0, tries, len;
1867 u32 block_retry_cnt = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001868 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001869 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001870
1871 if (!firmware || !firmware_len) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301872 mwifiex_dbg(adapter, ERROR,
1873 "No firmware image found! Terminating download\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001874 return -1;
1875 }
1876
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301877 mwifiex_dbg(adapter, INFO,
1878 "info: Downloading FW image (%d bytes)\n",
1879 firmware_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001880
1881 if (mwifiex_pcie_disable_host_int(adapter)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301882 mwifiex_dbg(adapter, ERROR,
1883 "%s: Disabling interrupts failed.\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001884 return -1;
1885 }
1886
1887 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
1888 if (!skb) {
1889 ret = -ENOMEM;
1890 goto done;
1891 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001892
1893 /* Perform firmware data transfer */
1894 do {
1895 u32 ireg_intr = 0;
1896
1897 /* More data? */
1898 if (offset >= firmware_len)
1899 break;
1900
1901 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08001902 ret = mwifiex_read_reg(adapter, reg->cmd_size,
Amitkumar Karward930fae2011-10-11 17:41:21 -07001903 &len);
1904 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301905 mwifiex_dbg(adapter, FATAL,
1906 "Failed reading len from boot code\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001907 goto done;
1908 }
1909 if (len)
1910 break;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001911 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001912 }
1913
1914 if (!len) {
1915 break;
1916 } else if (len > MWIFIEX_UPLD_SIZE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301917 mwifiex_dbg(adapter, ERROR,
1918 "FW download failure @ %d, invalid length %d\n",
1919 offset, len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001920 ret = -1;
1921 goto done;
1922 }
1923
1924 txlen = len;
1925
1926 if (len & BIT(0)) {
1927 block_retry_cnt++;
1928 if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301929 mwifiex_dbg(adapter, ERROR,
1930 "FW download failure @ %d, over max\t"
1931 "retry count\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001932 ret = -1;
1933 goto done;
1934 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301935 mwifiex_dbg(adapter, ERROR,
1936 "FW CRC error indicated by the\t"
1937 "helper: len = 0x%04X, txlen = %d\n",
1938 len, txlen);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001939 len &= ~BIT(0);
1940 /* Setting this to 0 to resend from same offset */
1941 txlen = 0;
1942 } else {
1943 block_retry_cnt = 0;
1944 /* Set blocksize to transfer - checking for
1945 last block */
1946 if (firmware_len - offset < txlen)
1947 txlen = firmware_len - offset;
1948
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301949 mwifiex_dbg(adapter, INFO, ".");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001950
Avinash Patildd04e6a2013-02-08 18:18:06 -08001951 tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
1952 card->pcie.blksz_fw_dl;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001953
1954 /* Copy payload to buffer */
1955 memmove(skb->data, &firmware[offset], txlen);
1956 }
1957
1958 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001959 skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001960
1961 /* Send the boot command to device */
1962 if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301963 mwifiex_dbg(adapter, ERROR,
1964 "Failed to send firmware download command\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001965 ret = -1;
1966 goto done;
1967 }
Avinash Patilfc331462013-01-03 21:21:30 -08001968
Amitkumar Karward930fae2011-10-11 17:41:21 -07001969 /* Wait for the command done interrupt */
1970 do {
1971 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
1972 &ireg_intr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301973 mwifiex_dbg(adapter, ERROR,
1974 "%s: Failed to read\t"
1975 "interrupt status during fw dnld.\n",
1976 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001977 mwifiex_unmap_pci_memory(adapter, skb,
1978 PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001979 ret = -1;
1980 goto done;
1981 }
1982 } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
1983 CPU_INTR_DOOR_BELL);
Avinash Patilfc331462013-01-03 21:21:30 -08001984
Aaron Durbindbccc922014-02-07 16:25:50 -08001985 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001986
Amitkumar Karward930fae2011-10-11 17:41:21 -07001987 offset += txlen;
1988 } while (true);
1989
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301990 mwifiex_dbg(adapter, MSG,
1991 "info: FW download over, size %d bytes\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001992
1993 ret = 0;
1994
1995done:
1996 dev_kfree_skb_any(skb);
1997 return ret;
1998}
1999
2000/*
2001 * This function checks the firmware status in card.
2002 *
2003 * The winner interface is also determined by this function.
2004 */
2005static int
2006mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
2007{
2008 int ret = 0;
2009 u32 firmware_stat, winner_status;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002010 struct pcie_service_card *card = adapter->card;
2011 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002012 u32 tries;
2013
2014 /* Mask spurios interrupts */
2015 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002016 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302017 mwifiex_dbg(adapter, ERROR,
2018 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002019 return -1;
2020 }
2021
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302022 mwifiex_dbg(adapter, INFO,
2023 "Setting driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002024 if (mwifiex_write_reg(adapter, reg->drv_rdy,
2025 FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302026 mwifiex_dbg(adapter, ERROR,
2027 "Failed to write driver ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002028 return -1;
2029 }
2030
2031 /* Wait for firmware initialization event */
2032 for (tries = 0; tries < poll_num; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002033 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002034 &firmware_stat))
2035 ret = -1;
2036 else
2037 ret = 0;
2038 if (ret)
2039 continue;
2040 if (firmware_stat == FIRMWARE_READY_PCIE) {
2041 ret = 0;
2042 break;
2043 } else {
Amitkumar Karwara76b20e2013-07-22 19:17:53 -07002044 msleep(100);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002045 ret = -1;
2046 }
2047 }
2048
2049 if (ret) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002050 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002051 &winner_status))
2052 ret = -1;
2053 else if (!winner_status) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302054 mwifiex_dbg(adapter, INFO,
2055 "PCI-E is the winner\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002056 adapter->winner = 1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002057 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302058 mwifiex_dbg(adapter, ERROR,
2059 "PCI-E is not the winner <%#x,%d>, exit dnld\n",
2060 ret, adapter->winner);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002061 }
2062 }
2063
2064 return ret;
2065}
2066
2067/*
2068 * This function reads the interrupt status from card.
2069 */
2070static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
2071{
2072 u32 pcie_ireg;
2073 unsigned long flags;
2074
2075 if (!mwifiex_pcie_ok_to_access_hw(adapter))
2076 return;
2077
2078 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302079 mwifiex_dbg(adapter, ERROR, "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002080 return;
2081 }
2082
2083 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2084
2085 mwifiex_pcie_disable_host_int(adapter);
2086
2087 /* Clear the pending interrupts */
2088 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
2089 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302090 mwifiex_dbg(adapter, ERROR,
2091 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002092 return;
2093 }
2094 spin_lock_irqsave(&adapter->int_lock, flags);
2095 adapter->int_status |= pcie_ireg;
2096 spin_unlock_irqrestore(&adapter->int_lock, flags);
2097
Amitkumar Karwar1c975602014-02-18 15:41:56 -08002098 if (!adapter->pps_uapsd_mode &&
2099 adapter->ps_state == PS_STATE_SLEEP &&
2100 mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07002101 /* Potentially for PCIe we could get other
2102 * interrupts like shared. Don't change power
2103 * state until cookie is set */
Avinash Patilc24d9922013-03-22 21:49:06 -07002104 adapter->ps_state = PS_STATE_AWAKE;
2105 adapter->pm_wakeup_fw_try = false;
Amitkumar Karwar46361872014-12-31 02:36:41 -08002106 del_timer(&adapter->wakeup_timer);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002107 }
2108 }
2109}
2110
2111/*
2112 * Interrupt handler for PCIe root port
2113 *
2114 * This function reads the interrupt status from firmware and assigns
2115 * the main process in workqueue which will handle the interrupt.
2116 */
2117static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
2118{
2119 struct pci_dev *pdev = (struct pci_dev *)context;
2120 struct pcie_service_card *card;
2121 struct mwifiex_adapter *adapter;
2122
2123 if (!pdev) {
2124 pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev);
2125 goto exit;
2126 }
2127
Jingoo Hanb2a31202013-09-09 14:26:51 +09002128 card = pci_get_drvdata(pdev);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002129 if (!card || !card->adapter) {
2130 pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002131 card ? card->adapter : NULL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002132 goto exit;
2133 }
2134 adapter = card->adapter;
2135
2136 if (adapter->surprise_removed)
2137 goto exit;
2138
2139 mwifiex_interrupt_status(adapter);
Shengzhen Lib2713f62015-03-13 17:37:54 +05302140 mwifiex_queue_main_work(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002141
2142exit:
2143 return IRQ_HANDLED;
2144}
2145
2146/*
2147 * This function checks the current interrupt status.
2148 *
2149 * The following interrupts are checked and handled by this function -
2150 * - Data sent
2151 * - Command sent
2152 * - Command received
2153 * - Packets received
2154 * - Events received
2155 *
2156 * In case of Rx packets received, the packets are uploaded from card to
2157 * host and processed accordingly.
2158 */
2159static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
2160{
2161 int ret;
Avinash Patil659c4782013-01-03 21:21:28 -08002162 u32 pcie_ireg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002163 unsigned long flags;
2164
2165 spin_lock_irqsave(&adapter->int_lock, flags);
2166 /* Clear out unused interrupts */
Avinash Patil659c4782013-01-03 21:21:28 -08002167 pcie_ireg = adapter->int_status;
2168 adapter->int_status = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002169 spin_unlock_irqrestore(&adapter->int_lock, flags);
2170
Avinash Patil659c4782013-01-03 21:21:28 -08002171 while (pcie_ireg & HOST_INTR_MASK) {
2172 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2173 pcie_ireg &= ~HOST_INTR_DNLD_DONE;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302174 mwifiex_dbg(adapter, INTR,
2175 "info: TX DNLD Done\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08002176 ret = mwifiex_pcie_send_data_complete(adapter);
2177 if (ret)
2178 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002179 }
Avinash Patil659c4782013-01-03 21:21:28 -08002180 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2181 pcie_ireg &= ~HOST_INTR_UPLD_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302182 mwifiex_dbg(adapter, INTR,
2183 "info: Rx DATA\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002184 ret = mwifiex_pcie_process_recv_data(adapter);
2185 if (ret)
2186 return ret;
2187 }
Avinash Patil659c4782013-01-03 21:21:28 -08002188 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2189 pcie_ireg &= ~HOST_INTR_EVENT_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302190 mwifiex_dbg(adapter, INTR,
2191 "info: Rx EVENT\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002192 ret = mwifiex_pcie_process_event_ready(adapter);
2193 if (ret)
2194 return ret;
2195 }
2196
Avinash Patil659c4782013-01-03 21:21:28 -08002197 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2198 pcie_ireg &= ~HOST_INTR_CMD_DONE;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002199 if (adapter->cmd_sent) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302200 mwifiex_dbg(adapter, INTR,
2201 "info: CMD sent Interrupt\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002202 adapter->cmd_sent = false;
2203 }
2204 /* Handle command response */
2205 ret = mwifiex_pcie_process_cmd_complete(adapter);
2206 if (ret)
2207 return ret;
2208 }
2209
2210 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2211 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2212 &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302213 mwifiex_dbg(adapter, ERROR,
2214 "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002215 return -1;
2216 }
2217
2218 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2219 if (mwifiex_write_reg(adapter,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002220 PCIE_HOST_INT_STATUS,
2221 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302222 mwifiex_dbg(adapter, ERROR,
2223 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002224 return -1;
2225 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002226 }
2227
2228 }
2229 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302230 mwifiex_dbg(adapter, INTR,
2231 "info: cmd_sent=%d data_sent=%d\n",
2232 adapter->cmd_sent, adapter->data_sent);
Avinash Patilb2fda1f2013-03-22 21:49:05 -07002233 if (adapter->ps_state != PS_STATE_SLEEP)
2234 mwifiex_pcie_enable_host_int(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002235
2236 return 0;
2237}
2238
2239/*
2240 * This function downloads data from driver to card.
2241 *
2242 * Both commands and data packets are transferred to the card by this
2243 * function.
2244 *
2245 * This function adds the PCIE specific header to the front of the buffer
2246 * before transferring. The header contains the length of the packet and
2247 * the type. The firmware handles the packets based upon this set type.
2248 */
2249static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
2250 struct sk_buff *skb,
2251 struct mwifiex_tx_param *tx_param)
2252{
Dan Carpenterfa161cb2011-11-07 19:31:45 -08002253 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302254 mwifiex_dbg(adapter, ERROR,
2255 "Passed NULL skb to %s\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002256 return -1;
2257 }
2258
2259 if (type == MWIFIEX_TYPE_DATA)
Avinash Patile7f767a2013-01-03 21:21:32 -08002260 return mwifiex_pcie_send_data(adapter, skb, tx_param);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002261 else if (type == MWIFIEX_TYPE_CMD)
2262 return mwifiex_pcie_send_cmd(adapter, skb);
2263
2264 return 0;
2265}
2266
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002267/* This function read/write firmware */
2268static enum rdwr_status
2269mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
2270{
2271 int ret, tries;
2272 u8 ctrl_data;
2273 struct pcie_service_card *card = adapter->card;
2274 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2275
2276 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
2277 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302278 mwifiex_dbg(adapter, ERROR,
2279 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002280 return RDWR_STATUS_FAILURE;
2281 }
2282
2283 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2284 mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
2285 if (ctrl_data == FW_DUMP_DONE)
2286 return RDWR_STATUS_SUCCESS;
2287 if (doneflag && ctrl_data == doneflag)
2288 return RDWR_STATUS_DONE;
2289 if (ctrl_data != FW_DUMP_HOST_READY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302290 mwifiex_dbg(adapter, WARN,
2291 "The ctrl reg was changed, re-try again!\n");
Amitkumar Karwar24716872014-09-18 08:04:01 -04002292 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
2293 FW_DUMP_HOST_READY);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002294 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302295 mwifiex_dbg(adapter, ERROR,
2296 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002297 return RDWR_STATUS_FAILURE;
2298 }
2299 }
2300 usleep_range(100, 200);
2301 }
2302
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302303 mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002304 return RDWR_STATUS_FAILURE;
2305}
2306
2307/* This function dump firmware memory to file */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002308static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002309{
2310 struct pcie_service_card *card = adapter->card;
2311 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2312 unsigned int reg, reg_start, reg_end;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002313 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
2314 enum rdwr_status stat;
2315 u32 memory_size;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002316 int ret;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002317
Avinash Patilb4e8aeb2015-02-11 23:12:26 +05302318 if (!card->pcie.can_dump_fw)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002319 return;
2320
2321 for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
2322 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
2323
2324 if (entry->mem_ptr) {
2325 vfree(entry->mem_ptr);
2326 entry->mem_ptr = NULL;
2327 }
2328 entry->mem_size = 0;
2329 }
2330
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302331 mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002332
2333 /* Read the number of the memories which will dump */
2334 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2335 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002336 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002337
2338 reg = creg->fw_dump_start;
2339 mwifiex_read_reg_byte(adapter, reg, &dump_num);
2340
2341 /* Read the length of every memory which will dump */
2342 for (idx = 0; idx < dump_num; idx++) {
2343 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
2344
2345 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2346 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002347 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002348
2349 memory_size = 0;
2350 reg = creg->fw_dump_start;
2351 for (i = 0; i < 4; i++) {
2352 mwifiex_read_reg_byte(adapter, reg, &read_reg);
2353 memory_size |= (read_reg << (i * 8));
2354 reg++;
2355 }
2356
2357 if (memory_size == 0) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302358 mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002359 ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
2360 FW_DUMP_READ_DONE);
2361 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302362 mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002363 return;
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002364 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002365 break;
2366 }
2367
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302368 mwifiex_dbg(adapter, DUMP,
2369 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002370 entry->mem_ptr = vmalloc(memory_size + 1);
2371 entry->mem_size = memory_size;
2372 if (!entry->mem_ptr) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302373 mwifiex_dbg(adapter, ERROR,
2374 "Vmalloc %s failed\n", entry->mem_name);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002375 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002376 }
2377 dbg_ptr = entry->mem_ptr;
2378 end_ptr = dbg_ptr + memory_size;
2379
2380 doneflag = entry->done_flag;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302381 mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
2382 entry->mem_name);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002383
2384 do {
2385 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2386 if (RDWR_STATUS_FAILURE == stat)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002387 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002388
2389 reg_start = creg->fw_dump_start;
2390 reg_end = creg->fw_dump_end;
2391 for (reg = reg_start; reg <= reg_end; reg++) {
2392 mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
Amitkumar Karwar24716872014-09-18 08:04:01 -04002393 if (dbg_ptr < end_ptr) {
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002394 dbg_ptr++;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002395 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302396 mwifiex_dbg(adapter, ERROR,
2397 "Allocated buf not enough\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002398 return;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002399 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002400 }
2401
2402 if (stat != RDWR_STATUS_DONE)
2403 continue;
2404
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302405 mwifiex_dbg(adapter, DUMP,
2406 "%s done: size=0x%tx\n",
2407 entry->mem_name, dbg_ptr - entry->mem_ptr);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002408 break;
2409 } while (true);
2410 }
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002411 mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002412}
2413
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002414static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
2415{
2416 mwifiex_drv_info_dump(adapter);
2417 mwifiex_pcie_fw_dump(adapter);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002418 mwifiex_upload_device_dump(adapter);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002419}
2420
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002421static unsigned long iface_work_flags;
2422static struct mwifiex_adapter *save_adapter;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002423static void mwifiex_pcie_work(struct work_struct *work)
2424{
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002425 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002426 &iface_work_flags))
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002427 mwifiex_pcie_device_dump_work(save_adapter);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002428}
2429
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002430static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002431/* This function dumps FW information */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002432static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002433{
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002434 save_adapter = adapter;
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002435 if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002436 return;
2437
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002438 set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002439
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002440 schedule_work(&pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002441}
2442
Amitkumar Karward930fae2011-10-11 17:41:21 -07002443/*
2444 * This function initializes the PCI-E host memory space, WCB rings, etc.
2445 *
2446 * The following initializations steps are followed -
2447 * - Allocate TXBD ring buffers
2448 * - Allocate RXBD ring buffers
2449 * - Allocate event BD ring buffers
2450 * - Allocate command response ring buffer
2451 * - Allocate sleep cookie buffer
2452 */
2453static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
2454{
2455 struct pcie_service_card *card = adapter->card;
2456 int ret;
2457 struct pci_dev *pdev = card->dev;
Avinash Patil52301a82013-02-12 14:38:32 -08002458 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002459
2460 pci_set_drvdata(pdev, card);
2461
2462 ret = pci_enable_device(pdev);
2463 if (ret)
2464 goto err_enable_dev;
2465
2466 pci_set_master(pdev);
2467
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302468 mwifiex_dbg(adapter, INFO,
2469 "try set_consistent_dma_mask(32)\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002470 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
2471 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302472 mwifiex_dbg(adapter, ERROR,
2473 "set_dma_mask(32) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002474 goto err_set_dma_mask;
2475 }
2476
2477 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
2478 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302479 mwifiex_dbg(adapter, ERROR,
2480 "set_consistent_dma_mask(64) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002481 goto err_set_dma_mask;
2482 }
2483
2484 ret = pci_request_region(pdev, 0, DRV_NAME);
2485 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302486 mwifiex_dbg(adapter, ERROR,
2487 "req_reg(0) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002488 goto err_req_region0;
2489 }
2490 card->pci_mmap = pci_iomap(pdev, 0, 0);
2491 if (!card->pci_mmap) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302492 mwifiex_dbg(adapter, ERROR, "iomap(0) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002493 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002494 goto err_iomap0;
2495 }
2496 ret = pci_request_region(pdev, 2, DRV_NAME);
2497 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302498 mwifiex_dbg(adapter, ERROR, "req_reg(2) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002499 goto err_req_region2;
2500 }
2501 card->pci_mmap1 = pci_iomap(pdev, 2, 0);
2502 if (!card->pci_mmap1) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302503 mwifiex_dbg(adapter, ERROR,
2504 "iomap(2) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002505 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002506 goto err_iomap2;
2507 }
2508
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302509 mwifiex_dbg(adapter, INFO,
2510 "PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
2511 card->pci_mmap, card->pci_mmap1);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002512
2513 card->cmdrsp_buf = NULL;
2514 ret = mwifiex_pcie_create_txbd_ring(adapter);
2515 if (ret)
2516 goto err_cre_txbd;
2517 ret = mwifiex_pcie_create_rxbd_ring(adapter);
2518 if (ret)
2519 goto err_cre_rxbd;
2520 ret = mwifiex_pcie_create_evtbd_ring(adapter);
2521 if (ret)
2522 goto err_cre_evtbd;
2523 ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
2524 if (ret)
2525 goto err_alloc_cmdbuf;
Avinash Patil52301a82013-02-12 14:38:32 -08002526 if (reg->sleep_cookie) {
2527 ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
2528 if (ret)
2529 goto err_alloc_cookie;
2530 } else {
2531 card->sleep_cookie_vbase = NULL;
2532 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002533 return ret;
2534
2535err_alloc_cookie:
2536 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2537err_alloc_cmdbuf:
2538 mwifiex_pcie_delete_evtbd_ring(adapter);
2539err_cre_evtbd:
2540 mwifiex_pcie_delete_rxbd_ring(adapter);
2541err_cre_rxbd:
2542 mwifiex_pcie_delete_txbd_ring(adapter);
2543err_cre_txbd:
2544 pci_iounmap(pdev, card->pci_mmap1);
2545err_iomap2:
2546 pci_release_region(pdev, 2);
2547err_req_region2:
2548 pci_iounmap(pdev, card->pci_mmap);
2549err_iomap0:
2550 pci_release_region(pdev, 0);
2551err_req_region0:
2552err_set_dma_mask:
2553 pci_disable_device(pdev);
2554err_enable_dev:
2555 pci_set_drvdata(pdev, NULL);
2556 return ret;
2557}
2558
2559/*
2560 * This function cleans up the allocated card buffers.
2561 *
2562 * The following are freed by this function -
2563 * - TXBD ring buffers
2564 * - RXBD ring buffers
2565 * - Event BD ring buffers
2566 * - Command response ring buffer
2567 * - Sleep cookie buffer
2568 */
2569static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
2570{
2571 struct pcie_service_card *card = adapter->card;
2572 struct pci_dev *pdev = card->dev;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002573 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002574
Amitkumar Karward930fae2011-10-11 17:41:21 -07002575 if (user_rmmod) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302576 mwifiex_dbg(adapter, INFO,
2577 "Clearing driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002578 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302579 mwifiex_dbg(adapter, ERROR,
2580 "Failed to write driver not-ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002581 }
2582
2583 if (pdev) {
2584 pci_iounmap(pdev, card->pci_mmap);
2585 pci_iounmap(pdev, card->pci_mmap1);
Yogesh Ashok Powar5b0d9b22013-04-23 16:49:48 -07002586 pci_disable_device(pdev);
Yogesh Ashok Powarc380aaf2013-04-23 16:49:47 -07002587 pci_release_region(pdev, 2);
2588 pci_release_region(pdev, 0);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002589 pci_set_drvdata(pdev, NULL);
2590 }
Amitkumar Karwar3c59e322013-11-14 19:10:41 -08002591 kfree(card);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002592}
2593
2594/*
2595 * This function registers the PCIE device.
2596 *
2597 * PCIE IRQ is claimed, block size is set and driver data is initialized.
2598 */
2599static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
2600{
2601 int ret;
2602 struct pcie_service_card *card = adapter->card;
2603 struct pci_dev *pdev = card->dev;
2604
2605 /* save adapter pointer in card */
2606 card->adapter = adapter;
2607
2608 ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
2609 "MRVL_PCIE", pdev);
2610 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302611 mwifiex_dbg(adapter, ERROR,
2612 "request_irq failed: ret=%d\n", ret);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002613 adapter->card = NULL;
2614 return -1;
2615 }
2616
2617 adapter->dev = &pdev->dev;
Amitkumar Karwar828cf222014-02-27 19:35:13 -08002618 adapter->tx_buf_size = card->pcie.tx_buf_size;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002619 adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
2620 adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
Avinash Patildd04e6a2013-02-08 18:18:06 -08002621 strcpy(adapter->fw_name, card->pcie.firmware);
Avinash Patil1fe192d2015-01-23 17:09:19 +05302622 adapter->ext_scan = card->pcie.can_ext_scan;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002623
2624 return 0;
2625}
2626
2627/*
2628 * This function unregisters the PCIE device.
2629 *
2630 * The PCIE IRQ is released, the function is disabled and driver
2631 * data is set to null.
2632 */
2633static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
2634{
2635 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -08002636 const struct mwifiex_pcie_card_reg *reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002637
2638 if (card) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302639 mwifiex_dbg(adapter, INFO,
2640 "%s(): calling free_irq()\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002641 free_irq(card->dev->irq, card->dev);
Avinash Patilfc331462013-01-03 21:21:30 -08002642
Avinash Patil52301a82013-02-12 14:38:32 -08002643 reg = card->pcie.reg;
2644 if (reg->sleep_cookie)
2645 mwifiex_pcie_delete_sleep_cookie_buf(adapter);
2646
Avinash Patilfc331462013-01-03 21:21:30 -08002647 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2648 mwifiex_pcie_delete_evtbd_ring(adapter);
2649 mwifiex_pcie_delete_rxbd_ring(adapter);
2650 mwifiex_pcie_delete_txbd_ring(adapter);
2651 card->cmdrsp_buf = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002652 }
2653}
2654
2655static struct mwifiex_if_ops pcie_ops = {
2656 .init_if = mwifiex_pcie_init,
2657 .cleanup_if = mwifiex_pcie_cleanup,
2658 .check_fw_status = mwifiex_check_fw_status,
2659 .prog_fw = mwifiex_prog_fw_w_helper,
2660 .register_dev = mwifiex_register_dev,
2661 .unregister_dev = mwifiex_unregister_dev,
2662 .enable_int = mwifiex_pcie_enable_host_int,
2663 .process_int_status = mwifiex_process_int_status,
2664 .host_to_card = mwifiex_pcie_host_to_card,
2665 .wakeup = mwifiex_pm_wakeup_card,
2666 .wakeup_complete = mwifiex_pm_wakeup_card_complete,
2667
2668 /* PCIE specific */
2669 .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
2670 .event_complete = mwifiex_pcie_event_complete,
2671 .update_mp_end_port = NULL,
2672 .cleanup_mpa_buf = NULL,
Avinash Patilc6d1d872013-01-03 21:21:29 -08002673 .init_fw_port = mwifiex_pcie_init_fw_port,
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08002674 .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002675 .device_dump = mwifiex_pcie_device_dump,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002676};
2677
2678/*
2679 * This function initializes the PCIE driver module.
2680 *
2681 * This initiates the semaphore and registers the device with
2682 * PCIE bus.
2683 */
2684static int mwifiex_pcie_init_module(void)
2685{
2686 int ret;
2687
Avinash Patilca8f2112013-02-08 18:18:09 -08002688 pr_debug("Marvell PCIe Driver\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002689
2690 sema_init(&add_remove_card_sem, 1);
2691
2692 /* Clear the flag in case user removes the card. */
2693 user_rmmod = 0;
2694
2695 ret = pci_register_driver(&mwifiex_pcie);
2696 if (ret)
2697 pr_err("Driver register failed!\n");
2698 else
2699 pr_debug("info: Driver registered successfully!\n");
2700
2701 return ret;
2702}
2703
2704/*
2705 * This function cleans up the PCIE driver.
2706 *
2707 * The following major steps are followed for cleanup -
2708 * - Resume the device if its suspended
2709 * - Disconnect the device if connected
2710 * - Shutdown the firmware
2711 * - Unregister the device from PCIE bus.
2712 */
2713static void mwifiex_pcie_cleanup_module(void)
2714{
2715 if (!down_interruptible(&add_remove_card_sem))
2716 up(&add_remove_card_sem);
2717
2718 /* Set the flag as user is removing this module. */
2719 user_rmmod = 1;
2720
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002721 cancel_work_sync(&pcie_work);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002722 pci_unregister_driver(&mwifiex_pcie);
2723}
2724
2725module_init(mwifiex_pcie_init_module);
2726module_exit(mwifiex_pcie_cleanup_module);
2727
2728MODULE_AUTHOR("Marvell International Ltd.");
2729MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
2730MODULE_VERSION(PCIE_VERSION);
2731MODULE_LICENSE("GPL v2");
Avinash Patilca8f2112013-02-08 18:18:09 -08002732MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
2733MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);