blob: b9fe1813cc4febeb446b0a543e3ef52f9706d714 [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);
Xinming Huaf051482016-02-02 22:05:03 -0800326 if (*data == 0xffffffff)
327 return 0xffffffff;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700328
329 return 0;
330}
331
Amitkumar Karwar92c25382014-06-19 21:38:52 -0700332/* This function reads u8 data from PCIE card register. */
333static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
334 int reg, u8 *data)
335{
336 struct pcie_service_card *card = adapter->card;
337
338 *data = ioread8(card->pci_mmap1 + reg);
339
340 return 0;
341}
342
Amitkumar Karward930fae2011-10-11 17:41:21 -0700343/*
Avinash Patilc0880a22013-03-22 21:49:07 -0700344 * This function adds delay loop to ensure FW is awake before proceeding.
Amitkumar Karward930fae2011-10-11 17:41:21 -0700345 */
Avinash Patilc0880a22013-03-22 21:49:07 -0700346static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700347{
348 int i = 0;
349
Avinash Patilc0880a22013-03-22 21:49:07 -0700350 while (mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700351 i++;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -0700352 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700353 /* 50ms max wait */
Avinash Patil3e7a4ff2013-02-25 16:01:34 -0800354 if (i == 5000)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700355 break;
356 }
357
Avinash Patilc0880a22013-03-22 21:49:07 -0700358 return;
359}
360
Avinash Patilc4bc9802014-03-18 22:19:17 -0700361static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
362 u32 max_delay_loop_cnt)
363{
364 struct pcie_service_card *card = adapter->card;
365 u8 *buffer;
366 u32 sleep_cookie, count;
367
368 for (count = 0; count < max_delay_loop_cnt; count++) {
369 buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
370 sleep_cookie = *(u32 *)buffer;
371
372 if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530373 mwifiex_dbg(adapter, INFO,
374 "sleep cookie found at count %d\n", count);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700375 break;
376 }
377 usleep_range(20, 30);
378 }
379
380 if (count >= max_delay_loop_cnt)
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530381 mwifiex_dbg(adapter, INFO,
382 "max count reached while accessing sleep cookie\n");
Avinash Patilc4bc9802014-03-18 22:19:17 -0700383}
384
Avinash Patilc0880a22013-03-22 21:49:07 -0700385/* This function wakes up the card by reading fw_status register. */
386static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
387{
388 u32 fw_status;
389 struct pcie_service_card *card = adapter->card;
390 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
391
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530392 mwifiex_dbg(adapter, EVENT,
393 "event: Wakeup device...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700394
Avinash Patilc0880a22013-03-22 21:49:07 -0700395 if (reg->sleep_cookie)
396 mwifiex_pcie_dev_wakeup_delay(adapter);
397
398 /* Reading fw_status register will wakeup device */
399 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530400 mwifiex_dbg(adapter, ERROR,
401 "Reading fw_status register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700402 return -1;
403 }
404
Avinash Patilc0880a22013-03-22 21:49:07 -0700405 if (reg->sleep_cookie) {
406 mwifiex_pcie_dev_wakeup_delay(adapter);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530407 mwifiex_dbg(adapter, INFO,
408 "PCIE wakeup: Setting PS_STATE_AWAKE\n");
Avinash Patilc0880a22013-03-22 21:49:07 -0700409 adapter->ps_state = PS_STATE_AWAKE;
410 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700411
412 return 0;
413}
414
415/*
416 * This function is called after the card has woken up.
417 *
418 * The card configuration register is reset.
419 */
420static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
421{
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530422 mwifiex_dbg(adapter, CMD,
423 "cmd: Wakeup device completed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700424
425 return 0;
426}
427
428/*
429 * This function disables the host interrupt.
430 *
431 * The host interrupt mask is read, the disable bit is reset and
432 * written back to the card host interrupt mask register.
433 */
434static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
435{
436 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
437 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
438 0x00000000)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530439 mwifiex_dbg(adapter, ERROR,
440 "Disable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700441 return -1;
442 }
443 }
444
445 return 0;
446}
447
448/*
449 * This function enables the host interrupt.
450 *
451 * The host interrupt enable mask is written to the card
452 * host interrupt mask register.
453 */
454static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
455{
456 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
457 /* Simply write the mask to the register */
458 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
459 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530460 mwifiex_dbg(adapter, ERROR,
461 "Enable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700462 return -1;
463 }
464 }
465
466 return 0;
467}
468
469/*
Avinash Patil07324842013-02-08 18:18:07 -0800470 * This function initializes TX buffer ring descriptors
471 */
472static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
473{
474 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800475 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800476 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800477 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800478 int i;
479
480 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
481 card->tx_buf_list[i] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -0800482 if (reg->pfu_enabled) {
483 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
484 (sizeof(*desc2) * i);
485 desc2 = card->txbd_ring[i];
486 memset(desc2, 0, sizeof(*desc2));
487 } else {
488 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
489 (sizeof(*desc) * i);
490 desc = card->txbd_ring[i];
491 memset(desc, 0, sizeof(*desc));
492 }
Avinash Patil07324842013-02-08 18:18:07 -0800493 }
494
495 return 0;
496}
497
498/* This function initializes RX buffer ring descriptors. Each SKB is allocated
499 * here and after mapping PCI memory, its physical address is assigned to
500 * PCIE Rx buffer descriptor's physical address.
501 */
502static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
503{
504 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800505 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800506 struct sk_buff *skb;
507 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800508 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800509 dma_addr_t buf_pa;
510 int i;
511
512 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
513 /* Allocate skb here so that firmware can DMA data from it */
Avinash Patil62159942015-03-13 17:37:52 +0530514 skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
515 GFP_KERNEL | GFP_DMA);
Avinash Patil07324842013-02-08 18:18:07 -0800516 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530517 mwifiex_dbg(adapter, ERROR,
518 "Unable to allocate skb for RX ring.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800519 kfree(card->rxbd_ring_vbase);
520 return -ENOMEM;
521 }
522
523 if (mwifiex_map_pci_memory(adapter, skb,
524 MWIFIEX_RX_DATA_BUF_SIZE,
525 PCI_DMA_FROMDEVICE))
526 return -1;
527
Aaron Durbindbccc922014-02-07 16:25:50 -0800528 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800529
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530530 mwifiex_dbg(adapter, INFO,
531 "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
532 skb, skb->len, skb->data, (u32)buf_pa,
533 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800534
535 card->rx_buf_list[i] = skb;
Avinash Patilca8f2112013-02-08 18:18:09 -0800536 if (reg->pfu_enabled) {
537 card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
538 (sizeof(*desc2) * i);
539 desc2 = card->rxbd_ring[i];
540 desc2->paddr = buf_pa;
541 desc2->len = (u16)skb->len;
542 desc2->frag_len = (u16)skb->len;
543 desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
544 desc2->offset = 0;
545 } else {
546 card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
547 (sizeof(*desc) * i));
548 desc = card->rxbd_ring[i];
549 desc->paddr = buf_pa;
550 desc->len = (u16)skb->len;
551 desc->flags = 0;
552 }
Avinash Patil07324842013-02-08 18:18:07 -0800553 }
554
555 return 0;
556}
557
558/* This function initializes event buffer ring descriptors. Each SKB is
559 * allocated here and after mapping PCI memory, its physical address is assigned
560 * to PCIE Rx buffer descriptor's physical address
561 */
562static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
563{
564 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800565 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800566 struct sk_buff *skb;
567 dma_addr_t buf_pa;
568 int i;
569
570 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
571 /* Allocate skb here so that firmware can DMA data from it */
572 skb = dev_alloc_skb(MAX_EVENT_SIZE);
573 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530574 mwifiex_dbg(adapter, ERROR,
575 "Unable to allocate skb for EVENT buf.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800576 kfree(card->evtbd_ring_vbase);
577 return -ENOMEM;
578 }
579 skb_put(skb, MAX_EVENT_SIZE);
580
581 if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
582 PCI_DMA_FROMDEVICE))
583 return -1;
584
Aaron Durbindbccc922014-02-07 16:25:50 -0800585 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800586
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530587 mwifiex_dbg(adapter, EVENT,
588 "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
589 skb, skb->len, skb->data, (u32)buf_pa,
590 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800591
592 card->evt_buf_list[i] = skb;
593 card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
594 (sizeof(*desc) * i));
Avinash Patil07324842013-02-08 18:18:07 -0800595 desc = card->evtbd_ring[i];
596 desc->paddr = buf_pa;
597 desc->len = (u16)skb->len;
598 desc->flags = 0;
599 }
600
601 return 0;
602}
603
604/* This function cleans up TX buffer rings. If any of the buffer list has valid
605 * SKB address, associated SKB is freed.
606 */
607static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
608{
609 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800610 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800611 struct sk_buff *skb;
612 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800613 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800614 int i;
615
616 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800617 if (reg->pfu_enabled) {
618 desc2 = card->txbd_ring[i];
619 if (card->tx_buf_list[i]) {
620 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800621 mwifiex_unmap_pci_memory(adapter, skb,
622 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800623 dev_kfree_skb_any(skb);
624 }
625 memset(desc2, 0, sizeof(*desc2));
626 } else {
627 desc = card->txbd_ring[i];
628 if (card->tx_buf_list[i]) {
629 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800630 mwifiex_unmap_pci_memory(adapter, skb,
631 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800632 dev_kfree_skb_any(skb);
633 }
634 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800635 }
636 card->tx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800637 }
638
639 return;
640}
641
642/* This function cleans up RX buffer rings. If any of the buffer list has valid
643 * SKB address, associated SKB is freed.
644 */
645static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
646{
647 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800648 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800649 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800650 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800651 struct sk_buff *skb;
652 int i;
653
654 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800655 if (reg->pfu_enabled) {
656 desc2 = card->rxbd_ring[i];
657 if (card->rx_buf_list[i]) {
658 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800659 mwifiex_unmap_pci_memory(adapter, skb,
660 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800661 dev_kfree_skb_any(skb);
662 }
663 memset(desc2, 0, sizeof(*desc2));
664 } else {
665 desc = card->rxbd_ring[i];
666 if (card->rx_buf_list[i]) {
667 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800668 mwifiex_unmap_pci_memory(adapter, skb,
669 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800670 dev_kfree_skb_any(skb);
671 }
672 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800673 }
Avinash Patilca8f2112013-02-08 18:18:09 -0800674 card->rx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800675 }
676
677 return;
678}
679
680/* This function cleans up event buffer rings. If any of the buffer list has
681 * valid SKB address, associated SKB is freed.
682 */
683static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
684{
685 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800686 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800687 struct sk_buff *skb;
688 int i;
689
690 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
691 desc = card->evtbd_ring[i];
692 if (card->evt_buf_list[i]) {
693 skb = card->evt_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800694 mwifiex_unmap_pci_memory(adapter, skb,
695 PCI_DMA_FROMDEVICE);
Avinash Patil07324842013-02-08 18:18:07 -0800696 dev_kfree_skb_any(skb);
697 }
698 card->evt_buf_list[i] = NULL;
699 memset(desc, 0, sizeof(*desc));
700 }
701
702 return;
703}
704
705/* This function creates buffer descriptor ring for TX
Amitkumar Karward930fae2011-10-11 17:41:21 -0700706 */
707static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
708{
709 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800710 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700711
712 /*
713 * driver maintaines the write pointer and firmware maintaines the read
714 * pointer. The write pointer starts at 0 (zero) while the read pointer
715 * starts at zero with rollover bit set
716 */
717 card->txbd_wrptr = 0;
Avinash Patilca8f2112013-02-08 18:18:09 -0800718
719 if (reg->pfu_enabled)
720 card->txbd_rdptr = 0;
721 else
722 card->txbd_rdptr |= reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700723
724 /* allocate shared memory for the BD ring and divide the same in to
725 several descriptors */
Avinash Patilca8f2112013-02-08 18:18:09 -0800726 if (reg->pfu_enabled)
727 card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
728 MWIFIEX_MAX_TXRX_BD;
729 else
730 card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
731 MWIFIEX_MAX_TXRX_BD;
732
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530733 mwifiex_dbg(adapter, INFO,
734 "info: txbd_ring: Allocating %d bytes\n",
735 card->txbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800736 card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
737 card->txbd_ring_size,
738 &card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700739 if (!card->txbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530740 mwifiex_dbg(adapter, ERROR,
741 "allocate consistent memory (%d bytes) failed!\n",
742 card->txbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800743 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700744 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530745 mwifiex_dbg(adapter, DATA,
746 "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
747 card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
748 (u32)((u64)card->txbd_ring_pbase >> 32),
749 card->txbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700750
Avinash Patil07324842013-02-08 18:18:07 -0800751 return mwifiex_init_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700752}
753
754static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
755{
756 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800757 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700758
Avinash Patil07324842013-02-08 18:18:07 -0800759 mwifiex_cleanup_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700760
Avinash Patilfc331462013-01-03 21:21:30 -0800761 if (card->txbd_ring_vbase)
762 pci_free_consistent(card->dev, card->txbd_ring_size,
763 card->txbd_ring_vbase,
764 card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700765 card->txbd_ring_size = 0;
766 card->txbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800767 card->txbd_rdptr = 0 | reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700768 card->txbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800769 card->txbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700770
771 return 0;
772}
773
774/*
775 * This function creates buffer descriptor ring for RX
776 */
777static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
778{
779 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800780 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700781
782 /*
783 * driver maintaines the read pointer and firmware maintaines the write
784 * pointer. The write pointer starts at 0 (zero) while the read pointer
785 * starts at zero with rollover bit set
786 */
787 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800788 card->rxbd_rdptr = reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700789
Avinash Patilca8f2112013-02-08 18:18:09 -0800790 if (reg->pfu_enabled)
791 card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
792 MWIFIEX_MAX_TXRX_BD;
793 else
794 card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
795 MWIFIEX_MAX_TXRX_BD;
796
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530797 mwifiex_dbg(adapter, INFO,
798 "info: rxbd_ring: Allocating %d bytes\n",
799 card->rxbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800800 card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
801 card->rxbd_ring_size,
802 &card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700803 if (!card->rxbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530804 mwifiex_dbg(adapter, ERROR,
805 "allocate consistent memory (%d bytes) failed!\n",
806 card->rxbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800807 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700808 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700809
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530810 mwifiex_dbg(adapter, DATA,
811 "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
812 card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
813 (u32)((u64)card->rxbd_ring_pbase >> 32),
814 card->rxbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700815
Avinash Patil07324842013-02-08 18:18:07 -0800816 return mwifiex_init_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700817}
818
819/*
820 * This function deletes Buffer descriptor ring for RX
821 */
822static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
823{
824 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800825 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700826
Avinash Patil07324842013-02-08 18:18:07 -0800827 mwifiex_cleanup_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700828
Avinash Patilfc331462013-01-03 21:21:30 -0800829 if (card->rxbd_ring_vbase)
830 pci_free_consistent(card->dev, card->rxbd_ring_size,
831 card->rxbd_ring_vbase,
832 card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700833 card->rxbd_ring_size = 0;
834 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800835 card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700836 card->rxbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800837 card->rxbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700838
839 return 0;
840}
841
842/*
843 * This function creates buffer descriptor ring for Events
844 */
845static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
846{
847 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800848 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700849
850 /*
851 * driver maintaines the read pointer and firmware maintaines the write
852 * pointer. The write pointer starts at 0 (zero) while the read pointer
853 * starts at zero with rollover bit set
854 */
855 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800856 card->evtbd_rdptr = reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700857
Avinash Patile05dc3e2013-02-08 18:18:08 -0800858 card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
Avinash Patilca8f2112013-02-08 18:18:09 -0800859 MWIFIEX_MAX_EVT_BD;
860
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530861 mwifiex_dbg(adapter, INFO,
862 "info: evtbd_ring: Allocating %d bytes\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700863 card->evtbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800864 card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
865 card->evtbd_ring_size,
866 &card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700867 if (!card->evtbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530868 mwifiex_dbg(adapter, ERROR,
869 "allocate consistent memory (%d bytes) failed!\n",
870 card->evtbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800871 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700872 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700873
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530874 mwifiex_dbg(adapter, EVENT,
875 "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
876 card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
877 (u32)((u64)card->evtbd_ring_pbase >> 32),
878 card->evtbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700879
Avinash Patil07324842013-02-08 18:18:07 -0800880 return mwifiex_pcie_init_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700881}
882
883/*
884 * This function deletes Buffer descriptor ring for Events
885 */
886static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
887{
888 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800889 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700890
Avinash Patil07324842013-02-08 18:18:07 -0800891 mwifiex_cleanup_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700892
Avinash Patilfc331462013-01-03 21:21:30 -0800893 if (card->evtbd_ring_vbase)
894 pci_free_consistent(card->dev, card->evtbd_ring_size,
895 card->evtbd_ring_vbase,
896 card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700897 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800898 card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700899 card->evtbd_ring_size = 0;
900 card->evtbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800901 card->evtbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700902
903 return 0;
904}
905
906/*
907 * This function allocates a buffer for CMDRSP
908 */
909static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
910{
911 struct pcie_service_card *card = adapter->card;
912 struct sk_buff *skb;
913
914 /* Allocate memory for receiving command response data */
915 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
916 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530917 mwifiex_dbg(adapter, ERROR,
918 "Unable to allocate skb for command response data.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700919 return -ENOMEM;
920 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700921 skb_put(skb, MWIFIEX_UPLD_SIZE);
Avinash Patilfc331462013-01-03 21:21:30 -0800922 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
923 PCI_DMA_FROMDEVICE))
924 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700925
Avinash Patilfc331462013-01-03 21:21:30 -0800926 card->cmdrsp_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700927
928 return 0;
929}
930
931/*
932 * This function deletes a buffer for CMDRSP
933 */
934static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
935{
936 struct pcie_service_card *card;
937
938 if (!adapter)
939 return 0;
940
941 card = adapter->card;
942
Avinash Patilfc331462013-01-03 21:21:30 -0800943 if (card && card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800944 mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
945 PCI_DMA_FROMDEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700946 dev_kfree_skb_any(card->cmdrsp_buf);
Avinash Patilfc331462013-01-03 21:21:30 -0800947 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700948
Avinash Patilfc331462013-01-03 21:21:30 -0800949 if (card && card->cmd_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -0800950 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
951 PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -0800952 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700953 return 0;
954}
955
956/*
957 * This function allocates a buffer for sleep cookie
958 */
959static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
960{
Amitkumar Karward930fae2011-10-11 17:41:21 -0700961 struct pcie_service_card *card = adapter->card;
962
Avinash Patilfc331462013-01-03 21:21:30 -0800963 card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
964 &card->sleep_cookie_pbase);
965 if (!card->sleep_cookie_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530966 mwifiex_dbg(adapter, ERROR,
967 "pci_alloc_consistent failed!\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700968 return -ENOMEM;
969 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700970 /* Init val of Sleep Cookie */
Avinash Patilfc331462013-01-03 21:21:30 -0800971 *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700972
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530973 mwifiex_dbg(adapter, INFO,
974 "alloc_scook: sleep cookie=0x%x\n",
975 *((u32 *)card->sleep_cookie_vbase));
Amitkumar Karward930fae2011-10-11 17:41:21 -0700976
977 return 0;
978}
979
980/*
981 * This function deletes buffer for sleep cookie
982 */
983static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
984{
985 struct pcie_service_card *card;
986
987 if (!adapter)
988 return 0;
989
990 card = adapter->card;
991
Avinash Patilfc331462013-01-03 21:21:30 -0800992 if (card && card->sleep_cookie_vbase) {
993 pci_free_consistent(card->dev, sizeof(u32),
994 card->sleep_cookie_vbase,
995 card->sleep_cookie_pbase);
996 card->sleep_cookie_vbase = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700997 }
998
999 return 0;
1000}
1001
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001002/* This function flushes the TX buffer descriptor ring
1003 * This function defined as handler is also called while cleaning TXRX
1004 * during disconnect/ bss stop.
1005 */
1006static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
1007{
1008 struct pcie_service_card *card = adapter->card;
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001009
Avinash Patil48f4d912013-02-20 21:12:58 -08001010 if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001011 card->txbd_flush = 1;
1012 /* write pointer already set at last send
1013 * send dnld-rdy intr again, wait for completion.
1014 */
1015 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1016 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301017 mwifiex_dbg(adapter, ERROR,
1018 "failed to assert dnld-rdy interrupt.\n");
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001019 return -1;
1020 }
1021 }
1022 return 0;
1023}
1024
Amitkumar Karward930fae2011-10-11 17:41:21 -07001025/*
Avinash Patile7f767a2013-01-03 21:21:32 -08001026 * This function unmaps and frees downloaded data buffer
Amitkumar Karward930fae2011-10-11 17:41:21 -07001027 */
Avinash Patile7f767a2013-01-03 21:21:32 -08001028static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001029{
Avinash Patile7f767a2013-01-03 21:21:32 -08001030 struct sk_buff *skb;
Avinash Patilca8f2112013-02-08 18:18:09 -08001031 u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001032 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001033 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001034 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001035 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001036
1037 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1038 mwifiex_pm_wakeup_card(adapter);
1039
1040 /* Read the TX ring read pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001041 if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301042 mwifiex_dbg(adapter, ERROR,
1043 "SEND COMP: failed to read reg->tx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001044 return -1;
1045 }
1046
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301047 mwifiex_dbg(adapter, DATA,
1048 "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
1049 card->txbd_rdptr, rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001050
Avinash Patilca8f2112013-02-08 18:18:09 -08001051 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001052 /* free from previous txbd_rdptr to current txbd_rdptr */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001053 while (((card->txbd_rdptr & reg->tx_mask) !=
1054 (rdptr & reg->tx_mask)) ||
1055 ((card->txbd_rdptr & reg->tx_rollover_ind) !=
1056 (rdptr & reg->tx_rollover_ind))) {
Avinash Patilca8f2112013-02-08 18:18:09 -08001057 wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
1058 reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001059
1060 skb = card->tx_buf_list[wrdoneidx];
Aaron Durbindbccc922014-02-07 16:25:50 -08001061
Avinash Patile7f767a2013-01-03 21:21:32 -08001062 if (skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301063 mwifiex_dbg(adapter, DATA,
1064 "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
1065 skb, wrdoneidx);
Aaron Durbindbccc922014-02-07 16:25:50 -08001066 mwifiex_unmap_pci_memory(adapter, skb,
1067 PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001068
1069 unmap_count++;
1070
1071 if (card->txbd_flush)
1072 mwifiex_write_data_complete(adapter, skb, 0,
1073 -1);
1074 else
1075 mwifiex_write_data_complete(adapter, skb, 0, 0);
1076 }
1077
1078 card->tx_buf_list[wrdoneidx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001079
1080 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001081 desc2 = card->txbd_ring[wrdoneidx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001082 memset(desc2, 0, sizeof(*desc2));
1083 } else {
1084 desc = card->txbd_ring[wrdoneidx];
1085 memset(desc, 0, sizeof(*desc));
1086 }
1087 switch (card->dev->device) {
1088 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1089 card->txbd_rdptr++;
1090 break;
1091 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001092 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001093 card->txbd_rdptr += reg->ring_tx_start_ptr;
1094 break;
1095 }
1096
Avinash Patile7f767a2013-01-03 21:21:32 -08001097
Avinash Patildd04e6a2013-02-08 18:18:06 -08001098 if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
Avinash Patile7f767a2013-01-03 21:21:32 -08001099 card->txbd_rdptr = ((card->txbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001100 reg->tx_rollover_ind) ^
1101 reg->tx_rollover_ind);
Avinash Patile7f767a2013-01-03 21:21:32 -08001102 }
1103
1104 if (unmap_count)
1105 adapter->data_sent = false;
1106
1107 if (card->txbd_flush) {
Avinash Patil3d482032013-02-15 21:37:54 -08001108 if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
Avinash Patile7f767a2013-01-03 21:21:32 -08001109 card->txbd_flush = 0;
1110 else
1111 mwifiex_clean_pcie_ring_buf(adapter);
1112 }
1113
1114 return 0;
1115}
1116
1117/* This function sends data buffer to device. First 4 bytes of payload
1118 * are filled with payload length and payload type. Then this payload
1119 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
1120 * Download ready interrupt to FW is deffered if Tx ring is not full and
1121 * additional payload can be accomodated.
Avinash Patil8d767dc2014-05-13 19:50:13 -07001122 * Caller must ensure tx_param parameter to this function is not NULL.
Avinash Patile7f767a2013-01-03 21:21:32 -08001123 */
1124static int
1125mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
1126 struct mwifiex_tx_param *tx_param)
1127{
1128 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001129 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001130 u32 wrindx, num_tx_buffs, rx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001131 int ret;
1132 dma_addr_t buf_pa;
Bing Zhao99310782013-03-04 16:27:55 -08001133 struct mwifiex_pcie_buf_desc *desc = NULL;
1134 struct mwifiex_pfu_buf_desc *desc2 = NULL;
Avinash Patile7f767a2013-01-03 21:21:32 -08001135 __le16 *tmp;
1136
1137 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301138 mwifiex_dbg(adapter, ERROR,
1139 "%s(): invalid parameter <%p, %#x>\n",
1140 __func__, skb->data, skb->len);
Avinash Patile7f767a2013-01-03 21:21:32 -08001141 return -1;
1142 }
1143
1144 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1145 mwifiex_pm_wakeup_card(adapter);
1146
Avinash Patilca8f2112013-02-08 18:18:09 -08001147 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301148 mwifiex_dbg(adapter, DATA,
1149 "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
Avinash Patile7f767a2013-01-03 21:21:32 -08001150 card->txbd_rdptr, card->txbd_wrptr);
1151 if (mwifiex_pcie_txbd_not_full(card)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001152 u8 *payload;
1153
1154 adapter->data_sent = true;
Avinash Patile7f767a2013-01-03 21:21:32 -08001155 payload = skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001156 tmp = (__le16 *)&payload[0];
1157 *tmp = cpu_to_le16((u16)skb->len);
1158 tmp = (__le16 *)&payload[2];
1159 *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
Avinash Patile7f767a2013-01-03 21:21:32 -08001160
Aaron Durbindbccc922014-02-07 16:25:50 -08001161 if (mwifiex_map_pci_memory(adapter, skb, skb->len,
Avinash Patile7f767a2013-01-03 21:21:32 -08001162 PCI_DMA_TODEVICE))
1163 return -1;
1164
Avinash Patilca8f2112013-02-08 18:18:09 -08001165 wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
Aaron Durbindbccc922014-02-07 16:25:50 -08001166 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile7f767a2013-01-03 21:21:32 -08001167 card->tx_buf_list[wrindx] = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001168
Avinash Patilca8f2112013-02-08 18:18:09 -08001169 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001170 desc2 = card->txbd_ring[wrindx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001171 desc2->paddr = buf_pa;
1172 desc2->len = (u16)skb->len;
1173 desc2->frag_len = (u16)skb->len;
1174 desc2->offset = 0;
1175 desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1176 MWIFIEX_BD_FLAG_LAST_DESC;
1177 } else {
1178 desc = card->txbd_ring[wrindx];
1179 desc->paddr = buf_pa;
1180 desc->len = (u16)skb->len;
1181 desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1182 MWIFIEX_BD_FLAG_LAST_DESC;
1183 }
1184
1185 switch (card->dev->device) {
1186 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1187 card->txbd_wrptr++;
1188 break;
1189 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001190 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001191 card->txbd_wrptr += reg->ring_tx_start_ptr;
1192 break;
1193 }
1194
1195 if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001196 card->txbd_wrptr = ((card->txbd_wrptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001197 reg->tx_rollover_ind) ^
1198 reg->tx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001199
Avinash Patilca8f2112013-02-08 18:18:09 -08001200 rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001201 /* Write the TX ring write pointer in to reg->tx_wrptr */
1202 if (mwifiex_write_reg(adapter, reg->tx_wrptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001203 card->txbd_wrptr | rx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301204 mwifiex_dbg(adapter, ERROR,
1205 "SEND DATA: failed to write reg->tx_wrptr\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001206 ret = -1;
1207 goto done_unmap;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001208 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001209 if ((mwifiex_pcie_txbd_not_full(card)) &&
1210 tx_param->next_pkt_len) {
1211 /* have more packets and TxBD still can hold more */
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301212 mwifiex_dbg(adapter, DATA,
1213 "SEND DATA: delay dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001214 adapter->data_sent = false;
1215 } else {
1216 /* Send the TX ready interrupt */
1217 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1218 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301219 mwifiex_dbg(adapter, ERROR,
1220 "SEND DATA: failed to assert dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001221 ret = -1;
1222 goto done_unmap;
1223 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001224 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301225 mwifiex_dbg(adapter, DATA,
1226 "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
1227 "%#x> and sent packet to firmware successfully\n",
1228 card->txbd_rdptr, card->txbd_wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001229 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301230 mwifiex_dbg(adapter, DATA,
1231 "info: TX Ring full, can't send packets to fw\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001232 adapter->data_sent = true;
1233 /* Send the TX ready interrupt */
1234 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1235 CPU_INTR_DNLD_RDY))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301236 mwifiex_dbg(adapter, ERROR,
1237 "SEND DATA: failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001238 return -EBUSY;
1239 }
1240
Avinash Patile7f767a2013-01-03 21:21:32 -08001241 return -EINPROGRESS;
1242done_unmap:
Aaron Durbindbccc922014-02-07 16:25:50 -08001243 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001244 card->tx_buf_list[wrindx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001245 if (reg->pfu_enabled)
1246 memset(desc2, 0, sizeof(*desc2));
1247 else
1248 memset(desc, 0, sizeof(*desc));
1249
Avinash Patile7f767a2013-01-03 21:21:32 -08001250 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001251}
1252
1253/*
1254 * This function handles received buffer ring and
1255 * dispatches packets to upper
1256 */
1257static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
1258{
1259 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001260 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001261 u32 wrptr, rd_index, tx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001262 dma_addr_t buf_pa;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001263 int ret = 0;
1264 struct sk_buff *skb_tmp = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001265 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001266 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001267
Avinash Patile7f767a2013-01-03 21:21:32 -08001268 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1269 mwifiex_pm_wakeup_card(adapter);
1270
Amitkumar Karward930fae2011-10-11 17:41:21 -07001271 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001272 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301273 mwifiex_dbg(adapter, ERROR,
1274 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001275 ret = -1;
1276 goto done;
1277 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001278 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001279
Avinash Patildd04e6a2013-02-08 18:18:06 -08001280 while (((wrptr & reg->rx_mask) !=
1281 (card->rxbd_rdptr & reg->rx_mask)) ||
1282 ((wrptr & reg->rx_rollover_ind) ==
1283 (card->rxbd_rdptr & reg->rx_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001284 struct sk_buff *skb_data;
1285 u16 rx_len;
Avinash Patile7f767a2013-01-03 21:21:32 -08001286 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001287
Avinash Patildd04e6a2013-02-08 18:18:06 -08001288 rd_index = card->rxbd_rdptr & reg->rx_mask;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001289 skb_data = card->rx_buf_list[rd_index];
1290
Amitkumar Karwarbb8e6a12014-02-18 15:41:55 -08001291 /* If skb allocation was failed earlier for Rx packet,
1292 * rx_buf_list[rd_index] would have been left with a NULL.
1293 */
1294 if (!skb_data)
1295 return -ENOMEM;
1296
Aaron Durbindbccc922014-02-07 16:25:50 -08001297 mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001298 card->rx_buf_list[rd_index] = NULL;
1299
Amitkumar Karward930fae2011-10-11 17:41:21 -07001300 /* Get data length from interface header -
Avinash Patile7f767a2013-01-03 21:21:32 -08001301 * first 2 bytes for len, next 2 bytes is for type
1302 */
1303 pkt_len = *((__le16 *)skb_data->data);
1304 rx_len = le16_to_cpu(pkt_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301305 if (WARN_ON(rx_len <= INTF_HEADER_LEN ||
1306 rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301307 mwifiex_dbg(adapter, ERROR,
1308 "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
1309 rx_len, card->rxbd_rdptr, wrptr);
Avinash Patil42a028a2014-09-12 20:08:47 +05301310 dev_kfree_skb_any(skb_data);
1311 } else {
1312 skb_put(skb_data, rx_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301313 mwifiex_dbg(adapter, DATA,
1314 "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
1315 card->rxbd_rdptr, wrptr, rx_len);
Avinash Patil42a028a2014-09-12 20:08:47 +05301316 skb_pull(skb_data, INTF_HEADER_LEN);
Avinash Patil6e251172014-09-12 20:08:59 +05301317 if (adapter->rx_work_enabled) {
Avinash Patil6e251172014-09-12 20:08:59 +05301318 skb_queue_tail(&adapter->rx_data_q, skb_data);
Avinash Patil6e251172014-09-12 20:08:59 +05301319 adapter->data_received = true;
1320 atomic_inc(&adapter->rx_pending);
1321 } else {
1322 mwifiex_handle_rx_packet(adapter, skb_data);
1323 }
Avinash Patil42a028a2014-09-12 20:08:47 +05301324 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001325
Avinash Patil62159942015-03-13 17:37:52 +05301326 skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
1327 GFP_KERNEL | GFP_DMA);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001328 if (!skb_tmp) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301329 mwifiex_dbg(adapter, ERROR,
1330 "Unable to allocate skb.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001331 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001332 }
1333
Avinash Patile7f767a2013-01-03 21:21:32 -08001334 if (mwifiex_map_pci_memory(adapter, skb_tmp,
1335 MWIFIEX_RX_DATA_BUF_SIZE,
1336 PCI_DMA_FROMDEVICE))
1337 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001338
Aaron Durbindbccc922014-02-07 16:25:50 -08001339 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
Avinash Patile7f767a2013-01-03 21:21:32 -08001340
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301341 mwifiex_dbg(adapter, INFO,
1342 "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
1343 skb_tmp, rd_index);
Avinash Patile7f767a2013-01-03 21:21:32 -08001344 card->rx_buf_list[rd_index] = skb_tmp;
Avinash Patilca8f2112013-02-08 18:18:09 -08001345
1346 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001347 desc2 = card->rxbd_ring[rd_index];
Avinash Patilca8f2112013-02-08 18:18:09 -08001348 desc2->paddr = buf_pa;
1349 desc2->len = skb_tmp->len;
1350 desc2->frag_len = skb_tmp->len;
1351 desc2->offset = 0;
1352 desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
1353 } else {
1354 desc = card->rxbd_ring[rd_index];
1355 desc->paddr = buf_pa;
1356 desc->len = skb_tmp->len;
1357 desc->flags = 0;
1358 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001359
Avinash Patildd04e6a2013-02-08 18:18:06 -08001360 if ((++card->rxbd_rdptr & reg->rx_mask) ==
Amitkumar Karward930fae2011-10-11 17:41:21 -07001361 MWIFIEX_MAX_TXRX_BD) {
1362 card->rxbd_rdptr = ((card->rxbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001363 reg->rx_rollover_ind) ^
1364 reg->rx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001365 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301366 mwifiex_dbg(adapter, DATA,
1367 "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
1368 card->rxbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001369
Avinash Patilca8f2112013-02-08 18:18:09 -08001370 tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001371 /* Write the RX ring read pointer in to reg->rx_rdptr */
1372 if (mwifiex_write_reg(adapter, reg->rx_rdptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001373 card->rxbd_rdptr | tx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301374 mwifiex_dbg(adapter, DATA,
1375 "RECV DATA: failed to write reg->rx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001376 ret = -1;
1377 goto done;
1378 }
1379
1380 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001381 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301382 mwifiex_dbg(adapter, ERROR,
1383 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001384 ret = -1;
1385 goto done;
1386 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301387 mwifiex_dbg(adapter, DATA,
1388 "info: RECV DATA: Rcvd packet from fw successfully\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001389 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001390 }
1391
1392done:
Amitkumar Karward930fae2011-10-11 17:41:21 -07001393 return ret;
1394}
1395
1396/*
1397 * This function downloads the boot command to device
1398 */
1399static int
1400mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1401{
Avinash Patilfc331462013-01-03 21:21:30 -08001402 dma_addr_t buf_pa;
1403 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001404 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001405
Avinash Patilfc331462013-01-03 21:21:30 -08001406 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301407 mwifiex_dbg(adapter, ERROR,
1408 "Invalid parameter in %s <%p. len %d>\n",
1409 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001410 return -1;
1411 }
1412
Avinash Patilfc331462013-01-03 21:21:30 -08001413 if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
1414 return -1;
1415
Aaron Durbindbccc922014-02-07 16:25:50 -08001416 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patilfc331462013-01-03 21:21:30 -08001417
Avinash Patildd04e6a2013-02-08 18:18:06 -08001418 /* Write the lower 32bits of the physical address to low command
1419 * address scratch register
1420 */
1421 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301422 mwifiex_dbg(adapter, ERROR,
1423 "%s: failed to write download command to boot code.\n",
1424 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001425 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001426 return -1;
1427 }
1428
Avinash Patildd04e6a2013-02-08 18:18:06 -08001429 /* Write the upper 32bits of the physical address to high command
1430 * address scratch register
1431 */
1432 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001433 (u32)((u64)buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301434 mwifiex_dbg(adapter, ERROR,
1435 "%s: failed to write download command to boot code.\n",
1436 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001437 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001438 return -1;
1439 }
1440
Avinash Patildd04e6a2013-02-08 18:18:06 -08001441 /* Write the command length to cmd_size scratch register */
1442 if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301443 mwifiex_dbg(adapter, ERROR,
1444 "%s: failed to write command len to cmd_size scratch reg\n",
1445 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001446 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001447 return -1;
1448 }
1449
1450 /* Ring the door bell */
1451 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1452 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301453 mwifiex_dbg(adapter, ERROR,
1454 "%s: failed to assert door-bell intr\n", __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001455 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001456 return -1;
1457 }
1458
1459 return 0;
1460}
1461
Avinash Patilc6d1d872013-01-03 21:21:29 -08001462/* This function init rx port in firmware which in turn enables to receive data
1463 * from device before transmitting any packet.
1464 */
1465static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
1466{
1467 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001468 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001469 int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patilc6d1d872013-01-03 21:21:29 -08001470
Avinash Patildd04e6a2013-02-08 18:18:06 -08001471 /* Write the RX ring read pointer in to reg->rx_rdptr */
Avinash Patilca8f2112013-02-08 18:18:09 -08001472 if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
1473 tx_wrap)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301474 mwifiex_dbg(adapter, ERROR,
1475 "RECV DATA: failed to write reg->rx_rdptr\n");
Avinash Patilc6d1d872013-01-03 21:21:29 -08001476 return -1;
1477 }
1478 return 0;
1479}
1480
1481/* This function downloads commands to the device
Amitkumar Karward930fae2011-10-11 17:41:21 -07001482 */
1483static int
1484mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1485{
1486 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001487 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001488 int ret = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001489 dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
1490 u8 *payload = (u8 *)skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001491
1492 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301493 mwifiex_dbg(adapter, ERROR,
1494 "Invalid parameter in %s <%p, %#x>\n",
1495 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001496 return -1;
1497 }
1498
1499 /* Make sure a command response buffer is available */
1500 if (!card->cmdrsp_buf) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301501 mwifiex_dbg(adapter, ERROR,
1502 "No response buffer available, send command failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001503 return -EBUSY;
1504 }
1505
Avinash Patilfc331462013-01-03 21:21:30 -08001506 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1507 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001508
1509 adapter->cmd_sent = true;
Avinash Patilfc331462013-01-03 21:21:30 -08001510
1511 *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
1512 *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
1513
1514 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
1515 return -1;
1516
1517 card->cmd_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001518
1519 /* To send a command, the driver will:
1520 1. Write the 64bit physical address of the data buffer to
Avinash Patildd04e6a2013-02-08 18:18:06 -08001521 cmd response address low + cmd response address high
Amitkumar Karward930fae2011-10-11 17:41:21 -07001522 2. Ring the door bell (i.e. set the door bell interrupt)
1523
1524 In response to door bell interrupt, the firmware will perform
1525 the DMA of the command packet (first header to obtain the total
1526 length and then rest of the command).
1527 */
1528
1529 if (card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001530 cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001531 /* Write the lower 32bits of the cmdrsp buffer physical
1532 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001533 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
Avinash Patilfc331462013-01-03 21:21:30 -08001534 (u32)cmdrsp_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301535 mwifiex_dbg(adapter, ERROR,
1536 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001537 ret = -1;
1538 goto done;
1539 }
1540 /* Write the upper 32bits of the cmdrsp buffer physical
1541 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001542 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001543 (u32)((u64)cmdrsp_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301544 mwifiex_dbg(adapter, ERROR,
1545 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001546 ret = -1;
1547 goto done;
1548 }
1549 }
1550
Aaron Durbindbccc922014-02-07 16:25:50 -08001551 cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001552 /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
1553 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
1554 (u32)cmd_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301555 mwifiex_dbg(adapter, ERROR,
1556 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001557 ret = -1;
1558 goto done;
1559 }
Avinash Patildd04e6a2013-02-08 18:18:06 -08001560 /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
1561 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001562 (u32)((u64)cmd_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301563 mwifiex_dbg(adapter, ERROR,
1564 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001565 ret = -1;
1566 goto done;
1567 }
1568
Avinash Patildd04e6a2013-02-08 18:18:06 -08001569 /* Write the command length to reg->cmd_size */
1570 if (mwifiex_write_reg(adapter, reg->cmd_size,
1571 card->cmd_buf->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301572 mwifiex_dbg(adapter, ERROR,
1573 "Failed to write cmd len to reg->cmd_size\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001574 ret = -1;
1575 goto done;
1576 }
1577
1578 /* Ring the door bell */
1579 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1580 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301581 mwifiex_dbg(adapter, ERROR,
1582 "Failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001583 ret = -1;
1584 goto done;
1585 }
1586
1587done:
1588 if (ret)
1589 adapter->cmd_sent = false;
1590
1591 return 0;
1592}
1593
1594/*
1595 * This function handles command complete interrupt
1596 */
1597static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
1598{
1599 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001600 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001601 struct sk_buff *skb = card->cmdrsp_buf;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001602 int count = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001603 u16 rx_len;
1604 __le16 pkt_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001605
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301606 mwifiex_dbg(adapter, CMD,
1607 "info: Rx CMD Response\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001608
Aaron Durbindbccc922014-02-07 16:25:50 -08001609 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001610
Aaron Durbin189b3292014-02-07 16:25:51 -08001611 /* Unmap the command as a response has been received. */
1612 if (card->cmd_buf) {
1613 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1614 PCI_DMA_TODEVICE);
1615 card->cmd_buf = NULL;
1616 }
1617
Avinash Patilfc331462013-01-03 21:21:30 -08001618 pkt_len = *((__le16 *)skb->data);
1619 rx_len = le16_to_cpu(pkt_len);
1620 skb_trim(skb, rx_len);
1621 skb_pull(skb, INTF_HEADER_LEN);
1622
Amitkumar Karward930fae2011-10-11 17:41:21 -07001623 if (!adapter->curr_cmd) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001624 if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001625 mwifiex_process_sleep_confirm_resp(adapter, skb->data,
1626 skb->len);
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001627 mwifiex_pcie_enable_host_int(adapter);
1628 if (mwifiex_write_reg(adapter,
1629 PCIE_CPU_INT_EVENT,
1630 CPU_INTR_SLEEP_CFM_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301631 mwifiex_dbg(adapter, ERROR,
1632 "Write register failed\n");
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001633 return -1;
1634 }
Avinash Patilc4bc9802014-03-18 22:19:17 -07001635 mwifiex_delay_for_sleep_cookie(adapter,
1636 MWIFIEX_MAX_DELAY_COUNT);
Avinash Patil52301a82013-02-12 14:38:32 -08001637 while (reg->sleep_cookie && (count++ < 10) &&
1638 mwifiex_pcie_ok_to_access_hw(adapter))
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001639 usleep_range(50, 60);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001640 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301641 mwifiex_dbg(adapter, ERROR,
1642 "There is no command but got cmdrsp\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001643 }
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001644 memcpy(adapter->upld_buf, skb->data,
1645 min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
Avinash Patil0f49d642013-03-20 17:56:23 -07001646 skb_push(skb, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001647 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1648 PCI_DMA_FROMDEVICE))
1649 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001650 } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001651 adapter->curr_cmd->resp_skb = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001652 adapter->cmd_resp_received = true;
1653 /* Take the pointer and set it to CMD node and will
1654 return in the response complete callback */
1655 card->cmdrsp_buf = NULL;
1656
1657 /* Clear the cmd-rsp buffer address in scratch registers. This
1658 will prevent firmware from writing to the same response
1659 buffer again. */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001660 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301661 mwifiex_dbg(adapter, ERROR,
1662 "cmd_done: failed to clear cmd_rsp_addr_lo\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001663 return -1;
1664 }
1665 /* Write the upper 32bits of the cmdrsp buffer physical
1666 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001667 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301668 mwifiex_dbg(adapter, ERROR,
1669 "cmd_done: failed to clear cmd_rsp_addr_hi\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001670 return -1;
1671 }
1672 }
1673
1674 return 0;
1675}
1676
1677/*
1678 * Command Response processing complete handler
1679 */
1680static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
1681 struct sk_buff *skb)
1682{
1683 struct pcie_service_card *card = adapter->card;
1684
1685 if (skb) {
1686 card->cmdrsp_buf = skb;
1687 skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
Avinash Patilfc331462013-01-03 21:21:30 -08001688 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1689 PCI_DMA_FROMDEVICE))
1690 return -1;
1691 }
1692
Amitkumar Karward930fae2011-10-11 17:41:21 -07001693 return 0;
1694}
1695
1696/*
1697 * This function handles firmware event ready interrupt
1698 */
1699static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
1700{
1701 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001702 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001703 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1704 u32 wrptr, event;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001705 struct mwifiex_evt_buf_desc *desc;
Avinash Patilfc331462013-01-03 21:21:30 -08001706
1707 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1708 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001709
1710 if (adapter->event_received) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301711 mwifiex_dbg(adapter, EVENT,
1712 "info: Event being processed,\t"
1713 "do not process this interrupt just yet\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001714 return 0;
1715 }
1716
1717 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301718 mwifiex_dbg(adapter, ERROR,
1719 "info: Invalid read pointer...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001720 return -1;
1721 }
1722
1723 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001724 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301725 mwifiex_dbg(adapter, ERROR,
1726 "EventReady: failed to read reg->evt_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001727 return -1;
1728 }
1729
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301730 mwifiex_dbg(adapter, EVENT,
1731 "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
1732 card->evtbd_rdptr, wrptr);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001733 if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
1734 & MWIFIEX_EVTBD_MASK)) ||
Avinash Patildd04e6a2013-02-08 18:18:06 -08001735 ((wrptr & reg->evt_rollover_ind) ==
1736 (card->evtbd_rdptr & reg->evt_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001737 struct sk_buff *skb_cmd;
1738 __le16 data_len = 0;
1739 u16 evt_len;
1740
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301741 mwifiex_dbg(adapter, INFO,
1742 "info: Read Index: %d\n", rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001743 skb_cmd = card->evt_buf_list[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001744 mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001745
Amitkumar Karward930fae2011-10-11 17:41:21 -07001746 /* Take the pointer and set it to event pointer in adapter
1747 and will return back after event handling callback */
1748 card->evt_buf_list[rdptr] = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001749 desc = card->evtbd_ring[rdptr];
1750 memset(desc, 0, sizeof(*desc));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001751
1752 event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
1753 adapter->event_cause = event;
1754 /* The first 4bytes will be the event transfer header
1755 len is 2 bytes followed by type which is 2 bytes */
1756 memcpy(&data_len, skb_cmd->data, sizeof(__le16));
1757 evt_len = le16_to_cpu(data_len);
Zhaoyang Liu868093a2015-05-12 00:48:19 +05301758 skb_trim(skb_cmd, evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001759 skb_pull(skb_cmd, INTF_HEADER_LEN);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301760 mwifiex_dbg(adapter, EVENT,
1761 "info: Event length: %d\n", evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001762
1763 if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
1764 memcpy(adapter->event_body, skb_cmd->data +
1765 MWIFIEX_EVENT_HEADER_LEN, evt_len -
1766 MWIFIEX_EVENT_HEADER_LEN);
1767
1768 adapter->event_received = true;
1769 adapter->event_skb = skb_cmd;
1770
1771 /* Do not update the event read pointer here, wait till the
1772 buffer is released. This is just to make things simpler,
1773 we need to find a better method of managing these buffers.
1774 */
Avinash Patil2703a662014-09-12 20:08:49 +05301775 } else {
1776 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1777 CPU_INTR_EVENT_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301778 mwifiex_dbg(adapter, ERROR,
1779 "Write register failed\n");
Avinash Patil2703a662014-09-12 20:08:49 +05301780 return -1;
1781 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001782 }
1783
1784 return 0;
1785}
1786
1787/*
1788 * Event processing complete handler
1789 */
1790static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
1791 struct sk_buff *skb)
1792{
1793 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001794 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001795 int ret = 0;
1796 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1797 u32 wrptr;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001798 struct mwifiex_evt_buf_desc *desc;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001799
1800 if (!skb)
1801 return 0;
1802
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001803 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301804 mwifiex_dbg(adapter, ERROR,
1805 "event_complete: Invalid rdptr 0x%x\n",
1806 rdptr);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001807 return -EINVAL;
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001808 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001809
1810 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001811 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301812 mwifiex_dbg(adapter, ERROR,
1813 "event_complete: failed to read reg->evt_wrptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001814 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001815 }
1816
1817 if (!card->evt_buf_list[rdptr]) {
1818 skb_push(skb, INTF_HEADER_LEN);
Amitkumar Karwar2728cec2015-07-22 04:53:45 -07001819 skb_put(skb, MAX_EVENT_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001820 if (mwifiex_map_pci_memory(adapter, skb,
1821 MAX_EVENT_SIZE,
1822 PCI_DMA_FROMDEVICE))
1823 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001824 card->evt_buf_list[rdptr] = skb;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001825 desc = card->evtbd_ring[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001826 desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile05dc3e2013-02-08 18:18:08 -08001827 desc->len = (u16)skb->len;
1828 desc->flags = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001829 skb = NULL;
1830 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301831 mwifiex_dbg(adapter, ERROR,
1832 "info: ERROR: buf still valid at index %d, <%p, %p>\n",
1833 rdptr, card->evt_buf_list[rdptr], skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001834 }
1835
1836 if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
1837 card->evtbd_rdptr = ((card->evtbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001838 reg->evt_rollover_ind) ^
1839 reg->evt_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001840 }
1841
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301842 mwifiex_dbg(adapter, EVENT,
1843 "info: Updated <Rd: 0x%x, Wr: 0x%x>",
1844 card->evtbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001845
Avinash Patildd04e6a2013-02-08 18:18:06 -08001846 /* Write the event ring read pointer in to reg->evt_rdptr */
1847 if (mwifiex_write_reg(adapter, reg->evt_rdptr,
1848 card->evtbd_rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301849 mwifiex_dbg(adapter, ERROR,
1850 "event_complete: failed to read reg->evt_rdptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001851 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001852 }
1853
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301854 mwifiex_dbg(adapter, EVENT,
1855 "info: Check Events Again\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001856 ret = mwifiex_pcie_process_event_ready(adapter);
1857
1858 return ret;
1859}
1860
1861/*
1862 * This function downloads the firmware to the card.
1863 *
1864 * Firmware is downloaded to the card in blocks. Every block download
1865 * is tested for CRC errors, and retried a number of times before
1866 * returning failure.
1867 */
1868static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
1869 struct mwifiex_fw_image *fw)
1870{
1871 int ret;
1872 u8 *firmware = fw->fw_buf;
1873 u32 firmware_len = fw->fw_len;
1874 u32 offset = 0;
1875 struct sk_buff *skb;
1876 u32 txlen, tx_blocks = 0, tries, len;
1877 u32 block_retry_cnt = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001878 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001879 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001880
1881 if (!firmware || !firmware_len) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301882 mwifiex_dbg(adapter, ERROR,
1883 "No firmware image found! Terminating download\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001884 return -1;
1885 }
1886
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301887 mwifiex_dbg(adapter, INFO,
1888 "info: Downloading FW image (%d bytes)\n",
1889 firmware_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001890
1891 if (mwifiex_pcie_disable_host_int(adapter)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301892 mwifiex_dbg(adapter, ERROR,
1893 "%s: Disabling interrupts failed.\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001894 return -1;
1895 }
1896
1897 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
1898 if (!skb) {
1899 ret = -ENOMEM;
1900 goto done;
1901 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001902
1903 /* Perform firmware data transfer */
1904 do {
1905 u32 ireg_intr = 0;
1906
1907 /* More data? */
1908 if (offset >= firmware_len)
1909 break;
1910
1911 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08001912 ret = mwifiex_read_reg(adapter, reg->cmd_size,
Amitkumar Karward930fae2011-10-11 17:41:21 -07001913 &len);
1914 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301915 mwifiex_dbg(adapter, FATAL,
1916 "Failed reading len from boot code\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001917 goto done;
1918 }
1919 if (len)
1920 break;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001921 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001922 }
1923
1924 if (!len) {
1925 break;
1926 } else if (len > MWIFIEX_UPLD_SIZE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301927 mwifiex_dbg(adapter, ERROR,
1928 "FW download failure @ %d, invalid length %d\n",
1929 offset, len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001930 ret = -1;
1931 goto done;
1932 }
1933
1934 txlen = len;
1935
1936 if (len & BIT(0)) {
1937 block_retry_cnt++;
1938 if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301939 mwifiex_dbg(adapter, ERROR,
1940 "FW download failure @ %d, over max\t"
1941 "retry count\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001942 ret = -1;
1943 goto done;
1944 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301945 mwifiex_dbg(adapter, ERROR,
1946 "FW CRC error indicated by the\t"
1947 "helper: len = 0x%04X, txlen = %d\n",
1948 len, txlen);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001949 len &= ~BIT(0);
1950 /* Setting this to 0 to resend from same offset */
1951 txlen = 0;
1952 } else {
1953 block_retry_cnt = 0;
1954 /* Set blocksize to transfer - checking for
1955 last block */
1956 if (firmware_len - offset < txlen)
1957 txlen = firmware_len - offset;
1958
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301959 mwifiex_dbg(adapter, INFO, ".");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001960
Avinash Patildd04e6a2013-02-08 18:18:06 -08001961 tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
1962 card->pcie.blksz_fw_dl;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001963
1964 /* Copy payload to buffer */
1965 memmove(skb->data, &firmware[offset], txlen);
1966 }
1967
1968 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001969 skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001970
1971 /* Send the boot command to device */
1972 if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301973 mwifiex_dbg(adapter, ERROR,
1974 "Failed to send firmware download command\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001975 ret = -1;
1976 goto done;
1977 }
Avinash Patilfc331462013-01-03 21:21:30 -08001978
Amitkumar Karward930fae2011-10-11 17:41:21 -07001979 /* Wait for the command done interrupt */
1980 do {
1981 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
1982 &ireg_intr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301983 mwifiex_dbg(adapter, ERROR,
1984 "%s: Failed to read\t"
1985 "interrupt status during fw dnld.\n",
1986 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001987 mwifiex_unmap_pci_memory(adapter, skb,
1988 PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001989 ret = -1;
1990 goto done;
1991 }
1992 } while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
1993 CPU_INTR_DOOR_BELL);
Avinash Patilfc331462013-01-03 21:21:30 -08001994
Aaron Durbindbccc922014-02-07 16:25:50 -08001995 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001996
Amitkumar Karward930fae2011-10-11 17:41:21 -07001997 offset += txlen;
1998 } while (true);
1999
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302000 mwifiex_dbg(adapter, MSG,
2001 "info: FW download over, size %d bytes\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002002
2003 ret = 0;
2004
2005done:
2006 dev_kfree_skb_any(skb);
2007 return ret;
2008}
2009
2010/*
2011 * This function checks the firmware status in card.
Amitkumar Karward930fae2011-10-11 17:41:21 -07002012 */
2013static int
2014mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
2015{
2016 int ret = 0;
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002017 u32 firmware_stat;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002018 struct pcie_service_card *card = adapter->card;
2019 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002020 u32 tries;
2021
2022 /* Mask spurios interrupts */
2023 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002024 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302025 mwifiex_dbg(adapter, ERROR,
2026 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002027 return -1;
2028 }
2029
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302030 mwifiex_dbg(adapter, INFO,
2031 "Setting driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002032 if (mwifiex_write_reg(adapter, reg->drv_rdy,
2033 FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302034 mwifiex_dbg(adapter, ERROR,
2035 "Failed to write driver ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002036 return -1;
2037 }
2038
2039 /* Wait for firmware initialization event */
2040 for (tries = 0; tries < poll_num; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002041 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002042 &firmware_stat))
2043 ret = -1;
2044 else
2045 ret = 0;
2046 if (ret)
2047 continue;
2048 if (firmware_stat == FIRMWARE_READY_PCIE) {
2049 ret = 0;
2050 break;
2051 } else {
Amitkumar Karwara76b20e2013-07-22 19:17:53 -07002052 msleep(100);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002053 ret = -1;
2054 }
2055 }
2056
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002057 return ret;
2058}
2059
2060/* This function checks if WLAN is the winner.
2061 */
2062static int
2063mwifiex_check_winner_status(struct mwifiex_adapter *adapter)
2064{
2065 u32 winner = 0;
2066 int ret = 0;
2067 struct pcie_service_card *card = adapter->card;
2068 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2069
2070 if (mwifiex_read_reg(adapter, reg->fw_status, &winner)) {
2071 ret = -1;
2072 } else if (!winner) {
2073 mwifiex_dbg(adapter, INFO, "PCI-E is the winner\n");
2074 adapter->winner = 1;
2075 } else {
2076 mwifiex_dbg(adapter, ERROR,
2077 "PCI-E is not the winner <%#x,%d>, exit dnld\n",
2078 ret, adapter->winner);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002079 }
2080
2081 return ret;
2082}
2083
2084/*
2085 * This function reads the interrupt status from card.
2086 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002087static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter,
2088 int msg_id)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002089{
2090 u32 pcie_ireg;
2091 unsigned long flags;
Xinming Hu99074fc2016-01-11 02:16:40 -08002092 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002093
2094 if (!mwifiex_pcie_ok_to_access_hw(adapter))
2095 return;
2096
Xinming Hu99074fc2016-01-11 02:16:40 -08002097 if (card->msix_enable && msg_id >= 0) {
2098 pcie_ireg = BIT(msg_id);
2099 } else {
2100 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2101 &pcie_ireg)) {
2102 mwifiex_dbg(adapter, ERROR, "Read register failed\n");
2103 return;
2104 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002105
Xinming Hu99074fc2016-01-11 02:16:40 -08002106 if ((pcie_ireg == 0xFFFFFFFF) || !pcie_ireg)
2107 return;
2108
Amitkumar Karward930fae2011-10-11 17:41:21 -07002109
2110 mwifiex_pcie_disable_host_int(adapter);
2111
2112 /* Clear the pending interrupts */
2113 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
2114 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302115 mwifiex_dbg(adapter, ERROR,
2116 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002117 return;
2118 }
Xinming Hu99074fc2016-01-11 02:16:40 -08002119 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002120
Xinming Hu99074fc2016-01-11 02:16:40 -08002121 if (!adapter->pps_uapsd_mode &&
2122 adapter->ps_state == PS_STATE_SLEEP &&
2123 mwifiex_pcie_ok_to_access_hw(adapter)) {
2124 /* Potentially for PCIe we could get other
2125 * interrupts like shared. Don't change power
2126 * state until cookie is set
2127 */
2128 adapter->ps_state = PS_STATE_AWAKE;
2129 adapter->pm_wakeup_fw_try = false;
2130 del_timer(&adapter->wakeup_timer);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002131 }
Shengzhen Lidc896b12016-01-12 05:43:16 -08002132
2133 spin_lock_irqsave(&adapter->int_lock, flags);
2134 adapter->int_status |= pcie_ireg;
2135 spin_unlock_irqrestore(&adapter->int_lock, flags);
2136 mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002137}
2138
2139/*
2140 * Interrupt handler for PCIe root port
2141 *
2142 * This function reads the interrupt status from firmware and assigns
2143 * the main process in workqueue which will handle the interrupt.
2144 */
2145static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
2146{
Xinming Hu99074fc2016-01-11 02:16:40 -08002147 struct mwifiex_msix_context *ctx = context;
2148 struct pci_dev *pdev = ctx->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002149 struct pcie_service_card *card;
2150 struct mwifiex_adapter *adapter;
2151
2152 if (!pdev) {
Xinming Hu91442432015-12-31 06:24:14 -08002153 pr_err("info: %s: pdev is NULL\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002154 goto exit;
2155 }
2156
Jingoo Hanb2a31202013-09-09 14:26:51 +09002157 card = pci_get_drvdata(pdev);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002158 if (!card || !card->adapter) {
Xinming Hu91442432015-12-31 06:24:14 -08002159 pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
2160 card ? card->adapter : NULL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002161 goto exit;
2162 }
2163 adapter = card->adapter;
2164
2165 if (adapter->surprise_removed)
2166 goto exit;
2167
Xinming Hu99074fc2016-01-11 02:16:40 -08002168 if (card->msix_enable)
2169 mwifiex_interrupt_status(adapter, ctx->msg_id);
2170 else
2171 mwifiex_interrupt_status(adapter, -1);
2172
Shengzhen Lib2713f62015-03-13 17:37:54 +05302173 mwifiex_queue_main_work(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002174
2175exit:
2176 return IRQ_HANDLED;
2177}
2178
2179/*
2180 * This function checks the current interrupt status.
2181 *
2182 * The following interrupts are checked and handled by this function -
2183 * - Data sent
2184 * - Command sent
2185 * - Command received
2186 * - Packets received
2187 * - Events received
2188 *
2189 * In case of Rx packets received, the packets are uploaded from card to
2190 * host and processed accordingly.
2191 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002192static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002193{
2194 int ret;
Avinash Patil659c4782013-01-03 21:21:28 -08002195 u32 pcie_ireg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002196 unsigned long flags;
2197
2198 spin_lock_irqsave(&adapter->int_lock, flags);
2199 /* Clear out unused interrupts */
Avinash Patil659c4782013-01-03 21:21:28 -08002200 pcie_ireg = adapter->int_status;
2201 adapter->int_status = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002202 spin_unlock_irqrestore(&adapter->int_lock, flags);
2203
Avinash Patil659c4782013-01-03 21:21:28 -08002204 while (pcie_ireg & HOST_INTR_MASK) {
2205 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2206 pcie_ireg &= ~HOST_INTR_DNLD_DONE;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302207 mwifiex_dbg(adapter, INTR,
2208 "info: TX DNLD Done\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08002209 ret = mwifiex_pcie_send_data_complete(adapter);
2210 if (ret)
2211 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002212 }
Avinash Patil659c4782013-01-03 21:21:28 -08002213 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2214 pcie_ireg &= ~HOST_INTR_UPLD_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302215 mwifiex_dbg(adapter, INTR,
2216 "info: Rx DATA\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002217 ret = mwifiex_pcie_process_recv_data(adapter);
2218 if (ret)
2219 return ret;
2220 }
Avinash Patil659c4782013-01-03 21:21:28 -08002221 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2222 pcie_ireg &= ~HOST_INTR_EVENT_RDY;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302223 mwifiex_dbg(adapter, INTR,
2224 "info: Rx EVENT\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002225 ret = mwifiex_pcie_process_event_ready(adapter);
2226 if (ret)
2227 return ret;
2228 }
2229
Avinash Patil659c4782013-01-03 21:21:28 -08002230 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2231 pcie_ireg &= ~HOST_INTR_CMD_DONE;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002232 if (adapter->cmd_sent) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302233 mwifiex_dbg(adapter, INTR,
2234 "info: CMD sent Interrupt\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002235 adapter->cmd_sent = false;
2236 }
2237 /* Handle command response */
2238 ret = mwifiex_pcie_process_cmd_complete(adapter);
2239 if (ret)
2240 return ret;
2241 }
2242
2243 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2244 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2245 &pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302246 mwifiex_dbg(adapter, ERROR,
2247 "Read register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002248 return -1;
2249 }
2250
2251 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2252 if (mwifiex_write_reg(adapter,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002253 PCIE_HOST_INT_STATUS,
2254 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302255 mwifiex_dbg(adapter, ERROR,
2256 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002257 return -1;
2258 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002259 }
2260
2261 }
2262 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302263 mwifiex_dbg(adapter, INTR,
2264 "info: cmd_sent=%d data_sent=%d\n",
2265 adapter->cmd_sent, adapter->data_sent);
Avinash Patilb2fda1f2013-03-22 21:49:05 -07002266 if (adapter->ps_state != PS_STATE_SLEEP)
2267 mwifiex_pcie_enable_host_int(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002268
2269 return 0;
2270}
2271
Xinming Hu99074fc2016-01-11 02:16:40 -08002272static int mwifiex_process_msix_int(struct mwifiex_adapter *adapter)
2273{
2274 int ret;
2275 u32 pcie_ireg;
2276 unsigned long flags;
2277
2278 spin_lock_irqsave(&adapter->int_lock, flags);
2279 /* Clear out unused interrupts */
2280 pcie_ireg = adapter->int_status;
2281 adapter->int_status = 0;
2282 spin_unlock_irqrestore(&adapter->int_lock, flags);
2283
2284 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
2285 mwifiex_dbg(adapter, INTR,
2286 "info: TX DNLD Done\n");
2287 ret = mwifiex_pcie_send_data_complete(adapter);
2288 if (ret)
2289 return ret;
2290 }
2291 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
2292 mwifiex_dbg(adapter, INTR,
2293 "info: Rx DATA\n");
2294 ret = mwifiex_pcie_process_recv_data(adapter);
2295 if (ret)
2296 return ret;
2297 }
2298 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
2299 mwifiex_dbg(adapter, INTR,
2300 "info: Rx EVENT\n");
2301 ret = mwifiex_pcie_process_event_ready(adapter);
2302 if (ret)
2303 return ret;
2304 }
2305
2306 if (pcie_ireg & HOST_INTR_CMD_DONE) {
2307 if (adapter->cmd_sent) {
2308 mwifiex_dbg(adapter, INTR,
2309 "info: CMD sent Interrupt\n");
2310 adapter->cmd_sent = false;
2311 }
2312 /* Handle command response */
2313 ret = mwifiex_pcie_process_cmd_complete(adapter);
2314 if (ret)
2315 return ret;
2316 }
2317
2318 mwifiex_dbg(adapter, INTR,
2319 "info: cmd_sent=%d data_sent=%d\n",
2320 adapter->cmd_sent, adapter->data_sent);
2321
2322 return 0;
2323}
2324
2325static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
2326{
2327 struct pcie_service_card *card = adapter->card;
2328
2329 if (card->msix_enable)
2330 return mwifiex_process_msix_int(adapter);
2331 else
2332 return mwifiex_process_pcie_int(adapter);
2333}
2334
Amitkumar Karward930fae2011-10-11 17:41:21 -07002335/*
2336 * This function downloads data from driver to card.
2337 *
2338 * Both commands and data packets are transferred to the card by this
2339 * function.
2340 *
2341 * This function adds the PCIE specific header to the front of the buffer
2342 * before transferring. The header contains the length of the packet and
2343 * the type. The firmware handles the packets based upon this set type.
2344 */
2345static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
2346 struct sk_buff *skb,
2347 struct mwifiex_tx_param *tx_param)
2348{
Dan Carpenterfa161cb2011-11-07 19:31:45 -08002349 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302350 mwifiex_dbg(adapter, ERROR,
2351 "Passed NULL skb to %s\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002352 return -1;
2353 }
2354
2355 if (type == MWIFIEX_TYPE_DATA)
Avinash Patile7f767a2013-01-03 21:21:32 -08002356 return mwifiex_pcie_send_data(adapter, skb, tx_param);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002357 else if (type == MWIFIEX_TYPE_CMD)
2358 return mwifiex_pcie_send_cmd(adapter, skb);
2359
2360 return 0;
2361}
2362
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002363/* This function read/write firmware */
2364static enum rdwr_status
2365mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
2366{
2367 int ret, tries;
2368 u8 ctrl_data;
2369 struct pcie_service_card *card = adapter->card;
2370 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2371
2372 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY);
2373 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302374 mwifiex_dbg(adapter, ERROR,
2375 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002376 return RDWR_STATUS_FAILURE;
2377 }
2378
2379 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2380 mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
2381 if (ctrl_data == FW_DUMP_DONE)
2382 return RDWR_STATUS_SUCCESS;
2383 if (doneflag && ctrl_data == doneflag)
2384 return RDWR_STATUS_DONE;
2385 if (ctrl_data != FW_DUMP_HOST_READY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302386 mwifiex_dbg(adapter, WARN,
2387 "The ctrl reg was changed, re-try again!\n");
Amitkumar Karwar24716872014-09-18 08:04:01 -04002388 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
2389 FW_DUMP_HOST_READY);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002390 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302391 mwifiex_dbg(adapter, ERROR,
2392 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002393 return RDWR_STATUS_FAILURE;
2394 }
2395 }
2396 usleep_range(100, 200);
2397 }
2398
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302399 mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002400 return RDWR_STATUS_FAILURE;
2401}
2402
2403/* This function dump firmware memory to file */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002404static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002405{
2406 struct pcie_service_card *card = adapter->card;
2407 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2408 unsigned int reg, reg_start, reg_end;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002409 u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
2410 enum rdwr_status stat;
2411 u32 memory_size;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002412 int ret;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002413
Avinash Patilb4e8aeb2015-02-11 23:12:26 +05302414 if (!card->pcie.can_dump_fw)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002415 return;
2416
2417 for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
2418 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
2419
2420 if (entry->mem_ptr) {
2421 vfree(entry->mem_ptr);
2422 entry->mem_ptr = NULL;
2423 }
2424 entry->mem_size = 0;
2425 }
2426
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302427 mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002428
2429 /* Read the number of the memories which will dump */
2430 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2431 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002432 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002433
2434 reg = creg->fw_dump_start;
2435 mwifiex_read_reg_byte(adapter, reg, &dump_num);
2436
2437 /* Read the length of every memory which will dump */
2438 for (idx = 0; idx < dump_num; idx++) {
2439 struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
2440
2441 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2442 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002443 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002444
2445 memory_size = 0;
2446 reg = creg->fw_dump_start;
2447 for (i = 0; i < 4; i++) {
2448 mwifiex_read_reg_byte(adapter, reg, &read_reg);
2449 memory_size |= (read_reg << (i * 8));
2450 reg++;
2451 }
2452
2453 if (memory_size == 0) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302454 mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002455 ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
2456 FW_DUMP_READ_DONE);
2457 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302458 mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002459 return;
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002460 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002461 break;
2462 }
2463
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302464 mwifiex_dbg(adapter, DUMP,
2465 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002466 entry->mem_ptr = vmalloc(memory_size + 1);
2467 entry->mem_size = memory_size;
2468 if (!entry->mem_ptr) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302469 mwifiex_dbg(adapter, ERROR,
2470 "Vmalloc %s failed\n", entry->mem_name);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002471 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002472 }
2473 dbg_ptr = entry->mem_ptr;
2474 end_ptr = dbg_ptr + memory_size;
2475
2476 doneflag = entry->done_flag;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302477 mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
2478 entry->mem_name);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002479
2480 do {
2481 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2482 if (RDWR_STATUS_FAILURE == stat)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002483 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002484
2485 reg_start = creg->fw_dump_start;
2486 reg_end = creg->fw_dump_end;
2487 for (reg = reg_start; reg <= reg_end; reg++) {
2488 mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
Amitkumar Karwar24716872014-09-18 08:04:01 -04002489 if (dbg_ptr < end_ptr) {
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002490 dbg_ptr++;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002491 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302492 mwifiex_dbg(adapter, ERROR,
2493 "Allocated buf not enough\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002494 return;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002495 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002496 }
2497
2498 if (stat != RDWR_STATUS_DONE)
2499 continue;
2500
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302501 mwifiex_dbg(adapter, DUMP,
2502 "%s done: size=0x%tx\n",
2503 entry->mem_name, dbg_ptr - entry->mem_ptr);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002504 break;
2505 } while (true);
2506 }
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002507 mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002508}
2509
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002510static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
2511{
2512 mwifiex_drv_info_dump(adapter);
2513 mwifiex_pcie_fw_dump(adapter);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002514 mwifiex_upload_device_dump(adapter);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002515}
2516
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002517static unsigned long iface_work_flags;
2518static struct mwifiex_adapter *save_adapter;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002519static void mwifiex_pcie_work(struct work_struct *work)
2520{
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002521 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002522 &iface_work_flags))
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002523 mwifiex_pcie_device_dump_work(save_adapter);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002524}
2525
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002526static DECLARE_WORK(pcie_work, mwifiex_pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002527/* This function dumps FW information */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002528static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002529{
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002530 save_adapter = adapter;
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002531 if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags))
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002532 return;
2533
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002534 set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002535
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002536 schedule_work(&pcie_work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002537}
2538
Amitkumar Karward930fae2011-10-11 17:41:21 -07002539/*
2540 * This function initializes the PCI-E host memory space, WCB rings, etc.
2541 *
2542 * The following initializations steps are followed -
2543 * - Allocate TXBD ring buffers
2544 * - Allocate RXBD ring buffers
2545 * - Allocate event BD ring buffers
2546 * - Allocate command response ring buffer
2547 * - Allocate sleep cookie buffer
2548 */
2549static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
2550{
2551 struct pcie_service_card *card = adapter->card;
2552 int ret;
2553 struct pci_dev *pdev = card->dev;
Avinash Patil52301a82013-02-12 14:38:32 -08002554 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002555
2556 pci_set_drvdata(pdev, card);
2557
2558 ret = pci_enable_device(pdev);
2559 if (ret)
2560 goto err_enable_dev;
2561
2562 pci_set_master(pdev);
2563
Xinming Hufdb1e282015-12-31 06:24:12 -08002564 pr_notice("try set_consistent_dma_mask(32)\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002565 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
2566 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002567 pr_err("set_dma_mask(32) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002568 goto err_set_dma_mask;
2569 }
2570
2571 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
2572 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002573 pr_err("set_consistent_dma_mask(64) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002574 goto err_set_dma_mask;
2575 }
2576
2577 ret = pci_request_region(pdev, 0, DRV_NAME);
2578 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002579 pr_err("req_reg(0) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002580 goto err_req_region0;
2581 }
2582 card->pci_mmap = pci_iomap(pdev, 0, 0);
2583 if (!card->pci_mmap) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002584 pr_err("iomap(0) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002585 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002586 goto err_iomap0;
2587 }
2588 ret = pci_request_region(pdev, 2, DRV_NAME);
2589 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002590 pr_err("req_reg(2) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002591 goto err_req_region2;
2592 }
2593 card->pci_mmap1 = pci_iomap(pdev, 2, 0);
2594 if (!card->pci_mmap1) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002595 pr_err("iomap(2) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002596 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002597 goto err_iomap2;
2598 }
2599
Xinming Hufdb1e282015-12-31 06:24:12 -08002600 pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
2601 card->pci_mmap, card->pci_mmap1);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002602
2603 card->cmdrsp_buf = NULL;
2604 ret = mwifiex_pcie_create_txbd_ring(adapter);
2605 if (ret)
2606 goto err_cre_txbd;
2607 ret = mwifiex_pcie_create_rxbd_ring(adapter);
2608 if (ret)
2609 goto err_cre_rxbd;
2610 ret = mwifiex_pcie_create_evtbd_ring(adapter);
2611 if (ret)
2612 goto err_cre_evtbd;
2613 ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
2614 if (ret)
2615 goto err_alloc_cmdbuf;
Avinash Patil52301a82013-02-12 14:38:32 -08002616 if (reg->sleep_cookie) {
2617 ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
2618 if (ret)
2619 goto err_alloc_cookie;
2620 } else {
2621 card->sleep_cookie_vbase = NULL;
2622 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002623 return ret;
2624
2625err_alloc_cookie:
2626 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2627err_alloc_cmdbuf:
2628 mwifiex_pcie_delete_evtbd_ring(adapter);
2629err_cre_evtbd:
2630 mwifiex_pcie_delete_rxbd_ring(adapter);
2631err_cre_rxbd:
2632 mwifiex_pcie_delete_txbd_ring(adapter);
2633err_cre_txbd:
2634 pci_iounmap(pdev, card->pci_mmap1);
2635err_iomap2:
2636 pci_release_region(pdev, 2);
2637err_req_region2:
2638 pci_iounmap(pdev, card->pci_mmap);
2639err_iomap0:
2640 pci_release_region(pdev, 0);
2641err_req_region0:
2642err_set_dma_mask:
2643 pci_disable_device(pdev);
2644err_enable_dev:
2645 pci_set_drvdata(pdev, NULL);
2646 return ret;
2647}
2648
2649/*
2650 * This function cleans up the allocated card buffers.
2651 *
2652 * The following are freed by this function -
2653 * - TXBD ring buffers
2654 * - RXBD ring buffers
2655 * - Event BD ring buffers
2656 * - Command response ring buffer
2657 * - Sleep cookie buffer
2658 */
2659static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
2660{
2661 struct pcie_service_card *card = adapter->card;
2662 struct pci_dev *pdev = card->dev;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002663 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002664
Amitkumar Karward930fae2011-10-11 17:41:21 -07002665 if (user_rmmod) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302666 mwifiex_dbg(adapter, INFO,
2667 "Clearing driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002668 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302669 mwifiex_dbg(adapter, ERROR,
2670 "Failed to write driver not-ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002671 }
2672
2673 if (pdev) {
2674 pci_iounmap(pdev, card->pci_mmap);
2675 pci_iounmap(pdev, card->pci_mmap1);
Yogesh Ashok Powar5b0d9b22013-04-23 16:49:48 -07002676 pci_disable_device(pdev);
Yogesh Ashok Powarc380aaf2013-04-23 16:49:47 -07002677 pci_release_region(pdev, 2);
2678 pci_release_region(pdev, 0);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002679 pci_set_drvdata(pdev, NULL);
2680 }
Amitkumar Karwar3c59e322013-11-14 19:10:41 -08002681 kfree(card);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002682}
2683
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002684static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
2685{
Xinming Hu99074fc2016-01-11 02:16:40 -08002686 int ret, i, j;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002687 struct pcie_service_card *card = adapter->card;
2688 struct pci_dev *pdev = card->dev;
2689
Xinming Hu99074fc2016-01-11 02:16:40 -08002690 if (card->pcie.reg->msix_support) {
2691 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2692 card->msix_entries[i].entry = i;
2693 ret = pci_enable_msix_exact(pdev, card->msix_entries,
2694 MWIFIEX_NUM_MSIX_VECTORS);
2695 if (!ret) {
2696 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) {
2697 card->msix_ctx[i].dev = pdev;
2698 card->msix_ctx[i].msg_id = i;
2699
2700 ret = request_irq(card->msix_entries[i].vector,
2701 mwifiex_pcie_interrupt, 0,
2702 "MWIFIEX_PCIE_MSIX",
2703 &card->msix_ctx[i]);
2704 if (ret)
2705 break;
2706 }
2707
2708 if (ret) {
2709 mwifiex_dbg(adapter, INFO, "request_irq fail: %d\n",
2710 ret);
2711 for (j = 0; j < i; j++)
2712 free_irq(card->msix_entries[j].vector,
2713 &card->msix_ctx[i]);
2714 pci_disable_msix(pdev);
2715 } else {
2716 mwifiex_dbg(adapter, MSG, "MSIx enabled!");
2717 card->msix_enable = 1;
2718 return 0;
2719 }
2720 }
2721 }
2722
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002723 if (pci_enable_msi(pdev) != 0)
2724 pci_disable_msi(pdev);
2725 else
2726 card->msi_enable = 1;
2727
2728 mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable);
2729
Xinming Hu99074fc2016-01-11 02:16:40 -08002730 card->share_irq_ctx.dev = pdev;
2731 card->share_irq_ctx.msg_id = -1;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002732 ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
Xinming Hu99074fc2016-01-11 02:16:40 -08002733 "MRVL_PCIE", &card->share_irq_ctx);
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002734 if (ret) {
2735 pr_err("request_irq failed: ret=%d\n", ret);
2736 adapter->card = NULL;
2737 return -1;
2738 }
2739
2740 return 0;
2741}
2742
Amitkumar Karward930fae2011-10-11 17:41:21 -07002743/*
2744 * This function registers the PCIE device.
2745 *
2746 * PCIE IRQ is claimed, block size is set and driver data is initialized.
2747 */
2748static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
2749{
Amitkumar Karward930fae2011-10-11 17:41:21 -07002750 struct pcie_service_card *card = adapter->card;
2751 struct pci_dev *pdev = card->dev;
2752
2753 /* save adapter pointer in card */
2754 card->adapter = adapter;
Xinming Hufdb1e282015-12-31 06:24:12 -08002755 adapter->dev = &pdev->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002756
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002757 if (mwifiex_pcie_request_irq(adapter))
Amitkumar Karward930fae2011-10-11 17:41:21 -07002758 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002759
Amitkumar Karwar828cf222014-02-27 19:35:13 -08002760 adapter->tx_buf_size = card->pcie.tx_buf_size;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002761 adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
2762 adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
Avinash Patildd04e6a2013-02-08 18:18:06 -08002763 strcpy(adapter->fw_name, card->pcie.firmware);
Avinash Patil1fe192d2015-01-23 17:09:19 +05302764 adapter->ext_scan = card->pcie.can_ext_scan;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002765
2766 return 0;
2767}
2768
2769/*
2770 * This function unregisters the PCIE device.
2771 *
2772 * The PCIE IRQ is released, the function is disabled and driver
2773 * data is set to null.
2774 */
2775static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
2776{
2777 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -08002778 const struct mwifiex_pcie_card_reg *reg;
Xinming Hu99074fc2016-01-11 02:16:40 -08002779 struct pci_dev *pdev = card->dev;
2780 int i;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002781
2782 if (card) {
Xinming Hu99074fc2016-01-11 02:16:40 -08002783 if (card->msix_enable) {
2784 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2785 synchronize_irq(card->msix_entries[i].vector);
2786
2787 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
2788 free_irq(card->msix_entries[i].vector,
2789 &card->msix_ctx[i]);
2790
2791 card->msix_enable = 0;
2792 pci_disable_msix(pdev);
2793 } else {
2794 mwifiex_dbg(adapter, INFO,
2795 "%s(): calling free_irq()\n", __func__);
2796 free_irq(card->dev->irq, &card->share_irq_ctx);
2797
2798 if (card->msi_enable)
2799 pci_disable_msi(pdev);
2800 }
Avinash Patilfc331462013-01-03 21:21:30 -08002801
Avinash Patil52301a82013-02-12 14:38:32 -08002802 reg = card->pcie.reg;
2803 if (reg->sleep_cookie)
2804 mwifiex_pcie_delete_sleep_cookie_buf(adapter);
2805
Avinash Patilfc331462013-01-03 21:21:30 -08002806 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2807 mwifiex_pcie_delete_evtbd_ring(adapter);
2808 mwifiex_pcie_delete_rxbd_ring(adapter);
2809 mwifiex_pcie_delete_txbd_ring(adapter);
2810 card->cmdrsp_buf = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002811 }
2812}
2813
2814static struct mwifiex_if_ops pcie_ops = {
2815 .init_if = mwifiex_pcie_init,
2816 .cleanup_if = mwifiex_pcie_cleanup,
2817 .check_fw_status = mwifiex_check_fw_status,
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002818 .check_winner_status = mwifiex_check_winner_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002819 .prog_fw = mwifiex_prog_fw_w_helper,
2820 .register_dev = mwifiex_register_dev,
2821 .unregister_dev = mwifiex_unregister_dev,
2822 .enable_int = mwifiex_pcie_enable_host_int,
2823 .process_int_status = mwifiex_process_int_status,
2824 .host_to_card = mwifiex_pcie_host_to_card,
2825 .wakeup = mwifiex_pm_wakeup_card,
2826 .wakeup_complete = mwifiex_pm_wakeup_card_complete,
2827
2828 /* PCIE specific */
2829 .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
2830 .event_complete = mwifiex_pcie_event_complete,
2831 .update_mp_end_port = NULL,
2832 .cleanup_mpa_buf = NULL,
Avinash Patilc6d1d872013-01-03 21:21:29 -08002833 .init_fw_port = mwifiex_pcie_init_fw_port,
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08002834 .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002835 .device_dump = mwifiex_pcie_device_dump,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002836};
2837
2838/*
2839 * This function initializes the PCIE driver module.
2840 *
2841 * This initiates the semaphore and registers the device with
2842 * PCIE bus.
2843 */
2844static int mwifiex_pcie_init_module(void)
2845{
2846 int ret;
2847
Avinash Patilca8f2112013-02-08 18:18:09 -08002848 pr_debug("Marvell PCIe Driver\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002849
2850 sema_init(&add_remove_card_sem, 1);
2851
2852 /* Clear the flag in case user removes the card. */
2853 user_rmmod = 0;
2854
2855 ret = pci_register_driver(&mwifiex_pcie);
2856 if (ret)
2857 pr_err("Driver register failed!\n");
2858 else
2859 pr_debug("info: Driver registered successfully!\n");
2860
2861 return ret;
2862}
2863
2864/*
2865 * This function cleans up the PCIE driver.
2866 *
2867 * The following major steps are followed for cleanup -
2868 * - Resume the device if its suspended
2869 * - Disconnect the device if connected
2870 * - Shutdown the firmware
2871 * - Unregister the device from PCIE bus.
2872 */
2873static void mwifiex_pcie_cleanup_module(void)
2874{
2875 if (!down_interruptible(&add_remove_card_sem))
2876 up(&add_remove_card_sem);
2877
2878 /* Set the flag as user is removing this module. */
2879 user_rmmod = 1;
2880
Maithili Hinge2f5872b2015-03-22 23:01:25 -07002881 cancel_work_sync(&pcie_work);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002882 pci_unregister_driver(&mwifiex_pcie);
2883}
2884
2885module_init(mwifiex_pcie_init_module);
2886module_exit(mwifiex_pcie_cleanup_module);
2887
2888MODULE_AUTHOR("Marvell International Ltd.");
2889MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
2890MODULE_VERSION(PCIE_VERSION);
2891MODULE_LICENSE("GPL v2");
Avinash Patilca8f2112013-02-08 18:18:09 -08002892MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
2893MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07002894MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME);