blob: 6d0dc40e20e5c535f127e69743e046162fb71138 [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,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700269 .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,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700274 .driver_data = (unsigned long)&mwifiex_pcie8897,
275 },
276 {
277 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
278 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
279 .driver_data = (unsigned long)&mwifiex_pcie8997,
Avinash Patilca8f2112013-02-08 18:18:09 -0800280 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700281 {},
282};
283
284MODULE_DEVICE_TABLE(pci, mwifiex_ids);
285
Shuah Khan3266d732013-07-03 10:47:10 -0600286#ifdef CONFIG_PM_SLEEP
287/* Power Management Hooks */
288static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
289 mwifiex_pcie_resume);
290#endif
291
Amitkumar Karward930fae2011-10-11 17:41:21 -0700292/* PCI Device Driver */
293static struct pci_driver __refdata mwifiex_pcie = {
294 .name = "mwifiex_pcie",
295 .id_table = mwifiex_ids,
296 .probe = mwifiex_pcie_probe,
297 .remove = mwifiex_pcie_remove,
Shuah Khan3266d732013-07-03 10:47:10 -0600298#ifdef CONFIG_PM_SLEEP
299 .driver = {
300 .pm = &mwifiex_pcie_pm_ops,
301 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700302#endif
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700303 .shutdown = mwifiex_pcie_shutdown,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700304};
305
306/*
307 * This function writes data into PCIE card register.
308 */
309static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
310{
311 struct pcie_service_card *card = adapter->card;
312
313 iowrite32(data, card->pci_mmap1 + reg);
314
315 return 0;
316}
317
318/*
319 * This function reads data from PCIE card register.
320 */
321static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
322{
323 struct pcie_service_card *card = adapter->card;
324
325 *data = ioread32(card->pci_mmap1 + reg);
326
327 return 0;
328}
329
Amitkumar Karwar92c25382014-06-19 21:38:52 -0700330/* This function reads u8 data from PCIE card register. */
331static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
332 int reg, u8 *data)
333{
334 struct pcie_service_card *card = adapter->card;
335
336 *data = ioread8(card->pci_mmap1 + reg);
337
338 return 0;
339}
340
Amitkumar Karward930fae2011-10-11 17:41:21 -0700341/*
Avinash Patilc0880a22013-03-22 21:49:07 -0700342 * This function adds delay loop to ensure FW is awake before proceeding.
Amitkumar Karward930fae2011-10-11 17:41:21 -0700343 */
Avinash Patilc0880a22013-03-22 21:49:07 -0700344static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700345{
346 int i = 0;
347
Avinash Patilc0880a22013-03-22 21:49:07 -0700348 while (mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700349 i++;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -0700350 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700351 /* 50ms max wait */
Avinash Patil3e7a4ff2013-02-25 16:01:34 -0800352 if (i == 5000)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700353 break;
354 }
355
Avinash Patilc0880a22013-03-22 21:49:07 -0700356 return;
357}
358
Avinash Patilc4bc9802014-03-18 22:19:17 -0700359static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
360 u32 max_delay_loop_cnt)
361{
362 struct pcie_service_card *card = adapter->card;
363 u8 *buffer;
364 u32 sleep_cookie, count;
365
366 for (count = 0; count < max_delay_loop_cnt; count++) {
367 buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
368 sleep_cookie = *(u32 *)buffer;
369
370 if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530371 mwifiex_dbg(adapter, INFO,
372 "sleep cookie found at count %d\n", count);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700373 break;
374 }
375 usleep_range(20, 30);
376 }
377
378 if (count >= max_delay_loop_cnt)
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530379 mwifiex_dbg(adapter, INFO,
380 "max count reached while accessing sleep cookie\n");
Avinash Patilc4bc9802014-03-18 22:19:17 -0700381}
382
Avinash Patilc0880a22013-03-22 21:49:07 -0700383/* This function wakes up the card by reading fw_status register. */
384static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
385{
386 u32 fw_status;
387 struct pcie_service_card *card = adapter->card;
388 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
389
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530390 mwifiex_dbg(adapter, EVENT,
391 "event: Wakeup device...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700392
Avinash Patilc0880a22013-03-22 21:49:07 -0700393 if (reg->sleep_cookie)
394 mwifiex_pcie_dev_wakeup_delay(adapter);
395
396 /* Reading fw_status register will wakeup device */
397 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530398 mwifiex_dbg(adapter, ERROR,
399 "Reading fw_status register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700400 return -1;
401 }
402
Avinash Patilc0880a22013-03-22 21:49:07 -0700403 if (reg->sleep_cookie) {
404 mwifiex_pcie_dev_wakeup_delay(adapter);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530405 mwifiex_dbg(adapter, INFO,
406 "PCIE wakeup: Setting PS_STATE_AWAKE\n");
Avinash Patilc0880a22013-03-22 21:49:07 -0700407 adapter->ps_state = PS_STATE_AWAKE;
408 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700409
410 return 0;
411}
412
413/*
414 * This function is called after the card has woken up.
415 *
416 * The card configuration register is reset.
417 */
418static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
419{
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530420 mwifiex_dbg(adapter, CMD,
421 "cmd: Wakeup device completed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700422
423 return 0;
424}
425
426/*
427 * This function disables the host interrupt.
428 *
429 * The host interrupt mask is read, the disable bit is reset and
430 * written back to the card host interrupt mask register.
431 */
432static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
433{
434 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
435 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
436 0x00000000)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530437 mwifiex_dbg(adapter, ERROR,
438 "Disable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700439 return -1;
440 }
441 }
442
443 return 0;
444}
445
446/*
447 * This function enables the host interrupt.
448 *
449 * The host interrupt enable mask is written to the card
450 * host interrupt mask register.
451 */
452static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
453{
454 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
455 /* Simply write the mask to the register */
456 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
457 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530458 mwifiex_dbg(adapter, ERROR,
459 "Enable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700460 return -1;
461 }
462 }
463
464 return 0;
465}
466
467/*
Avinash Patil07324842013-02-08 18:18:07 -0800468 * This function initializes TX buffer ring descriptors
469 */
470static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
471{
472 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800473 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800474 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800475 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800476 int i;
477
478 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
479 card->tx_buf_list[i] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -0800480 if (reg->pfu_enabled) {
481 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
482 (sizeof(*desc2) * i);
483 desc2 = card->txbd_ring[i];
484 memset(desc2, 0, sizeof(*desc2));
485 } else {
486 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
487 (sizeof(*desc) * i);
488 desc = card->txbd_ring[i];
489 memset(desc, 0, sizeof(*desc));
490 }
Avinash Patil07324842013-02-08 18:18:07 -0800491 }
492
493 return 0;
494}
495
496/* This function initializes RX buffer ring descriptors. Each SKB is allocated
497 * here and after mapping PCI memory, its physical address is assigned to
498 * PCIE Rx buffer descriptor's physical address.
499 */
500static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
501{
502 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800503 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800504 struct sk_buff *skb;
505 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800506 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800507 dma_addr_t buf_pa;
508 int i;
509
510 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
511 /* Allocate skb here so that firmware can DMA data from it */
Avinash Patil62159942015-03-13 17:37:52 +0530512 skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
513 GFP_KERNEL | GFP_DMA);
Avinash Patil07324842013-02-08 18:18:07 -0800514 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530515 mwifiex_dbg(adapter, ERROR,
516 "Unable to allocate skb for RX ring.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800517 kfree(card->rxbd_ring_vbase);
518 return -ENOMEM;
519 }
520
521 if (mwifiex_map_pci_memory(adapter, skb,
522 MWIFIEX_RX_DATA_BUF_SIZE,
523 PCI_DMA_FROMDEVICE))
524 return -1;
525
Aaron Durbindbccc922014-02-07 16:25:50 -0800526 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800527
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530528 mwifiex_dbg(adapter, INFO,
529 "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
530 skb, skb->len, skb->data, (u32)buf_pa,
531 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800532
533 card->rx_buf_list[i] = skb;
Avinash Patilca8f2112013-02-08 18:18:09 -0800534 if (reg->pfu_enabled) {
535 card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
536 (sizeof(*desc2) * i);
537 desc2 = card->rxbd_ring[i];
538 desc2->paddr = buf_pa;
539 desc2->len = (u16)skb->len;
540 desc2->frag_len = (u16)skb->len;
541 desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
542 desc2->offset = 0;
543 } else {
544 card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
545 (sizeof(*desc) * i));
546 desc = card->rxbd_ring[i];
547 desc->paddr = buf_pa;
548 desc->len = (u16)skb->len;
549 desc->flags = 0;
550 }
Avinash Patil07324842013-02-08 18:18:07 -0800551 }
552
553 return 0;
554}
555
556/* This function initializes event buffer ring descriptors. Each SKB is
557 * allocated here and after mapping PCI memory, its physical address is assigned
558 * to PCIE Rx buffer descriptor's physical address
559 */
560static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
561{
562 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800563 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800564 struct sk_buff *skb;
565 dma_addr_t buf_pa;
566 int i;
567
568 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
569 /* Allocate skb here so that firmware can DMA data from it */
570 skb = dev_alloc_skb(MAX_EVENT_SIZE);
571 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530572 mwifiex_dbg(adapter, ERROR,
573 "Unable to allocate skb for EVENT buf.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800574 kfree(card->evtbd_ring_vbase);
575 return -ENOMEM;
576 }
577 skb_put(skb, MAX_EVENT_SIZE);
578
579 if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
580 PCI_DMA_FROMDEVICE))
581 return -1;
582
Aaron Durbindbccc922014-02-07 16:25:50 -0800583 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800584
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530585 mwifiex_dbg(adapter, EVENT,
586 "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
587 skb, skb->len, skb->data, (u32)buf_pa,
588 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800589
590 card->evt_buf_list[i] = skb;
591 card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
592 (sizeof(*desc) * i));
Avinash Patil07324842013-02-08 18:18:07 -0800593 desc = card->evtbd_ring[i];
594 desc->paddr = buf_pa;
595 desc->len = (u16)skb->len;
596 desc->flags = 0;
597 }
598
599 return 0;
600}
601
602/* This function cleans up TX buffer rings. If any of the buffer list has valid
603 * SKB address, associated SKB is freed.
604 */
605static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
606{
607 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800608 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800609 struct sk_buff *skb;
610 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800611 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800612 int i;
613
614 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800615 if (reg->pfu_enabled) {
616 desc2 = card->txbd_ring[i];
617 if (card->tx_buf_list[i]) {
618 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800619 mwifiex_unmap_pci_memory(adapter, skb,
620 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800621 dev_kfree_skb_any(skb);
622 }
623 memset(desc2, 0, sizeof(*desc2));
624 } else {
625 desc = card->txbd_ring[i];
626 if (card->tx_buf_list[i]) {
627 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800628 mwifiex_unmap_pci_memory(adapter, skb,
629 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800630 dev_kfree_skb_any(skb);
631 }
632 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800633 }
634 card->tx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800635 }
636
637 return;
638}
639
640/* This function cleans up RX buffer rings. If any of the buffer list has valid
641 * SKB address, associated SKB is freed.
642 */
643static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
644{
645 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800646 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800647 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800648 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800649 struct sk_buff *skb;
650 int i;
651
652 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800653 if (reg->pfu_enabled) {
654 desc2 = card->rxbd_ring[i];
655 if (card->rx_buf_list[i]) {
656 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800657 mwifiex_unmap_pci_memory(adapter, skb,
658 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800659 dev_kfree_skb_any(skb);
660 }
661 memset(desc2, 0, sizeof(*desc2));
662 } else {
663 desc = card->rxbd_ring[i];
664 if (card->rx_buf_list[i]) {
665 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800666 mwifiex_unmap_pci_memory(adapter, skb,
667 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800668 dev_kfree_skb_any(skb);
669 }
670 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800671 }
Avinash Patilca8f2112013-02-08 18:18:09 -0800672 card->rx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800673 }
674
675 return;
676}
677
678/* This function cleans up event buffer rings. If any of the buffer list has
679 * valid SKB address, associated SKB is freed.
680 */
681static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
682{
683 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800684 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800685 struct sk_buff *skb;
686 int i;
687
688 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
689 desc = card->evtbd_ring[i];
690 if (card->evt_buf_list[i]) {
691 skb = card->evt_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800692 mwifiex_unmap_pci_memory(adapter, skb,
693 PCI_DMA_FROMDEVICE);
Avinash Patil07324842013-02-08 18:18:07 -0800694 dev_kfree_skb_any(skb);
695 }
696 card->evt_buf_list[i] = NULL;
697 memset(desc, 0, sizeof(*desc));
698 }
699
700 return;
701}
702
703/* This function creates buffer descriptor ring for TX
Amitkumar Karward930fae2011-10-11 17:41:21 -0700704 */
705static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
706{
707 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800708 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700709
710 /*
711 * driver maintaines the write pointer and firmware maintaines the read
712 * pointer. The write pointer starts at 0 (zero) while the read pointer
713 * starts at zero with rollover bit set
714 */
715 card->txbd_wrptr = 0;
Avinash Patilca8f2112013-02-08 18:18:09 -0800716
717 if (reg->pfu_enabled)
718 card->txbd_rdptr = 0;
719 else
720 card->txbd_rdptr |= reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700721
722 /* allocate shared memory for the BD ring and divide the same in to
723 several descriptors */
Avinash Patilca8f2112013-02-08 18:18:09 -0800724 if (reg->pfu_enabled)
725 card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
726 MWIFIEX_MAX_TXRX_BD;
727 else
728 card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
729 MWIFIEX_MAX_TXRX_BD;
730
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530731 mwifiex_dbg(adapter, INFO,
732 "info: txbd_ring: Allocating %d bytes\n",
733 card->txbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800734 card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
735 card->txbd_ring_size,
736 &card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700737 if (!card->txbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530738 mwifiex_dbg(adapter, ERROR,
739 "allocate consistent memory (%d bytes) failed!\n",
740 card->txbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800741 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700742 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530743 mwifiex_dbg(adapter, DATA,
744 "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
745 card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
746 (u32)((u64)card->txbd_ring_pbase >> 32),
747 card->txbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700748
Avinash Patil07324842013-02-08 18:18:07 -0800749 return mwifiex_init_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700750}
751
752static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
753{
754 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800755 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700756
Avinash Patil07324842013-02-08 18:18:07 -0800757 mwifiex_cleanup_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700758
Avinash Patilfc331462013-01-03 21:21:30 -0800759 if (card->txbd_ring_vbase)
760 pci_free_consistent(card->dev, card->txbd_ring_size,
761 card->txbd_ring_vbase,
762 card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700763 card->txbd_ring_size = 0;
764 card->txbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800765 card->txbd_rdptr = 0 | reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700766 card->txbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800767 card->txbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700768
769 return 0;
770}
771
772/*
773 * This function creates buffer descriptor ring for RX
774 */
775static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
776{
777 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800778 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700779
780 /*
781 * driver maintaines the read pointer and firmware maintaines the write
782 * pointer. The write pointer starts at 0 (zero) while the read pointer
783 * starts at zero with rollover bit set
784 */
785 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800786 card->rxbd_rdptr = reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700787
Avinash Patilca8f2112013-02-08 18:18:09 -0800788 if (reg->pfu_enabled)
789 card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
790 MWIFIEX_MAX_TXRX_BD;
791 else
792 card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
793 MWIFIEX_MAX_TXRX_BD;
794
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530795 mwifiex_dbg(adapter, INFO,
796 "info: rxbd_ring: Allocating %d bytes\n",
797 card->rxbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800798 card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
799 card->rxbd_ring_size,
800 &card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700801 if (!card->rxbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530802 mwifiex_dbg(adapter, ERROR,
803 "allocate consistent memory (%d bytes) failed!\n",
804 card->rxbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800805 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700806 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700807
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530808 mwifiex_dbg(adapter, DATA,
809 "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
810 card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
811 (u32)((u64)card->rxbd_ring_pbase >> 32),
812 card->rxbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700813
Avinash Patil07324842013-02-08 18:18:07 -0800814 return mwifiex_init_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700815}
816
817/*
818 * This function deletes Buffer descriptor ring for RX
819 */
820static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
821{
822 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800823 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700824
Avinash Patil07324842013-02-08 18:18:07 -0800825 mwifiex_cleanup_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700826
Avinash Patilfc331462013-01-03 21:21:30 -0800827 if (card->rxbd_ring_vbase)
828 pci_free_consistent(card->dev, card->rxbd_ring_size,
829 card->rxbd_ring_vbase,
830 card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700831 card->rxbd_ring_size = 0;
832 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800833 card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700834 card->rxbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800835 card->rxbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700836
837 return 0;
838}
839
840/*
841 * This function creates buffer descriptor ring for Events
842 */
843static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
844{
845 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800846 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700847
848 /*
849 * driver maintaines the read pointer and firmware maintaines the write
850 * pointer. The write pointer starts at 0 (zero) while the read pointer
851 * starts at zero with rollover bit set
852 */
853 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800854 card->evtbd_rdptr = reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700855
Avinash Patile05dc3e2013-02-08 18:18:08 -0800856 card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
Avinash Patilca8f2112013-02-08 18:18:09 -0800857 MWIFIEX_MAX_EVT_BD;
858
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530859 mwifiex_dbg(adapter, INFO,
860 "info: evtbd_ring: Allocating %d bytes\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700861 card->evtbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800862 card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
863 card->evtbd_ring_size,
864 &card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700865 if (!card->evtbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530866 mwifiex_dbg(adapter, ERROR,
867 "allocate consistent memory (%d bytes) failed!\n",
868 card->evtbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800869 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700870 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700871
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530872 mwifiex_dbg(adapter, EVENT,
873 "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
874 card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
875 (u32)((u64)card->evtbd_ring_pbase >> 32),
876 card->evtbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700877
Avinash Patil07324842013-02-08 18:18:07 -0800878 return mwifiex_pcie_init_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700879}
880
881/*
882 * This function deletes Buffer descriptor ring for Events
883 */
884static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
885{
886 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800887 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700888
Avinash Patil07324842013-02-08 18:18:07 -0800889 mwifiex_cleanup_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700890
Avinash Patilfc331462013-01-03 21:21:30 -0800891 if (card->evtbd_ring_vbase)
892 pci_free_consistent(card->dev, card->evtbd_ring_size,
893 card->evtbd_ring_vbase,
894 card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700895 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800896 card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700897 card->evtbd_ring_size = 0;
898 card->evtbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800899 card->evtbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700900
901 return 0;
902}
903
904/*
905 * This function allocates a buffer for CMDRSP
906 */
907static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
908{
909 struct pcie_service_card *card = adapter->card;
910 struct sk_buff *skb;
911
912 /* Allocate memory for receiving command response data */
913 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
914 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530915 mwifiex_dbg(adapter, ERROR,
916 "Unable to allocate skb for command response data.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700917 return -ENOMEM;
918 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700919 skb_put(skb, MWIFIEX_UPLD_SIZE);
Avinash Patilfc331462013-01-03 21:21:30 -0800920 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
921 PCI_DMA_FROMDEVICE))
922 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700923
Avinash Patilfc331462013-01-03 21:21:30 -0800924 card->cmdrsp_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700925
926 return 0;
927}
928
929/*
930 * This function deletes a buffer for CMDRSP
931 */
932static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
933{
934 struct pcie_service_card *card;
935
936 if (!adapter)
937 return 0;
938
939 card = adapter->card;
940
Avinash Patilfc331462013-01-03 21:21:30 -0800941 if (card && card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800942 mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
943 PCI_DMA_FROMDEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700944 dev_kfree_skb_any(card->cmdrsp_buf);
Avinash Patilfc331462013-01-03 21:21:30 -0800945 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700946
Avinash Patilfc331462013-01-03 21:21:30 -0800947 if (card && card->cmd_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800948 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
949 PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -0800950 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700951 return 0;
952}
953
954/*
955 * This function allocates a buffer for sleep cookie
956 */
957static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
958{
Amitkumar Karward930fae2011-10-11 17:41:21 -0700959 struct pcie_service_card *card = adapter->card;
960
Avinash Patilfc331462013-01-03 21:21:30 -0800961 card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
962 &card->sleep_cookie_pbase);
963 if (!card->sleep_cookie_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530964 mwifiex_dbg(adapter, ERROR,
965 "pci_alloc_consistent failed!\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700966 return -ENOMEM;
967 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700968 /* Init val of Sleep Cookie */
Avinash Patilfc331462013-01-03 21:21:30 -0800969 *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700970
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530971 mwifiex_dbg(adapter, INFO,
972 "alloc_scook: sleep cookie=0x%x\n",
973 *((u32 *)card->sleep_cookie_vbase));
Amitkumar Karward930fae2011-10-11 17:41:21 -0700974
975 return 0;
976}
977
978/*
979 * This function deletes buffer for sleep cookie
980 */
981static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
982{
983 struct pcie_service_card *card;
984
985 if (!adapter)
986 return 0;
987
988 card = adapter->card;
989
Avinash Patilfc331462013-01-03 21:21:30 -0800990 if (card && card->sleep_cookie_vbase) {
991 pci_free_consistent(card->dev, sizeof(u32),
992 card->sleep_cookie_vbase,
993 card->sleep_cookie_pbase);
994 card->sleep_cookie_vbase = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700995 }
996
997 return 0;
998}
999
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001000/* This function flushes the TX buffer descriptor ring
1001 * This function defined as handler is also called while cleaning TXRX
1002 * during disconnect/ bss stop.
1003 */
1004static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
1005{
1006 struct pcie_service_card *card = adapter->card;
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001007
Avinash Patil48f4d912013-02-20 21:12:58 -08001008 if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001009 card->txbd_flush = 1;
1010 /* write pointer already set at last send
1011 * send dnld-rdy intr again, wait for completion.
1012 */
1013 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1014 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301015 mwifiex_dbg(adapter, ERROR,
1016 "failed to assert dnld-rdy interrupt.\n");
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001017 return -1;
1018 }
1019 }
1020 return 0;
1021}
1022
Amitkumar Karward930fae2011-10-11 17:41:21 -07001023/*
Avinash Patile7f767a2013-01-03 21:21:32 -08001024 * This function unmaps and frees downloaded data buffer
Amitkumar Karward930fae2011-10-11 17:41:21 -07001025 */
Avinash Patile7f767a2013-01-03 21:21:32 -08001026static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001027{
Avinash Patile7f767a2013-01-03 21:21:32 -08001028 struct sk_buff *skb;
Avinash Patilca8f2112013-02-08 18:18:09 -08001029 u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001030 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001031 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001032 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001033 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001034
1035 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1036 mwifiex_pm_wakeup_card(adapter);
1037
1038 /* Read the TX ring read pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001039 if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301040 mwifiex_dbg(adapter, ERROR,
1041 "SEND COMP: failed to read reg->tx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001042 return -1;
1043 }
1044
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301045 mwifiex_dbg(adapter, DATA,
1046 "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
1047 card->txbd_rdptr, rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001048
Avinash Patilca8f2112013-02-08 18:18:09 -08001049 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001050 /* free from previous txbd_rdptr to current txbd_rdptr */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001051 while (((card->txbd_rdptr & reg->tx_mask) !=
1052 (rdptr & reg->tx_mask)) ||
1053 ((card->txbd_rdptr & reg->tx_rollover_ind) !=
1054 (rdptr & reg->tx_rollover_ind))) {
Avinash Patilca8f2112013-02-08 18:18:09 -08001055 wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
1056 reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001057
1058 skb = card->tx_buf_list[wrdoneidx];
Aaron Durbindbccc922014-02-07 16:25:50 -08001059
Avinash Patile7f767a2013-01-03 21:21:32 -08001060 if (skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301061 mwifiex_dbg(adapter, DATA,
1062 "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
1063 skb, wrdoneidx);
Aaron Durbindbccc922014-02-07 16:25:50 -08001064 mwifiex_unmap_pci_memory(adapter, skb,
1065 PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001066
1067 unmap_count++;
1068
1069 if (card->txbd_flush)
1070 mwifiex_write_data_complete(adapter, skb, 0,
1071 -1);
1072 else
1073 mwifiex_write_data_complete(adapter, skb, 0, 0);
1074 }
1075
1076 card->tx_buf_list[wrdoneidx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001077
1078 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001079 desc2 = card->txbd_ring[wrdoneidx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001080 memset(desc2, 0, sizeof(*desc2));
1081 } else {
1082 desc = card->txbd_ring[wrdoneidx];
1083 memset(desc, 0, sizeof(*desc));
1084 }
1085 switch (card->dev->device) {
1086 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1087 card->txbd_rdptr++;
1088 break;
1089 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001090 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001091 card->txbd_rdptr += reg->ring_tx_start_ptr;
1092 break;
1093 }
1094
Avinash Patile7f767a2013-01-03 21:21:32 -08001095
Avinash Patildd04e6a2013-02-08 18:18:06 -08001096 if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
Avinash Patile7f767a2013-01-03 21:21:32 -08001097 card->txbd_rdptr = ((card->txbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001098 reg->tx_rollover_ind) ^
1099 reg->tx_rollover_ind);
Avinash Patile7f767a2013-01-03 21:21:32 -08001100 }
1101
1102 if (unmap_count)
1103 adapter->data_sent = false;
1104
1105 if (card->txbd_flush) {
Avinash Patil3d482032013-02-15 21:37:54 -08001106 if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
Avinash Patile7f767a2013-01-03 21:21:32 -08001107 card->txbd_flush = 0;
1108 else
1109 mwifiex_clean_pcie_ring_buf(adapter);
1110 }
1111
1112 return 0;
1113}
1114
1115/* This function sends data buffer to device. First 4 bytes of payload
1116 * are filled with payload length and payload type. Then this payload
1117 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
1118 * Download ready interrupt to FW is deffered if Tx ring is not full and
1119 * additional payload can be accomodated.
Avinash Patil8d767dc2014-05-13 19:50:13 -07001120 * Caller must ensure tx_param parameter to this function is not NULL.
Avinash Patile7f767a2013-01-03 21:21:32 -08001121 */
1122static int
1123mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
1124 struct mwifiex_tx_param *tx_param)
1125{
1126 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001127 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001128 u32 wrindx, num_tx_buffs, rx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001129 int ret;
1130 dma_addr_t buf_pa;
Bing Zhao99310782013-03-04 16:27:55 -08001131 struct mwifiex_pcie_buf_desc *desc = NULL;
1132 struct mwifiex_pfu_buf_desc *desc2 = NULL;
Avinash Patile7f767a2013-01-03 21:21:32 -08001133 __le16 *tmp;
1134
1135 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301136 mwifiex_dbg(adapter, ERROR,
1137 "%s(): invalid parameter <%p, %#x>\n",
1138 __func__, skb->data, skb->len);
Avinash Patile7f767a2013-01-03 21:21:32 -08001139 return -1;
1140 }
1141
1142 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1143 mwifiex_pm_wakeup_card(adapter);
1144
Avinash Patilca8f2112013-02-08 18:18:09 -08001145 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301146 mwifiex_dbg(adapter, DATA,
1147 "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
Avinash Patile7f767a2013-01-03 21:21:32 -08001148 card->txbd_rdptr, card->txbd_wrptr);
1149 if (mwifiex_pcie_txbd_not_full(card)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001150 u8 *payload;
1151
1152 adapter->data_sent = true;
Avinash Patile7f767a2013-01-03 21:21:32 -08001153 payload = skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001154 tmp = (__le16 *)&payload[0];
1155 *tmp = cpu_to_le16((u16)skb->len);
1156 tmp = (__le16 *)&payload[2];
1157 *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
Avinash Patile7f767a2013-01-03 21:21:32 -08001158
Aaron Durbindbccc922014-02-07 16:25:50 -08001159 if (mwifiex_map_pci_memory(adapter, skb, skb->len,
Avinash Patile7f767a2013-01-03 21:21:32 -08001160 PCI_DMA_TODEVICE))
1161 return -1;
1162
Avinash Patilca8f2112013-02-08 18:18:09 -08001163 wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
Aaron Durbindbccc922014-02-07 16:25:50 -08001164 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile7f767a2013-01-03 21:21:32 -08001165 card->tx_buf_list[wrindx] = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001166
Avinash Patilca8f2112013-02-08 18:18:09 -08001167 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001168 desc2 = card->txbd_ring[wrindx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001169 desc2->paddr = buf_pa;
1170 desc2->len = (u16)skb->len;
1171 desc2->frag_len = (u16)skb->len;
1172 desc2->offset = 0;
1173 desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1174 MWIFIEX_BD_FLAG_LAST_DESC;
1175 } else {
1176 desc = card->txbd_ring[wrindx];
1177 desc->paddr = buf_pa;
1178 desc->len = (u16)skb->len;
1179 desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1180 MWIFIEX_BD_FLAG_LAST_DESC;
1181 }
1182
1183 switch (card->dev->device) {
1184 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1185 card->txbd_wrptr++;
1186 break;
1187 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001188 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001189 card->txbd_wrptr += reg->ring_tx_start_ptr;
1190 break;
1191 }
1192
1193 if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001194 card->txbd_wrptr = ((card->txbd_wrptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001195 reg->tx_rollover_ind) ^
1196 reg->tx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001197
Avinash Patilca8f2112013-02-08 18:18:09 -08001198 rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001199 /* Write the TX ring write pointer in to reg->tx_wrptr */
1200 if (mwifiex_write_reg(adapter, reg->tx_wrptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001201 card->txbd_wrptr | rx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301202 mwifiex_dbg(adapter, ERROR,
1203 "SEND DATA: failed to write reg->tx_wrptr\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001204 ret = -1;
1205 goto done_unmap;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001206 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001207 if ((mwifiex_pcie_txbd_not_full(card)) &&
1208 tx_param->next_pkt_len) {
1209 /* have more packets and TxBD still can hold more */
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301210 mwifiex_dbg(adapter, DATA,
1211 "SEND DATA: delay dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001212 adapter->data_sent = false;
1213 } else {
1214 /* Send the TX ready interrupt */
1215 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1216 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301217 mwifiex_dbg(adapter, ERROR,
1218 "SEND DATA: failed to assert dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001219 ret = -1;
1220 goto done_unmap;
1221 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001222 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301223 mwifiex_dbg(adapter, DATA,
1224 "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
1225 "%#x> and sent packet to firmware successfully\n",
1226 card->txbd_rdptr, card->txbd_wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001227 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301228 mwifiex_dbg(adapter, DATA,
1229 "info: TX Ring full, can't send packets to fw\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001230 adapter->data_sent = true;
1231 /* Send the TX ready interrupt */
1232 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1233 CPU_INTR_DNLD_RDY))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301234 mwifiex_dbg(adapter, ERROR,
1235 "SEND DATA: failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001236 return -EBUSY;
1237 }
1238
Avinash Patile7f767a2013-01-03 21:21:32 -08001239 return -EINPROGRESS;
1240done_unmap:
Aaron Durbindbccc922014-02-07 16:25:50 -08001241 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001242 card->tx_buf_list[wrindx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001243 if (reg->pfu_enabled)
1244 memset(desc2, 0, sizeof(*desc2));
1245 else
1246 memset(desc, 0, sizeof(*desc));
1247
Avinash Patile7f767a2013-01-03 21:21:32 -08001248 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001249}
1250
1251/*
1252 * This function handles received buffer ring and
1253 * dispatches packets to upper
1254 */
1255static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
1256{
1257 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001258 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001259 u32 wrptr, rd_index, tx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001260 dma_addr_t buf_pa;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001261 int ret = 0;
1262 struct sk_buff *skb_tmp = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001263 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001264 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001265
Avinash Patile7f767a2013-01-03 21:21:32 -08001266 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1267 mwifiex_pm_wakeup_card(adapter);
1268
Amitkumar Karward930fae2011-10-11 17:41:21 -07001269 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001270 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301271 mwifiex_dbg(adapter, ERROR,
1272 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001273 ret = -1;
1274 goto done;
1275 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001276 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001277
Avinash Patildd04e6a2013-02-08 18:18:06 -08001278 while (((wrptr & reg->rx_mask) !=
1279 (card->rxbd_rdptr & reg->rx_mask)) ||
1280 ((wrptr & reg->rx_rollover_ind) ==
1281 (card->rxbd_rdptr & reg->rx_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001282 struct sk_buff *skb_data;
1283 u16 rx_len;
Avinash Patile7f767a2013-01-03 21:21:32 -08001284 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001285
Avinash Patildd04e6a2013-02-08 18:18:06 -08001286 rd_index = card->rxbd_rdptr & reg->rx_mask;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001287 skb_data = card->rx_buf_list[rd_index];
1288
Amitkumar Karwarbb8e6a12014-02-18 15:41:55 -08001289 /* If skb allocation was failed earlier for Rx packet,
1290 * rx_buf_list[rd_index] would have been left with a NULL.
1291 */
1292 if (!skb_data)
1293 return -ENOMEM;
1294
Aaron Durbindbccc922014-02-07 16:25:50 -08001295 mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001296 card->rx_buf_list[rd_index] = NULL;
1297
Amitkumar Karward930fae2011-10-11 17:41:21 -07001298 /* Get data length from interface header -
Avinash Patile7f767a2013-01-03 21:21:32 -08001299 * first 2 bytes for len, next 2 bytes is for type
1300 */
1301 pkt_len = *((__le16 *)skb_data->data);
1302 rx_len = le16_to_cpu(pkt_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301303 if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
1304 rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301305 mwifiex_dbg(adapter, ERROR,
1306 "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
1307 rx_len, card->rxbd_rdptr, wrptr);
Avinash Patil42a028a2014-09-12 20:08:47 +05301308 dev_kfree_skb_any(skb_data);
1309 } else {
1310 skb_put(skb_data, rx_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301311 mwifiex_dbg(adapter, DATA,
1312 "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
1313 card->rxbd_rdptr, wrptr, rx_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301314 skb_pull(skb_data, INTF_HEADER_LEN);
Avinash Patil6e251172014-09-12 20:08:59 +05301315 if (adapter->rx_work_enabled) {
Avinash Patil6e251172014-09-12 20:08:59 +05301316 skb_queue_tail(&adapter->rx_data_q, skb_data);
Avinash Patil6e251172014-09-12 20:08:59 +05301317 adapter->data_received = true;
1318 atomic_inc(&adapter->rx_pending);
1319 } else {
1320 mwifiex_handle_rx_packet(adapter, skb_data);
1321 }
Avinash Patil42a028a2014-09-12 20:08:47 +05301322 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001323
Avinash Patil62159942015-03-13 17:37:52 +05301324 skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
1325 GFP_KERNEL | GFP_DMA);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001326 if (!skb_tmp) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301327 mwifiex_dbg(adapter, ERROR,
1328 "Unable to allocate skb.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001329 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001330 }
1331
Avinash Patile7f767a2013-01-03 21:21:32 -08001332 if (mwifiex_map_pci_memory(adapter, skb_tmp,
1333 MWIFIEX_RX_DATA_BUF_SIZE,
1334 PCI_DMA_FROMDEVICE))
1335 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001336
Aaron Durbindbccc922014-02-07 16:25:50 -08001337 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
Avinash Patile7f767a2013-01-03 21:21:32 -08001338
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301339 mwifiex_dbg(adapter, INFO,
1340 "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
1341 skb_tmp, rd_index);
Avinash Patile7f767a2013-01-03 21:21:32 -08001342 card->rx_buf_list[rd_index] = skb_tmp;
Avinash Patilca8f2112013-02-08 18:18:09 -08001343
1344 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001345 desc2 = card->rxbd_ring[rd_index];
Avinash Patilca8f2112013-02-08 18:18:09 -08001346 desc2->paddr = buf_pa;
1347 desc2->len = skb_tmp->len;
1348 desc2->frag_len = skb_tmp->len;
1349 desc2->offset = 0;
1350 desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
1351 } else {
1352 desc = card->rxbd_ring[rd_index];
1353 desc->paddr = buf_pa;
1354 desc->len = skb_tmp->len;
1355 desc->flags = 0;
1356 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001357
Avinash Patildd04e6a2013-02-08 18:18:06 -08001358 if ((++card->rxbd_rdptr & reg->rx_mask) ==
Amitkumar Karward930fae2011-10-11 17:41:21 -07001359 MWIFIEX_MAX_TXRX_BD) {
1360 card->rxbd_rdptr = ((card->rxbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001361 reg->rx_rollover_ind) ^
1362 reg->rx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001363 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301364 mwifiex_dbg(adapter, DATA,
1365 "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
1366 card->rxbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001367
Avinash Patilca8f2112013-02-08 18:18:09 -08001368 tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001369 /* Write the RX ring read pointer in to reg->rx_rdptr */
1370 if (mwifiex_write_reg(adapter, reg->rx_rdptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001371 card->rxbd_rdptr | tx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301372 mwifiex_dbg(adapter, DATA,
1373 "RECV DATA: failed to write reg->rx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001374 ret = -1;
1375 goto done;
1376 }
1377
1378 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001379 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301380 mwifiex_dbg(adapter, ERROR,
1381 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001382 ret = -1;
1383 goto done;
1384 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301385 mwifiex_dbg(adapter, DATA,
1386 "info: RECV DATA: Rcvd packet from fw successfully\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001387 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001388 }
1389
1390done:
Amitkumar Karward930fae2011-10-11 17:41:21 -07001391 return ret;
1392}
1393
1394/*
1395 * This function downloads the boot command to device
1396 */
1397static int
1398mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1399{
Avinash Patilfc331462013-01-03 21:21:30 -08001400 dma_addr_t buf_pa;
1401 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001402 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001403
Avinash Patilfc331462013-01-03 21:21:30 -08001404 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301405 mwifiex_dbg(adapter, ERROR,
1406 "Invalid parameter in %s <%p. len %d>\n",
1407 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001408 return -1;
1409 }
1410
Avinash Patilfc331462013-01-03 21:21:30 -08001411 if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
1412 return -1;
1413
Aaron Durbindbccc922014-02-07 16:25:50 -08001414 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patilfc331462013-01-03 21:21:30 -08001415
Avinash Patildd04e6a2013-02-08 18:18:06 -08001416 /* Write the lower 32bits of the physical address to low command
1417 * address scratch register
1418 */
1419 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301420 mwifiex_dbg(adapter, ERROR,
1421 "%s: failed to write download command to boot code.\n",
1422 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001423 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001424 return -1;
1425 }
1426
Avinash Patildd04e6a2013-02-08 18:18:06 -08001427 /* Write the upper 32bits of the physical address to high command
1428 * address scratch register
1429 */
1430 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001431 (u32)((u64)buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301432 mwifiex_dbg(adapter, ERROR,
1433 "%s: failed to write download command to boot code.\n",
1434 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001435 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001436 return -1;
1437 }
1438
Avinash Patildd04e6a2013-02-08 18:18:06 -08001439 /* Write the command length to cmd_size scratch register */
1440 if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301441 mwifiex_dbg(adapter, ERROR,
1442 "%s: failed to write command len to cmd_size scratch reg\n",
1443 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001444 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001445 return -1;
1446 }
1447
1448 /* Ring the door bell */
1449 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1450 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301451 mwifiex_dbg(adapter, ERROR,
1452 "%s: failed to assert door-bell intr\n", __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001453 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001454 return -1;
1455 }
1456
1457 return 0;
1458}
1459
Avinash Patilc6d1d872013-01-03 21:21:29 -08001460/* This function init rx port in firmware which in turn enables to receive data
1461 * from device before transmitting any packet.
1462 */
1463static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
1464{
1465 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001466 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001467 int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patilc6d1d872013-01-03 21:21:29 -08001468
Avinash Patildd04e6a2013-02-08 18:18:06 -08001469 /* Write the RX ring read pointer in to reg->rx_rdptr */
Avinash Patilca8f2112013-02-08 18:18:09 -08001470 if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
1471 tx_wrap)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301472 mwifiex_dbg(adapter, ERROR,
1473 "RECV DATA: failed to write reg->rx_rdptr\n");
Avinash Patilc6d1d872013-01-03 21:21:29 -08001474 return -1;
1475 }
1476 return 0;
1477}
1478
1479/* This function downloads commands to the device
Amitkumar Karward930fae2011-10-11 17:41:21 -07001480 */
1481static int
1482mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1483{
1484 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001485 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001486 int ret = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001487 dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
1488 u8 *payload = (u8 *)skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001489
1490 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301491 mwifiex_dbg(adapter, ERROR,
1492 "Invalid parameter in %s <%p, %#x>\n",
1493 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001494 return -1;
1495 }
1496
1497 /* Make sure a command response buffer is available */
1498 if (!card->cmdrsp_buf) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301499 mwifiex_dbg(adapter, ERROR,
1500 "No response buffer available, send command failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001501 return -EBUSY;
1502 }
1503
Avinash Patilfc331462013-01-03 21:21:30 -08001504 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1505 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001506
1507 adapter->cmd_sent = true;
Avinash Patilfc331462013-01-03 21:21:30 -08001508
1509 *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
1510 *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
1511
1512 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
1513 return -1;
1514
1515 card->cmd_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001516
1517 /* To send a command, the driver will:
1518 1. Write the 64bit physical address of the data buffer to
Avinash Patildd04e6a2013-02-08 18:18:06 -08001519 cmd response address low + cmd response address high
Amitkumar Karward930fae2011-10-11 17:41:21 -07001520 2. Ring the door bell (i.e. set the door bell interrupt)
1521
1522 In response to door bell interrupt, the firmware will perform
1523 the DMA of the command packet (first header to obtain the total
1524 length and then rest of the command).
1525 */
1526
1527 if (card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001528 cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001529 /* Write the lower 32bits of the cmdrsp buffer physical
1530 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001531 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
Avinash Patilfc331462013-01-03 21:21:30 -08001532 (u32)cmdrsp_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301533 mwifiex_dbg(adapter, ERROR,
1534 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001535 ret = -1;
1536 goto done;
1537 }
1538 /* Write the upper 32bits of the cmdrsp buffer physical
1539 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001540 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001541 (u32)((u64)cmdrsp_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301542 mwifiex_dbg(adapter, ERROR,
1543 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001544 ret = -1;
1545 goto done;
1546 }
1547 }
1548
Aaron Durbindbccc922014-02-07 16:25:50 -08001549 cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001550 /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
1551 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
1552 (u32)cmd_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301553 mwifiex_dbg(adapter, ERROR,
1554 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001555 ret = -1;
1556 goto done;
1557 }
Avinash Patildd04e6a2013-02-08 18:18:06 -08001558 /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
1559 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001560 (u32)((u64)cmd_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301561 mwifiex_dbg(adapter, ERROR,
1562 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001563 ret = -1;
1564 goto done;
1565 }
1566
Avinash Patildd04e6a2013-02-08 18:18:06 -08001567 /* Write the command length to reg->cmd_size */
1568 if (mwifiex_write_reg(adapter, reg->cmd_size,
1569 card->cmd_buf->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301570 mwifiex_dbg(adapter, ERROR,
1571 "Failed to write cmd len to reg->cmd_size\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001572 ret = -1;
1573 goto done;
1574 }
1575
1576 /* Ring the door bell */
1577 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1578 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301579 mwifiex_dbg(adapter, ERROR,
1580 "Failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001581 ret = -1;
1582 goto done;
1583 }
1584
1585done:
1586 if (ret)
1587 adapter->cmd_sent = false;
1588
1589 return 0;
1590}
1591
1592/*
1593 * This function handles command complete interrupt
1594 */
1595static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
1596{
1597 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001598 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001599 struct sk_buff *skb = card->cmdrsp_buf;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001600 int count = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001601 u16 rx_len;
1602 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001603
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301604 mwifiex_dbg(adapter, CMD,
1605 "info: Rx CMD Response\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001606
Aaron Durbindbccc922014-02-07 16:25:50 -08001607 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001608
Aaron Durbin189b3292014-02-07 16:25:51 -08001609 /* Unmap the command as a response has been received. */
1610 if (card->cmd_buf) {
1611 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1612 PCI_DMA_TODEVICE);
1613 card->cmd_buf = NULL;
1614 }
1615
Avinash Patilfc331462013-01-03 21:21:30 -08001616 pkt_len = *((__le16 *)skb->data);
1617 rx_len = le16_to_cpu(pkt_len);
1618 skb_trim(skb, rx_len);
1619 skb_pull(skb, INTF_HEADER_LEN);
1620
Amitkumar Karward930fae2011-10-11 17:41:21 -07001621 if (!adapter->curr_cmd) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001622 if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001623 mwifiex_process_sleep_confirm_resp(adapter, skb->data,
1624 skb->len);
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001625 mwifiex_pcie_enable_host_int(adapter);
1626 if (mwifiex_write_reg(adapter,
1627 PCIE_CPU_INT_EVENT,
1628 CPU_INTR_SLEEP_CFM_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301629 mwifiex_dbg(adapter, ERROR,
1630 "Write register failed\n");
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001631 return -1;
1632 }
Avinash Patilc4bc9802014-03-18 22:19:17 -07001633 mwifiex_delay_for_sleep_cookie(adapter,
1634 MWIFIEX_MAX_DELAY_COUNT);
Avinash Patil52301a82013-02-12 14:38:32 -08001635 while (reg->sleep_cookie && (count++ < 10) &&
1636 mwifiex_pcie_ok_to_access_hw(adapter))
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001637 usleep_range(50, 60);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001638 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301639 mwifiex_dbg(adapter, ERROR,
1640 "There is no command but got cmdrsp\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001641 }
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001642 memcpy(adapter->upld_buf, skb->data,
1643 min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
Avinash Patil0f49d642013-03-20 17:56:23 -07001644 skb_push(skb, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001645 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1646 PCI_DMA_FROMDEVICE))
1647 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001648 } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001649 adapter->curr_cmd->resp_skb = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001650 adapter->cmd_resp_received = true;
1651 /* Take the pointer and set it to CMD node and will
1652 return in the response complete callback */
1653 card->cmdrsp_buf = NULL;
1654
1655 /* Clear the cmd-rsp buffer address in scratch registers. This
1656 will prevent firmware from writing to the same response
1657 buffer again. */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001658 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301659 mwifiex_dbg(adapter, ERROR,
1660 "cmd_done: failed to clear cmd_rsp_addr_lo\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001661 return -1;
1662 }
1663 /* Write the upper 32bits of the cmdrsp buffer physical
1664 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001665 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301666 mwifiex_dbg(adapter, ERROR,
1667 "cmd_done: failed to clear cmd_rsp_addr_hi\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001668 return -1;
1669 }
1670 }
1671
1672 return 0;
1673}
1674
1675/*
1676 * Command Response processing complete handler
1677 */
1678static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
1679 struct sk_buff *skb)
1680{
1681 struct pcie_service_card *card = adapter->card;
1682
1683 if (skb) {
1684 card->cmdrsp_buf = skb;
1685 skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001686 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1687 PCI_DMA_FROMDEVICE))
1688 return -1;
1689 }
1690
Amitkumar Karward930fae2011-10-11 17:41:21 -07001691 return 0;
1692}
1693
1694/*
1695 * This function handles firmware event ready interrupt
1696 */
1697static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
1698{
1699 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001700 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001701 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1702 u32 wrptr, event;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001703 struct mwifiex_evt_buf_desc *desc;
Avinash Patilfc331462013-01-03 21:21:30 -08001704
1705 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1706 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001707
1708 if (adapter->event_received) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301709 mwifiex_dbg(adapter, EVENT,
1710 "info: Event being processed,\t"
1711 "do not process this interrupt just yet\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001712 return 0;
1713 }
1714
1715 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301716 mwifiex_dbg(adapter, ERROR,
1717 "info: Invalid read pointer...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001718 return -1;
1719 }
1720
1721 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001722 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301723 mwifiex_dbg(adapter, ERROR,
1724 "EventReady: failed to read reg->evt_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001725 return -1;
1726 }
1727
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301728 mwifiex_dbg(adapter, EVENT,
1729 "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
1730 card->evtbd_rdptr, wrptr);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001731 if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
1732 & MWIFIEX_EVTBD_MASK)) ||
Avinash Patildd04e6a2013-02-08 18:18:06 -08001733 ((wrptr & reg->evt_rollover_ind) ==
1734 (card->evtbd_rdptr & reg->evt_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001735 struct sk_buff *skb_cmd;
1736 __le16 data_len = 0;
1737 u16 evt_len;
1738
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301739 mwifiex_dbg(adapter, INFO,
1740 "info: Read Index: %d\n", rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001741 skb_cmd = card->evt_buf_list[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001742 mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001743
Amitkumar Karward930fae2011-10-11 17:41:21 -07001744 /* Take the pointer and set it to event pointer in adapter
1745 and will return back after event handling callback */
1746 card->evt_buf_list[rdptr] = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001747 desc = card->evtbd_ring[rdptr];
1748 memset(desc, 0, sizeof(*desc));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001749
1750 event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
1751 adapter->event_cause = event;
1752 /* The first 4bytes will be the event transfer header
1753 len is 2 bytes followed by type which is 2 bytes */
1754 memcpy(&data_len, skb_cmd->data, sizeof(__le16));
1755 evt_len = le16_to_cpu(data_len);
Zhaoyang Liu868093a2015-05-12 00:48:19 +05301756 skb_trim(skb_cmd, evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001757 skb_pull(skb_cmd, INTF_HEADER_LEN);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301758 mwifiex_dbg(adapter, EVENT,
1759 "info: Event length: %d\n", evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001760
1761 if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
1762 memcpy(adapter->event_body, skb_cmd->data +
1763 MWIFIEX_EVENT_HEADER_LEN, evt_len -
1764 MWIFIEX_EVENT_HEADER_LEN);
1765
1766 adapter->event_received = true;
1767 adapter->event_skb = skb_cmd;
1768
1769 /* Do not update the event read pointer here, wait till the
1770 buffer is released. This is just to make things simpler,
1771 we need to find a better method of managing these buffers.
1772 */
Avinash Patil2703a662014-09-12 20:08:49 +05301773 } else {
1774 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1775 CPU_INTR_EVENT_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301776 mwifiex_dbg(adapter, ERROR,
1777 "Write register failed\n");
Avinash Patil2703a662014-09-12 20:08:49 +05301778 return -1;
1779 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001780 }
1781
1782 return 0;
1783}
1784
1785/*
1786 * Event processing complete handler
1787 */
1788static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
1789 struct sk_buff *skb)
1790{
1791 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001792 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001793 int ret = 0;
1794 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1795 u32 wrptr;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001796 struct mwifiex_evt_buf_desc *desc;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001797
1798 if (!skb)
1799 return 0;
1800
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001801 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301802 mwifiex_dbg(adapter, ERROR,
1803 "event_complete: Invalid rdptr 0x%x\n",
1804 rdptr);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001805 return -EINVAL;
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001806 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001807
1808 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001809 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301810 mwifiex_dbg(adapter, ERROR,
1811 "event_complete: failed to read reg->evt_wrptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001812 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001813 }
1814
1815 if (!card->evt_buf_list[rdptr]) {
1816 skb_push(skb, INTF_HEADER_LEN);
Amitkumar Karwar2728cec2015-07-22 04:53:45 -07001817 skb_put(skb, MAX_EVENT_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001818 if (mwifiex_map_pci_memory(adapter, skb,
1819 MAX_EVENT_SIZE,
1820 PCI_DMA_FROMDEVICE))
1821 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001822 card->evt_buf_list[rdptr] = skb;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001823 desc = card->evtbd_ring[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001824 desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile05dc3e2013-02-08 18:18:08 -08001825 desc->len = (u16)skb->len;
1826 desc->flags = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001827 skb = NULL;
1828 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301829 mwifiex_dbg(adapter, ERROR,
1830 "info: ERROR: buf still valid at index %d, <%p, %p>\n",
1831 rdptr, card->evt_buf_list[rdptr], skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001832 }
1833
1834 if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
1835 card->evtbd_rdptr = ((card->evtbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001836 reg->evt_rollover_ind) ^
1837 reg->evt_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001838 }
1839
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301840 mwifiex_dbg(adapter, EVENT,
1841 "info: Updated <Rd: 0x%x, Wr: 0x%x>",
1842 card->evtbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001843
Avinash Patildd04e6a2013-02-08 18:18:06 -08001844 /* Write the event ring read pointer in to reg->evt_rdptr */
1845 if (mwifiex_write_reg(adapter, reg->evt_rdptr,
1846 card->evtbd_rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301847 mwifiex_dbg(adapter, ERROR,
1848 "event_complete: failed to read reg->evt_rdptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001849 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001850 }
1851
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301852 mwifiex_dbg(adapter, EVENT,
1853 "info: Check Events Again\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001854 ret = mwifiex_pcie_process_event_ready(adapter);
1855
1856 return ret;
1857}
1858
1859/*
1860 * This function downloads the firmware to the card.
1861 *
1862 * Firmware is downloaded to the card in blocks. Every block download
1863 * is tested for CRC errors, and retried a number of times before
1864 * returning failure.
1865 */
1866static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
1867 struct mwifiex_fw_image *fw)
1868{
1869 int ret;
1870 u8 *firmware = fw->fw_buf;
1871 u32 firmware_len = fw->fw_len;
1872 u32 offset = 0;
1873 struct sk_buff *skb;
1874 u32 txlen, tx_blocks = 0, tries, len;
1875 u32 block_retry_cnt = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001876 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001877 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001878
1879 if (!firmware || !firmware_len) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301880 mwifiex_dbg(adapter, ERROR,
1881 "No firmware image found! Terminating download\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001882 return -1;
1883 }
1884
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301885 mwifiex_dbg(adapter, INFO,
1886 "info: Downloading FW image (%d bytes)\n",
1887 firmware_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001888
1889 if (mwifiex_pcie_disable_host_int(adapter)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301890 mwifiex_dbg(adapter, ERROR,
1891 "%s: Disabling interrupts failed.\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001892 return -1;
1893 }
1894
1895 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
1896 if (!skb) {
1897 ret = -ENOMEM;
1898 goto done;
1899 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001900
1901 /* Perform firmware data transfer */
1902 do {
1903 u32 ireg_intr = 0;
1904
1905 /* More data? */
1906 if (offset >= firmware_len)
1907 break;
1908
1909 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08001910 ret = mwifiex_read_reg(adapter, reg->cmd_size,
Amitkumar Karward930fae2011-10-11 17:41:21 -07001911 &len);
1912 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301913 mwifiex_dbg(adapter, FATAL,
1914 "Failed reading len from boot code\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001915 goto done;
1916 }
1917 if (len)
1918 break;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001919 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001920 }
1921
1922 if (!len) {
1923 break;
1924 } else if (len > MWIFIEX_UPLD_SIZE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301925 mwifiex_dbg(adapter, ERROR,
1926 "FW download failure @ %d, invalid length %d\n",
1927 offset, len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001928 ret = -1;
1929 goto done;
1930 }
1931
1932 txlen = len;
1933
1934 if (len & BIT(0)) {
1935 block_retry_cnt++;
1936 if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301937 mwifiex_dbg(adapter, ERROR,
1938 "FW download failure @ %d, over max\t"
1939 "retry count\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001940 ret = -1;
1941 goto done;
1942 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301943 mwifiex_dbg(adapter, ERROR,
1944 "FW CRC error indicated by the\t"
1945 "helper: len = 0x%04X, txlen = %d\n",
1946 len, txlen);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001947 len &= ~BIT(0);
1948 /* Setting this to 0 to resend from same offset */
1949 txlen = 0;
1950 } else {
1951 block_retry_cnt = 0;
1952 /* Set blocksize to transfer - checking for
1953 last block */
1954 if (firmware_len - offset < txlen)
1955 txlen = firmware_len - offset;
1956
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301957 mwifiex_dbg(adapter, INFO, ".");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001958
Avinash Patildd04e6a2013-02-08 18:18:06 -08001959 tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
1960 card->pcie.blksz_fw_dl;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001961
1962 /* Copy payload to buffer */
1963 memmove(skb->data, &firmware[offset], txlen);
1964 }
1965
1966 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001967 skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001968
1969 /* Send the boot command to device */
1970 if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301971 mwifiex_dbg(adapter, ERROR,
1972 "Failed to send firmware download command\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001973 ret = -1;
1974 goto done;
1975 }
Avinash Patilfc331462013-01-03 21:21:30 -08001976
Amitkumar Karward930fae2011-10-11 17:41:21 -07001977 /* Wait for the command done interrupt */
1978 do {
1979 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
1980 &ireg_intr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301981 mwifiex_dbg(adapter, ERROR,
1982 "%s: Failed to read\t"
1983 "interrupt status during fw dnld.\n",
1984 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001985 mwifiex_unmap_pci_memory(adapter, skb,
1986 PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001987 ret = -1;
1988 goto done;
1989 }
1990 } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
1991 CPU_INTR_DOOR_BELL);
Avinash Patilfc331462013-01-03 21:21:30 -08001992
Aaron Durbindbccc922014-02-07 16:25:50 -08001993 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001994
Amitkumar Karward930fae2011-10-11 17:41:21 -07001995 offset += txlen;
1996 } while (true);
1997
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301998 mwifiex_dbg(adapter, MSG,
1999 "info: FW download over, size %d bytes\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002000
2001 ret = 0;
2002
2003done:
2004 dev_kfree_skb_any(skb);
2005 return ret;
2006}
2007
2008/*
2009 * This function checks the firmware status in card.
2010 *
2011 * The winner interface is also determined by this function.
2012 */
2013static int
2014mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
2015{
2016 int ret = 0;
2017 u32 firmware_stat, winner_status;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002018 struct pcie_service_card *card = adapter->card;
2019 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002020 u32 tries;
2021
2022 /* Mask spurios interrupts */
2023 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002024 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302025 mwifiex_dbg(adapter, ERROR,
2026 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002027 return -1;
2028 }
2029
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302030 mwifiex_dbg(adapter, INFO,
2031 "Setting driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002032 if (mwifiex_write_reg(adapter, reg->drv_rdy,
2033 FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302034 mwifiex_dbg(adapter, ERROR,
2035 "Failed to write driver ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002036 return -1;
2037 }
2038
2039 /* Wait for firmware initialization event */
2040 for (tries = 0; tries < poll_num; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002041 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002042 &firmware_stat))
2043 ret = -1;
2044 else
2045 ret = 0;
2046 if (ret)
2047 continue;
2048 if (firmware_stat == FIRMWARE_READY_PCIE) {
2049 ret = 0;
2050 break;
2051 } else {
Amitkumar Karwara76b20e2013-07-22 19:17:53 -07002052 msleep(100);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002053 ret = -1;
2054 }
2055 }
2056
2057 if (ret) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002058 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002059 &winner_status))
2060 ret = -1;
2061 else if (!winner_status) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302062 mwifiex_dbg(adapter, INFO,
2063 "PCI-E is the winner\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002064 adapter->winner = 1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002065 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302066 mwifiex_dbg(adapter, ERROR,
2067 "PCI-E is not the winner <%#x,%d>, exit dnld\n",
2068 ret, adapter->winner);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002069 }
2070 }
2071
2072 return ret;
2073}
2074
2075/*
2076 * This function reads the interrupt status from card.
2077 */
2078static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
2079{
2080 u32 pcie_ireg;
2081 unsigned long flags;
2082
2083 if (!mwifiex_pcie_ok_to_access_hw(adapter))
2084 return;
2085
2086 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302087 mwifiex_dbg(adapter, ERROR, "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002088 return;
2089 }
2090
2091 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2092
2093 mwifiex_pcie_disable_host_int(adapter);
2094
2095 /* Clear the pending interrupts */
2096 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
2097 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302098 mwifiex_dbg(adapter, ERROR,
2099 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002100 return;
2101 }
2102 spin_lock_irqsave(&adapter->int_lock, flags);
2103 adapter->int_status |= pcie_ireg;
2104 spin_unlock_irqrestore(&adapter->int_lock, flags);
2105
Amitkumar Karwar1c975602014-02-18 15:41:56 -08002106 if (!adapter->pps_uapsd_mode &&
2107 adapter->ps_state == PS_STATE_SLEEP &&
2108 mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07002109 /* Potentially for PCIe we could get other
2110 * interrupts like shared. Don't change power
2111 * state until cookie is set */
Avinash Patilc24d9922013-03-22 21:49:06 -07002112 adapter->ps_state = PS_STATE_AWAKE;
2113 adapter->pm_wakeup_fw_try = false;
Amitkumar Karwar46361872014-12-31 02:36:41 -08002114 del_timer(&adapter->wakeup_timer);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002115 }
2116 }
2117}
2118
2119/*
2120 * Interrupt handler for PCIe root port
2121 *
2122 * This function reads the interrupt status from firmware and assigns
2123 * the main process in workqueue which will handle the interrupt.
2124 */
2125static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
2126{
2127 struct pci_dev *pdev = (struct pci_dev *)context;
2128 struct pcie_service_card *card;
2129 struct mwifiex_adapter *adapter;
2130
2131 if (!pdev) {
Xinming Hu91442432015-12-31 06:24:14 -08002132 pr_err("info: %s: pdev is NULL\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002133 goto exit;
2134 }
2135
Jingoo Hanb2a31202013-09-09 14:26:51 +09002136 card = pci_get_drvdata(pdev);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002137 if (!card || !card->adapter) {
Xinming Hu91442432015-12-31 06:24:14 -08002138 pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
2139 card ? card->adapter : NULL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002140 goto exit;
2141 }
2142 adapter = card->adapter;
2143
2144 if (adapter->surprise_removed)
2145 goto exit;
2146
2147 mwifiex_interrupt_status(adapter);
Shengzhen Lib2713f62015-03-13 17:37:54 +05302148 mwifiex_queue_main_work(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002149
2150exit:
2151 return IRQ_HANDLED;
2152}
2153
2154/*
2155 * This function checks the current interrupt status.
2156 *
2157 * The following interrupts are checked and handled by this function -
2158 * - Data sent
2159 * - Command sent
2160 * - Command received
2161 * - Packets received
2162 * - Events received
2163 *
2164 * In case of Rx packets received, the packets are uploaded from card to
2165 * host and processed accordingly.
2166 */
2167static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
2168{
2169 int ret;
Avinash Patil659c4782013-01-03 21:21:28 -08002170 u32 pcie_ireg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002171 unsigned long flags;
2172
2173 spin_lock_irqsave(&adapter->int_lock, flags);
2174 /* Clear out unused interrupts */
Avinash Patil659c4782013-01-03 21:21:28 -08002175 pcie_ireg = adapter->int_status;
2176 adapter->int_status = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002177 spin_unlock_irqrestore(&adapter->int_lock, flags);
2178
Avinash Patil659c4782013-01-03 21:21:28 -08002179 while (pcie_ireg & HOST_INTR_MASK) {
2180 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2181 pcie_ireg &= ~HOST_INTR_DNLD_DONE;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302182 mwifiex_dbg(adapter, INTR,
2183 "info: TX DNLD Done\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08002184 ret = mwifiex_pcie_send_data_complete(adapter);
2185 if (ret)
2186 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002187 }
Avinash Patil659c4782013-01-03 21:21:28 -08002188 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2189 pcie_ireg &= ~HOST_INTR_UPLD_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302190 mwifiex_dbg(adapter, INTR,
2191 "info: Rx DATA\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002192 ret = mwifiex_pcie_process_recv_data(adapter);
2193 if (ret)
2194 return ret;
2195 }
Avinash Patil659c4782013-01-03 21:21:28 -08002196 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2197 pcie_ireg &= ~HOST_INTR_EVENT_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302198 mwifiex_dbg(adapter, INTR,
2199 "info: Rx EVENT\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002200 ret = mwifiex_pcie_process_event_ready(adapter);
2201 if (ret)
2202 return ret;
2203 }
2204
Avinash Patil659c4782013-01-03 21:21:28 -08002205 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2206 pcie_ireg &= ~HOST_INTR_CMD_DONE;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002207 if (adapter->cmd_sent) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302208 mwifiex_dbg(adapter, INTR,
2209 "info: CMD sent Interrupt\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002210 adapter->cmd_sent = false;
2211 }
2212 /* Handle command response */
2213 ret = mwifiex_pcie_process_cmd_complete(adapter);
2214 if (ret)
2215 return ret;
2216 }
2217
2218 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2219 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2220 &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302221 mwifiex_dbg(adapter, ERROR,
2222 "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002223 return -1;
2224 }
2225
2226 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2227 if (mwifiex_write_reg(adapter,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002228 PCIE_HOST_INT_STATUS,
2229 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302230 mwifiex_dbg(adapter, ERROR,
2231 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002232 return -1;
2233 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002234 }
2235
2236 }
2237 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302238 mwifiex_dbg(adapter, INTR,
2239 "info: cmd_sent=%d data_sent=%d\n",
2240 adapter->cmd_sent, adapter->data_sent);
Avinash Patilb2fda1f2013-03-22 21:49:05 -07002241 if (adapter->ps_state != PS_STATE_SLEEP)
2242 mwifiex_pcie_enable_host_int(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002243
2244 return 0;
2245}
2246
2247/*
2248 * This function downloads data from driver to card.
2249 *
2250 * Both commands and data packets are transferred to the card by this
2251 * function.
2252 *
2253 * This function adds the PCIE specific header to the front of the buffer
2254 * before transferring. The header contains the length of the packet and
2255 * the type. The firmware handles the packets based upon this set type.
2256 */
2257static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
2258 struct sk_buff *skb,
2259 struct mwifiex_tx_param *tx_param)
2260{
Dan Carpenterfa161cb2011-11-07 19:31:45 -08002261 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302262 mwifiex_dbg(adapter, ERROR,
2263 "Passed NULL skb to %s\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002264 return -1;
2265 }
2266
2267 if (type == MWIFIEX_TYPE_DATA)
Avinash Patile7f767a2013-01-03 21:21:32 -08002268 return mwifiex_pcie_send_data(adapter, skb, tx_param);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002269 else if (type == MWIFIEX_TYPE_CMD)
2270 return mwifiex_pcie_send_cmd(adapter, skb);
2271
2272 return 0;
2273}
2274
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002275/* This function read/write firmware */
2276static enum rdwr_status
2277mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
2278{
2279 int ret, tries;
2280 u8 ctrl_data;
2281 struct pcie_service_card *card = adapter->card;
2282 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2283
2284 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
2285 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302286 mwifiex_dbg(adapter, ERROR,
2287 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002288 return RDWR_STATUS_FAILURE;
2289 }
2290
2291 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2292 mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
2293 if (ctrl_data == FW_DUMP_DONE)
2294 return RDWR_STATUS_SUCCESS;
2295 if (doneflag && ctrl_data == doneflag)
2296 return RDWR_STATUS_DONE;
2297 if (ctrl_data != FW_DUMP_HOST_READY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302298 mwifiex_dbg(adapter, WARN,
2299 "The ctrl reg was changed, re-try again!\n");
Amitkumar Karwar24716872014-09-18 08:04:01 -04002300 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
2301 FW_DUMP_HOST_READY);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002302 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302303 mwifiex_dbg(adapter, ERROR,
2304 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002305 return RDWR_STATUS_FAILURE;
2306 }
2307 }
2308 usleep_range(100, 200);
2309 }
2310
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302311 mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002312 return RDWR_STATUS_FAILURE;
2313}
2314
2315/* This function dump firmware memory to file */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002316static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002317{
2318 struct pcie_service_card *card = adapter->card;
2319 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2320 unsigned int reg, reg_start, reg_end;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002321 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
2322 enum rdwr_status stat;
2323 u32 memory_size;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002324 int ret;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002325
Avinash Patilb4e8aeb2015-02-11 23:12:26 +05302326 if (!card->pcie.can_dump_fw)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002327 return;
2328
2329 for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
2330 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
2331
2332 if (entry->mem_ptr) {
2333 vfree(entry->mem_ptr);
2334 entry->mem_ptr = NULL;
2335 }
2336 entry->mem_size = 0;
2337 }
2338
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302339 mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002340
2341 /* Read the number of the memories which will dump */
2342 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2343 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002344 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002345
2346 reg = creg->fw_dump_start;
2347 mwifiex_read_reg_byte(adapter, reg, &dump_num);
2348
2349 /* Read the length of every memory which will dump */
2350 for (idx = 0; idx < dump_num; idx++) {
2351 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
2352
2353 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2354 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002355 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002356
2357 memory_size = 0;
2358 reg = creg->fw_dump_start;
2359 for (i = 0; i < 4; i++) {
2360 mwifiex_read_reg_byte(adapter, reg, &read_reg);
2361 memory_size |= (read_reg << (i * 8));
2362 reg++;
2363 }
2364
2365 if (memory_size == 0) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302366 mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002367 ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
2368 FW_DUMP_READ_DONE);
2369 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302370 mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002371 return;
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002372 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002373 break;
2374 }
2375
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302376 mwifiex_dbg(adapter, DUMP,
2377 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002378 entry->mem_ptr = vmalloc(memory_size + 1);
2379 entry->mem_size = memory_size;
2380 if (!entry->mem_ptr) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302381 mwifiex_dbg(adapter, ERROR,
2382 "Vmalloc %s failed\n", entry->mem_name);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002383 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002384 }
2385 dbg_ptr = entry->mem_ptr;
2386 end_ptr = dbg_ptr + memory_size;
2387
2388 doneflag = entry->done_flag;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302389 mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
2390 entry->mem_name);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002391
2392 do {
2393 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2394 if (RDWR_STATUS_FAILURE == stat)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002395 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002396
2397 reg_start = creg->fw_dump_start;
2398 reg_end = creg->fw_dump_end;
2399 for (reg = reg_start; reg <= reg_end; reg++) {
2400 mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
Amitkumar Karwar24716872014-09-18 08:04:01 -04002401 if (dbg_ptr < end_ptr) {
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002402 dbg_ptr++;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002403 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302404 mwifiex_dbg(adapter, ERROR,
2405 "Allocated buf not enough\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002406 return;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002407 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002408 }
2409
2410 if (stat != RDWR_STATUS_DONE)
2411 continue;
2412
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302413 mwifiex_dbg(adapter, DUMP,
2414 "%s done: size=0x%tx\n",
2415 entry->mem_name, dbg_ptr - entry->mem_ptr);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002416 break;
2417 } while (true);
2418 }
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002419 mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002420}
2421
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002422static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
2423{
2424 mwifiex_drv_info_dump(adapter);
2425 mwifiex_pcie_fw_dump(adapter);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002426 mwifiex_upload_device_dump(adapter);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002427}
2428
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002429static unsigned long iface_work_flags;
2430static struct mwifiex_adapter *save_adapter;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002431static void mwifiex_pcie_work(struct work_struct *work)
2432{
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002433 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002434 &iface_work_flags))
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002435 mwifiex_pcie_device_dump_work(save_adapter);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002436}
2437
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002438static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002439/* This function dumps FW information */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002440static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002441{
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002442 save_adapter = adapter;
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002443 if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002444 return;
2445
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002446 set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002447
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002448 schedule_work(&pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002449}
2450
Amitkumar Karward930fae2011-10-11 17:41:21 -07002451/*
2452 * This function initializes the PCI-E host memory space, WCB rings, etc.
2453 *
2454 * The following initializations steps are followed -
2455 * - Allocate TXBD ring buffers
2456 * - Allocate RXBD ring buffers
2457 * - Allocate event BD ring buffers
2458 * - Allocate command response ring buffer
2459 * - Allocate sleep cookie buffer
2460 */
2461static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
2462{
2463 struct pcie_service_card *card = adapter->card;
2464 int ret;
2465 struct pci_dev *pdev = card->dev;
Avinash Patil52301a82013-02-12 14:38:32 -08002466 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002467
2468 pci_set_drvdata(pdev, card);
2469
2470 ret = pci_enable_device(pdev);
2471 if (ret)
2472 goto err_enable_dev;
2473
2474 pci_set_master(pdev);
2475
Xinming Hufdb1e282015-12-31 06:24:12 -08002476 pr_notice("try set_consistent_dma_mask(32)\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002477 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
2478 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002479 pr_err("set_dma_mask(32) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002480 goto err_set_dma_mask;
2481 }
2482
2483 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
2484 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002485 pr_err("set_consistent_dma_mask(64) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002486 goto err_set_dma_mask;
2487 }
2488
2489 ret = pci_request_region(pdev, 0, DRV_NAME);
2490 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002491 pr_err("req_reg(0) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002492 goto err_req_region0;
2493 }
2494 card->pci_mmap = pci_iomap(pdev, 0, 0);
2495 if (!card->pci_mmap) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002496 pr_err("iomap(0) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002497 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002498 goto err_iomap0;
2499 }
2500 ret = pci_request_region(pdev, 2, DRV_NAME);
2501 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002502 pr_err("req_reg(2) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002503 goto err_req_region2;
2504 }
2505 card->pci_mmap1 = pci_iomap(pdev, 2, 0);
2506 if (!card->pci_mmap1) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002507 pr_err("iomap(2) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002508 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002509 goto err_iomap2;
2510 }
2511
Xinming Hufdb1e282015-12-31 06:24:12 -08002512 pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
2513 card->pci_mmap, card->pci_mmap1);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002514
2515 card->cmdrsp_buf = NULL;
2516 ret = mwifiex_pcie_create_txbd_ring(adapter);
2517 if (ret)
2518 goto err_cre_txbd;
2519 ret = mwifiex_pcie_create_rxbd_ring(adapter);
2520 if (ret)
2521 goto err_cre_rxbd;
2522 ret = mwifiex_pcie_create_evtbd_ring(adapter);
2523 if (ret)
2524 goto err_cre_evtbd;
2525 ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
2526 if (ret)
2527 goto err_alloc_cmdbuf;
Avinash Patil52301a82013-02-12 14:38:32 -08002528 if (reg->sleep_cookie) {
2529 ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
2530 if (ret)
2531 goto err_alloc_cookie;
2532 } else {
2533 card->sleep_cookie_vbase = NULL;
2534 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002535 return ret;
2536
2537err_alloc_cookie:
2538 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2539err_alloc_cmdbuf:
2540 mwifiex_pcie_delete_evtbd_ring(adapter);
2541err_cre_evtbd:
2542 mwifiex_pcie_delete_rxbd_ring(adapter);
2543err_cre_rxbd:
2544 mwifiex_pcie_delete_txbd_ring(adapter);
2545err_cre_txbd:
2546 pci_iounmap(pdev, card->pci_mmap1);
2547err_iomap2:
2548 pci_release_region(pdev, 2);
2549err_req_region2:
2550 pci_iounmap(pdev, card->pci_mmap);
2551err_iomap0:
2552 pci_release_region(pdev, 0);
2553err_req_region0:
2554err_set_dma_mask:
2555 pci_disable_device(pdev);
2556err_enable_dev:
2557 pci_set_drvdata(pdev, NULL);
2558 return ret;
2559}
2560
2561/*
2562 * This function cleans up the allocated card buffers.
2563 *
2564 * The following are freed by this function -
2565 * - TXBD ring buffers
2566 * - RXBD ring buffers
2567 * - Event BD ring buffers
2568 * - Command response ring buffer
2569 * - Sleep cookie buffer
2570 */
2571static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
2572{
2573 struct pcie_service_card *card = adapter->card;
2574 struct pci_dev *pdev = card->dev;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002575 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002576
Amitkumar Karward930fae2011-10-11 17:41:21 -07002577 if (user_rmmod) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302578 mwifiex_dbg(adapter, INFO,
2579 "Clearing driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002580 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302581 mwifiex_dbg(adapter, ERROR,
2582 "Failed to write driver not-ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002583 }
2584
2585 if (pdev) {
2586 pci_iounmap(pdev, card->pci_mmap);
2587 pci_iounmap(pdev, card->pci_mmap1);
Yogesh Ashok Powar5b0d9b22013-04-23 16:49:48 -07002588 pci_disable_device(pdev);
Yogesh Ashok Powarc380aaf2013-04-23 16:49:47 -07002589 pci_release_region(pdev, 2);
2590 pci_release_region(pdev, 0);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002591 pci_set_drvdata(pdev, NULL);
2592 }
Amitkumar Karwar3c59e322013-11-14 19:10:41 -08002593 kfree(card);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002594}
2595
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002596static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
2597{
2598 int ret;
2599 struct pcie_service_card *card = adapter->card;
2600 struct pci_dev *pdev = card->dev;
2601
2602 if (pci_enable_msi(pdev) != 0)
2603 pci_disable_msi(pdev);
2604 else
2605 card->msi_enable = 1;
2606
2607 mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable);
2608
2609 ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
2610 "MRVL_PCIE", pdev);
2611 if (ret) {
2612 pr_err("request_irq failed: ret=%d\n", ret);
2613 adapter->card = NULL;
2614 return -1;
2615 }
2616
2617 return 0;
2618}
2619
Amitkumar Karward930fae2011-10-11 17:41:21 -07002620/*
2621 * This function registers the PCIE device.
2622 *
2623 * PCIE IRQ is claimed, block size is set and driver data is initialized.
2624 */
2625static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
2626{
Amitkumar Karward930fae2011-10-11 17:41:21 -07002627 struct pcie_service_card *card = adapter->card;
2628 struct pci_dev *pdev = card->dev;
2629
2630 /* save adapter pointer in card */
2631 card->adapter = adapter;
Xinming Hufdb1e282015-12-31 06:24:12 -08002632 adapter->dev = &pdev->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002633
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002634 if (mwifiex_pcie_request_irq(adapter))
Amitkumar Karward930fae2011-10-11 17:41:21 -07002635 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002636
Amitkumar Karwar828cf222014-02-27 19:35:13 -08002637 adapter->tx_buf_size = card->pcie.tx_buf_size;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002638 adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
2639 adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
Avinash Patildd04e6a2013-02-08 18:18:06 -08002640 strcpy(adapter->fw_name, card->pcie.firmware);
Avinash Patil1fe192d2015-01-23 17:09:19 +05302641 adapter->ext_scan = card->pcie.can_ext_scan;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002642
2643 return 0;
2644}
2645
2646/*
2647 * This function unregisters the PCIE device.
2648 *
2649 * The PCIE IRQ is released, the function is disabled and driver
2650 * data is set to null.
2651 */
2652static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
2653{
2654 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -08002655 const struct mwifiex_pcie_card_reg *reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002656
2657 if (card) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302658 mwifiex_dbg(adapter, INFO,
2659 "%s(): calling free_irq()\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002660 free_irq(card->dev->irq, card->dev);
Avinash Patilfc331462013-01-03 21:21:30 -08002661
Avinash Patil52301a82013-02-12 14:38:32 -08002662 reg = card->pcie.reg;
2663 if (reg->sleep_cookie)
2664 mwifiex_pcie_delete_sleep_cookie_buf(adapter);
2665
Avinash Patilfc331462013-01-03 21:21:30 -08002666 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2667 mwifiex_pcie_delete_evtbd_ring(adapter);
2668 mwifiex_pcie_delete_rxbd_ring(adapter);
2669 mwifiex_pcie_delete_txbd_ring(adapter);
2670 card->cmdrsp_buf = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002671 }
2672}
2673
2674static struct mwifiex_if_ops pcie_ops = {
2675 .init_if = mwifiex_pcie_init,
2676 .cleanup_if = mwifiex_pcie_cleanup,
2677 .check_fw_status = mwifiex_check_fw_status,
2678 .prog_fw = mwifiex_prog_fw_w_helper,
2679 .register_dev = mwifiex_register_dev,
2680 .unregister_dev = mwifiex_unregister_dev,
2681 .enable_int = mwifiex_pcie_enable_host_int,
2682 .process_int_status = mwifiex_process_int_status,
2683 .host_to_card = mwifiex_pcie_host_to_card,
2684 .wakeup = mwifiex_pm_wakeup_card,
2685 .wakeup_complete = mwifiex_pm_wakeup_card_complete,
2686
2687 /* PCIE specific */
2688 .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
2689 .event_complete = mwifiex_pcie_event_complete,
2690 .update_mp_end_port = NULL,
2691 .cleanup_mpa_buf = NULL,
Avinash Patilc6d1d872013-01-03 21:21:29 -08002692 .init_fw_port = mwifiex_pcie_init_fw_port,
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08002693 .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002694 .device_dump = mwifiex_pcie_device_dump,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002695};
2696
2697/*
2698 * This function initializes the PCIE driver module.
2699 *
2700 * This initiates the semaphore and registers the device with
2701 * PCIE bus.
2702 */
2703static int mwifiex_pcie_init_module(void)
2704{
2705 int ret;
2706
Avinash Patilca8f2112013-02-08 18:18:09 -08002707 pr_debug("Marvell PCIe Driver\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002708
2709 sema_init(&add_remove_card_sem, 1);
2710
2711 /* Clear the flag in case user removes the card. */
2712 user_rmmod = 0;
2713
2714 ret = pci_register_driver(&mwifiex_pcie);
2715 if (ret)
2716 pr_err("Driver register failed!\n");
2717 else
2718 pr_debug("info: Driver registered successfully!\n");
2719
2720 return ret;
2721}
2722
2723/*
2724 * This function cleans up the PCIE driver.
2725 *
2726 * The following major steps are followed for cleanup -
2727 * - Resume the device if its suspended
2728 * - Disconnect the device if connected
2729 * - Shutdown the firmware
2730 * - Unregister the device from PCIE bus.
2731 */
2732static void mwifiex_pcie_cleanup_module(void)
2733{
2734 if (!down_interruptible(&add_remove_card_sem))
2735 up(&add_remove_card_sem);
2736
2737 /* Set the flag as user is removing this module. */
2738 user_rmmod = 1;
2739
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002740 cancel_work_sync(&pcie_work);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002741 pci_unregister_driver(&mwifiex_pcie);
2742}
2743
2744module_init(mwifiex_pcie_init_module);
2745module_exit(mwifiex_pcie_cleanup_module);
2746
2747MODULE_AUTHOR("Marvell International Ltd.");
2748MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
2749MODULE_VERSION(PCIE_VERSION);
2750MODULE_LICENSE("GPL v2");
Avinash Patilca8f2112013-02-08 18:18:09 -08002751MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
2752MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07002753MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME);