blob: cd314946452c1398fe6d583f7197dd12682a85ef [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
Amitkumar Karward930fae2011-10-11 17:41:21 -070034static struct mwifiex_if_ops pcie_ops;
35
Xinming Hu6b4480d2016-11-18 18:07:04 +053036static const struct of_device_id mwifiex_pcie_of_match_table[] = {
37 { .compatible = "pci11ab,2b42" },
38 { .compatible = "pci1b4b,2b42" },
39 { }
40};
41
42static int mwifiex_pcie_probe_of(struct device *dev)
43{
44 if (!of_match_node(mwifiex_pcie_of_match_table, dev->of_node)) {
45 dev_err(dev, "required compatible string missing\n");
46 return -EINVAL;
47 }
48
49 return 0;
50}
51
Xinming Hu41efaf52016-11-16 18:39:08 +053052static void mwifiex_pcie_work(struct work_struct *work);
Xinming Hu41efaf52016-11-16 18:39:08 +053053
Avinash Patilfc331462013-01-03 21:21:30 -080054static int
55mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
Aaron Durbindbccc922014-02-07 16:25:50 -080056 size_t size, int flags)
Amitkumar Karward930fae2011-10-11 17:41:21 -070057{
Avinash Patilfc331462013-01-03 21:21:30 -080058 struct pcie_service_card *card = adapter->card;
Aaron Durbindbccc922014-02-07 16:25:50 -080059 struct mwifiex_dma_mapping mapping;
Amitkumar Karward930fae2011-10-11 17:41:21 -070060
Aaron Durbindbccc922014-02-07 16:25:50 -080061 mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
62 if (pci_dma_mapping_error(card->dev, mapping.addr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +053063 mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
Avinash Patilfc331462013-01-03 21:21:30 -080064 return -1;
65 }
Aaron Durbindbccc922014-02-07 16:25:50 -080066 mapping.len = size;
Chin-Ran Lobca463e2014-06-06 19:37:10 -070067 mwifiex_store_mapping(skb, &mapping);
Avinash Patilfc331462013-01-03 21:21:30 -080068 return 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -070069}
70
Aaron Durbindbccc922014-02-07 16:25:50 -080071static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
72 struct sk_buff *skb, int flags)
73{
74 struct pcie_service_card *card = adapter->card;
75 struct mwifiex_dma_mapping mapping;
76
Chin-Ran Lobca463e2014-06-06 19:37:10 -070077 mwifiex_get_mapping(skb, &mapping);
Aaron Durbindbccc922014-02-07 16:25:50 -080078 pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
79}
80
Amitkumar Karward930fae2011-10-11 17:41:21 -070081/*
Xinming Hu90ff71f2016-11-30 20:22:16 +053082 * This function writes data into PCIE card register.
83 */
84static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data)
85{
86 struct pcie_service_card *card = adapter->card;
87
88 iowrite32(data, card->pci_mmap1 + reg);
89
90 return 0;
91}
92
93/* This function reads data from PCIE card register.
94 */
95static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
96{
97 struct pcie_service_card *card = adapter->card;
98
99 *data = ioread32(card->pci_mmap1 + reg);
100 if (*data == 0xffffffff)
101 return 0xffffffff;
102
103 return 0;
104}
105
106/* This function reads u8 data from PCIE card register. */
107static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter,
108 int reg, u8 *data)
109{
110 struct pcie_service_card *card = adapter->card;
111
112 *data = ioread8(card->pci_mmap1 + reg);
113
114 return 0;
115}
116
117/*
Amitkumar Karward930fae2011-10-11 17:41:21 -0700118 * This function reads sleep cookie and checks if FW is ready
119 */
120static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
121{
Devidas Puranik92c70a92017-03-09 14:06:17 +0530122 u32 cookie_value;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700123 struct pcie_service_card *card = adapter->card;
Avinash Patil52301a82013-02-12 14:38:32 -0800124 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
125
126 if (!reg->sleep_cookie)
127 return true;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700128
Avinash Patilfc331462013-01-03 21:21:30 -0800129 if (card->sleep_cookie_vbase) {
Devidas Puranik92c70a92017-03-09 14:06:17 +0530130 cookie_value = get_unaligned_le32(card->sleep_cookie_vbase);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530131 mwifiex_dbg(adapter, INFO,
132 "info: ACCESS_HW: sleep cookie=0x%x\n",
Devidas Puranik92c70a92017-03-09 14:06:17 +0530133 cookie_value);
134 if (cookie_value == FW_AWAKE_COOKIE)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700135 return true;
136 }
137
138 return false;
139}
140
Shuah Khan3266d732013-07-03 10:47:10 -0600141#ifdef CONFIG_PM_SLEEP
Amitkumar Karward930fae2011-10-11 17:41:21 -0700142/*
Bing Zhaofcca8d52013-03-04 16:27:53 -0800143 * Kernel needs to suspend all functions separately. Therefore all
144 * registered functions must have drivers with suspend and resume
145 * methods. Failing that the kernel simply removes the whole card.
146 *
147 * If already not suspended, this function allocates and sends a host
148 * sleep activate request to the firmware and turns off the traffic.
149 */
Shuah Khan3266d732013-07-03 10:47:10 -0600150static int mwifiex_pcie_suspend(struct device *dev)
Bing Zhaofcca8d52013-03-04 16:27:53 -0800151{
152 struct mwifiex_adapter *adapter;
153 struct pcie_service_card *card;
Shuah Khan3266d732013-07-03 10:47:10 -0600154 struct pci_dev *pdev = to_pci_dev(dev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800155
Amitkumar Karwara1beec42016-11-18 19:30:27 +0530156 card = pci_get_drvdata(pdev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800157
Brian Norrisb42dbb22016-11-18 19:30:29 +0530158 /* Might still be loading firmware */
159 wait_for_completion(&card->fw_done);
160
Bing Zhaofcca8d52013-03-04 16:27:53 -0800161 adapter = card->adapter;
Brian Norrisb42dbb22016-11-18 19:30:29 +0530162 if (!adapter) {
163 dev_err(dev, "adapter is not valid\n");
164 return 0;
165 }
166
Rajat Jain853402a2016-11-15 19:06:04 +0530167 mwifiex_enable_wake(adapter);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800168
Amitkumar Karwar5190f2e2016-09-28 18:18:22 +0530169 /* Enable the Host Sleep */
170 if (!mwifiex_enable_hs(adapter)) {
171 mwifiex_dbg(adapter, ERROR,
172 "cmd: failed to suspend\n");
173 adapter->hs_enabling = false;
Brian Norrisd96e3922016-11-18 22:43:24 +0530174 mwifiex_disable_wake(adapter);
Amitkumar Karwar5190f2e2016-09-28 18:18:22 +0530175 return -EFAULT;
176 }
177
Amitkumar Karwarec815dd2016-09-28 18:18:21 +0530178 flush_workqueue(adapter->workqueue);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800179
180 /* Indicate device suspended */
181 adapter->is_suspended = true;
Amitkumar Karwarc0dbba62014-03-25 19:01:20 -0700182 adapter->hs_enabling = false;
Bing Zhaofcca8d52013-03-04 16:27:53 -0800183
184 return 0;
185}
186
187/*
188 * Kernel needs to suspend all functions separately. Therefore all
189 * registered functions must have drivers with suspend and resume
190 * methods. Failing that the kernel simply removes the whole card.
191 *
192 * If already not resumed, this function turns on the traffic and
193 * sends a host sleep cancel request to the firmware.
194 */
Shuah Khan3266d732013-07-03 10:47:10 -0600195static int mwifiex_pcie_resume(struct device *dev)
Bing Zhaofcca8d52013-03-04 16:27:53 -0800196{
197 struct mwifiex_adapter *adapter;
198 struct pcie_service_card *card;
Shuah Khan3266d732013-07-03 10:47:10 -0600199 struct pci_dev *pdev = to_pci_dev(dev);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800200
Amitkumar Karwara1beec42016-11-18 19:30:27 +0530201 card = pci_get_drvdata(pdev);
Brian Norrise98fb112016-11-18 19:30:33 +0530202
203 if (!card->adapter) {
204 dev_err(dev, "adapter structure is not valid\n");
Bing Zhaofcca8d52013-03-04 16:27:53 -0800205 return 0;
206 }
207
208 adapter = card->adapter;
209
210 if (!adapter->is_suspended) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530211 mwifiex_dbg(adapter, WARN,
212 "Device already resumed\n");
Bing Zhaofcca8d52013-03-04 16:27:53 -0800213 return 0;
214 }
215
216 adapter->is_suspended = false;
217
218 mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
219 MWIFIEX_ASYNC_CMD);
Rajat Jain853402a2016-11-15 19:06:04 +0530220 mwifiex_disable_wake(adapter);
Bing Zhaofcca8d52013-03-04 16:27:53 -0800221
222 return 0;
223}
Bing Zhao8509e822013-03-04 16:27:54 -0800224#endif
Bing Zhaofcca8d52013-03-04 16:27:53 -0800225
226/*
Amitkumar Karward930fae2011-10-11 17:41:21 -0700227 * This function probes an mwifiex device and registers it. It allocates
228 * the card structure, enables PCIE function number and initiates the
229 * device registration and initialization procedure by adding a logical
230 * interface.
231 */
232static int mwifiex_pcie_probe(struct pci_dev *pdev,
233 const struct pci_device_id *ent)
234{
235 struct pcie_service_card *card;
Xinming Hu6b4480d2016-11-18 18:07:04 +0530236 int ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700237
238 pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700239 pdev->vendor, pdev->device, pdev->revision);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700240
Brian Norris66b9c182016-10-26 16:29:20 -0700241 card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
Joe Perchese404dec2012-01-29 12:56:23 +0000242 if (!card)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700243 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700244
Brian Norris4a79aa12016-11-18 19:30:26 +0530245 init_completion(&card->fw_done);
246
Amitkumar Karward930fae2011-10-11 17:41:21 -0700247 card->dev = pdev;
248
Avinash Patildd04e6a2013-02-08 18:18:06 -0800249 if (ent->driver_data) {
250 struct mwifiex_pcie_device *data = (void *)ent->driver_data;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800251 card->pcie.reg = data->reg;
252 card->pcie.blksz_fw_dl = data->blksz_fw_dl;
Amitkumar Karwar828cf222014-02-27 19:35:13 -0800253 card->pcie.tx_buf_size = data->tx_buf_size;
Avinash Patilb4e8aeb2015-02-11 23:12:26 +0530254 card->pcie.can_dump_fw = data->can_dump_fw;
Xinming Hu50632092016-02-02 22:05:06 -0800255 card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl;
256 card->pcie.num_mem_types = data->num_mem_types;
Avinash Patil1fe192d2015-01-23 17:09:19 +0530257 card->pcie.can_ext_scan = data->can_ext_scan;
Ganapathi Bhat3860e5e2016-11-16 18:39:09 +0530258 INIT_WORK(&card->work, mwifiex_pcie_work);
Avinash Patildd04e6a2013-02-08 18:18:06 -0800259 }
260
Xinming Hu6b4480d2016-11-18 18:07:04 +0530261 /* device tree node parsing and platform specific configuration*/
262 if (pdev->dev.of_node) {
263 ret = mwifiex_pcie_probe_of(&pdev->dev);
264 if (ret)
265 return ret;
266 }
267
Brian Norris4a79aa12016-11-18 19:30:26 +0530268 if (mwifiex_add_card(card, &card->fw_done, &pcie_ops,
Rajat Jain2e02b582016-11-15 19:06:02 +0530269 MWIFIEX_PCIE, &pdev->dev)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700270 pr_err("%s failed\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700271 return -1;
272 }
273
274 return 0;
275}
276
277/*
278 * This function removes the interface and frees up the card structure.
279 */
280static void mwifiex_pcie_remove(struct pci_dev *pdev)
281{
282 struct pcie_service_card *card;
283 struct mwifiex_adapter *adapter;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700284 struct mwifiex_private *priv;
Xinming Hu045f0c12016-11-30 20:22:17 +0530285 const struct mwifiex_pcie_card_reg *reg;
286 u32 fw_status;
287 int ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700288
289 card = pci_get_drvdata(pdev);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700290
Brian Norris4a79aa12016-11-18 19:30:26 +0530291 wait_for_completion(&card->fw_done);
292
Amitkumar Karward930fae2011-10-11 17:41:21 -0700293 adapter = card->adapter;
294 if (!adapter || !adapter->priv_num)
295 return;
296
Xinming Hu045f0c12016-11-30 20:22:17 +0530297 reg = card->pcie.reg;
298 if (reg)
299 ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
Arnd Bergmann0e8edb92017-01-13 16:35:03 +0100300 else
301 fw_status = -1;
Xinming Hu045f0c12016-11-30 20:22:17 +0530302
303 if (fw_status == FIRMWARE_READY_PCIE && !adapter->mfg_mode) {
Amitkumar Karwar848819f2014-02-27 19:35:17 -0800304 mwifiex_deauthenticate_all(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700305
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700306 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700307
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700308 mwifiex_disable_auto_ds(priv);
309
310 mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700311 }
312
Brian Norris4a79aa12016-11-18 19:30:26 +0530313 mwifiex_remove_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700314}
315
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700316static void mwifiex_pcie_shutdown(struct pci_dev *pdev)
317{
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700318 mwifiex_pcie_remove(pdev);
319
320 return;
321}
322
Benoit Taine9baa3c32014-08-08 15:56:03 +0200323static const struct pci_device_id mwifiex_ids[] = {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700324 {
325 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
326 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700327 .driver_data = (unsigned long)&mwifiex_pcie8766,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700328 },
Avinash Patilca8f2112013-02-08 18:18:09 -0800329 {
330 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
331 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -0700332 .driver_data = (unsigned long)&mwifiex_pcie8897,
333 },
334 {
335 PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
336 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
337 .driver_data = (unsigned long)&mwifiex_pcie8997,
Avinash Patilca8f2112013-02-08 18:18:09 -0800338 },
Shengzhen Lia362e162016-04-05 01:04:36 -0700339 {
340 PCIE_VENDOR_ID_V2_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997,
341 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
342 .driver_data = (unsigned long)&mwifiex_pcie8997,
343 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700344 {},
345};
346
347MODULE_DEVICE_TABLE(pci, mwifiex_ids);
348
Christoph Hellwig775755e2017-06-01 13:10:38 +0200349/*
350 * Cleanup all software without cleaning anything related to PCIe and HW.
351 */
352static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
353{
354 struct pcie_service_card *card = pci_get_drvdata(pdev);
355 struct mwifiex_adapter *adapter = card->adapter;
356
357 if (!adapter) {
358 dev_err(&pdev->dev, "%s: adapter structure is not valid\n",
359 __func__);
360 return;
361 }
362
363 mwifiex_dbg(adapter, INFO,
364 "%s: vendor=0x%4.04x device=0x%4.04x rev=%d Pre-FLR\n",
365 __func__, pdev->vendor, pdev->device, pdev->revision);
366
367 mwifiex_shutdown_sw(adapter);
Christoph Hellwig775755e2017-06-01 13:10:38 +0200368 clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
369 clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
370 mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
371}
372
373/*
374 * Kernel stores and restores PCIe function context before and after performing
375 * FLR respectively. Reconfigure the software and firmware including firmware
376 * redownload.
377 */
378static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530379{
Brian Norris52033412017-03-07 12:47:46 -0800380 struct pcie_service_card *card = pci_get_drvdata(pdev);
381 struct mwifiex_adapter *adapter = card->adapter;
Brian Norris755b37c2017-03-28 16:59:33 -0700382 int ret;
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530383
Brian Norris52033412017-03-07 12:47:46 -0800384 if (!adapter) {
385 dev_err(&pdev->dev, "%s: adapter structure is not valid\n",
386 __func__);
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530387 return;
388 }
389
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530390 mwifiex_dbg(adapter, INFO,
Christoph Hellwig775755e2017-06-01 13:10:38 +0200391 "%s: vendor=0x%4.04x device=0x%4.04x rev=%d Post-FLR\n",
392 __func__, pdev->vendor, pdev->device, pdev->revision);
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530393
Christoph Hellwig775755e2017-06-01 13:10:38 +0200394 ret = mwifiex_reinit_sw(adapter);
395 if (ret)
396 dev_err(&pdev->dev, "reinit failed: %d\n", ret);
397 else
398 mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530399}
400
Christoph Hellwig775755e2017-06-01 13:10:38 +0200401static const struct pci_error_handlers mwifiex_pcie_err_handler = {
402 .reset_prepare = mwifiex_pcie_reset_prepare,
403 .reset_done = mwifiex_pcie_reset_done,
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +0530404};
405
Shuah Khan3266d732013-07-03 10:47:10 -0600406#ifdef CONFIG_PM_SLEEP
407/* Power Management Hooks */
408static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend,
409 mwifiex_pcie_resume);
410#endif
411
Amitkumar Karward930fae2011-10-11 17:41:21 -0700412/* PCI Device Driver */
413static struct pci_driver __refdata mwifiex_pcie = {
414 .name = "mwifiex_pcie",
415 .id_table = mwifiex_ids,
416 .probe = mwifiex_pcie_probe,
417 .remove = mwifiex_pcie_remove,
Shuah Khan3266d732013-07-03 10:47:10 -0600418#ifdef CONFIG_PM_SLEEP
419 .driver = {
420 .pm = &mwifiex_pcie_pm_ops,
421 },
Amitkumar Karward930fae2011-10-11 17:41:21 -0700422#endif
Amitkumar Karwar43ba6b92013-07-22 19:17:47 -0700423 .shutdown = mwifiex_pcie_shutdown,
Christoph Hellwig775755e2017-06-01 13:10:38 +0200424 .err_handler = &mwifiex_pcie_err_handler,
Amitkumar Karward930fae2011-10-11 17:41:21 -0700425};
426
427/*
Avinash Patilc0880a22013-03-22 21:49:07 -0700428 * This function adds delay loop to ensure FW is awake before proceeding.
Amitkumar Karward930fae2011-10-11 17:41:21 -0700429 */
Avinash Patilc0880a22013-03-22 21:49:07 -0700430static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700431{
432 int i = 0;
433
Avinash Patilc0880a22013-03-22 21:49:07 -0700434 while (mwifiex_pcie_ok_to_access_hw(adapter)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -0700435 i++;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -0700436 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700437 /* 50ms max wait */
Avinash Patil3e7a4ff2013-02-25 16:01:34 -0800438 if (i == 5000)
Amitkumar Karward930fae2011-10-11 17:41:21 -0700439 break;
440 }
441
Avinash Patilc0880a22013-03-22 21:49:07 -0700442 return;
443}
444
Avinash Patilc4bc9802014-03-18 22:19:17 -0700445static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
446 u32 max_delay_loop_cnt)
447{
448 struct pcie_service_card *card = adapter->card;
449 u8 *buffer;
450 u32 sleep_cookie, count;
Amitkumar Karwarcc37d8e2017-01-24 19:05:45 +0530451 struct sk_buff *cmdrsp = card->cmdrsp_buf;
Avinash Patilc4bc9802014-03-18 22:19:17 -0700452
453 for (count = 0; count < max_delay_loop_cnt; count++) {
Amitkumar Karwarcc37d8e2017-01-24 19:05:45 +0530454 pci_dma_sync_single_for_cpu(card->dev,
455 MWIFIEX_SKB_DMA_ADDR(cmdrsp),
456 sizeof(sleep_cookie),
457 PCI_DMA_FROMDEVICE);
458 buffer = cmdrsp->data;
Devidas Puranik92c70a92017-03-09 14:06:17 +0530459 sleep_cookie = get_unaligned_le32(buffer);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700460
461 if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530462 mwifiex_dbg(adapter, INFO,
463 "sleep cookie found at count %d\n", count);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700464 break;
465 }
Amitkumar Karwarcc37d8e2017-01-24 19:05:45 +0530466 pci_dma_sync_single_for_device(card->dev,
467 MWIFIEX_SKB_DMA_ADDR(cmdrsp),
468 sizeof(sleep_cookie),
469 PCI_DMA_FROMDEVICE);
Avinash Patilc4bc9802014-03-18 22:19:17 -0700470 usleep_range(20, 30);
471 }
472
473 if (count >= max_delay_loop_cnt)
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530474 mwifiex_dbg(adapter, INFO,
475 "max count reached while accessing sleep cookie\n");
Avinash Patilc4bc9802014-03-18 22:19:17 -0700476}
477
Avinash Patilc0880a22013-03-22 21:49:07 -0700478/* This function wakes up the card by reading fw_status register. */
479static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
480{
Avinash Patilc0880a22013-03-22 21:49:07 -0700481 struct pcie_service_card *card = adapter->card;
482 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
483
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530484 mwifiex_dbg(adapter, EVENT,
485 "event: Wakeup device...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700486
Avinash Patilc0880a22013-03-22 21:49:07 -0700487 if (reg->sleep_cookie)
488 mwifiex_pcie_dev_wakeup_delay(adapter);
489
Brian Norris062e0082017-01-13 15:35:36 -0800490 /* Accessing fw_status register will wakeup device */
491 if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530492 mwifiex_dbg(adapter, ERROR,
Brian Norris062e0082017-01-13 15:35:36 -0800493 "Writing fw_status register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700494 return -1;
495 }
496
Avinash Patilc0880a22013-03-22 21:49:07 -0700497 if (reg->sleep_cookie) {
498 mwifiex_pcie_dev_wakeup_delay(adapter);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530499 mwifiex_dbg(adapter, INFO,
500 "PCIE wakeup: Setting PS_STATE_AWAKE\n");
Avinash Patilc0880a22013-03-22 21:49:07 -0700501 adapter->ps_state = PS_STATE_AWAKE;
502 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700503
504 return 0;
505}
506
507/*
508 * This function is called after the card has woken up.
509 *
510 * The card configuration register is reset.
511 */
512static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter)
513{
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530514 mwifiex_dbg(adapter, CMD,
515 "cmd: Wakeup device completed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700516
517 return 0;
518}
519
520/*
521 * This function disables the host interrupt.
522 *
523 * The host interrupt mask is read, the disable bit is reset and
524 * written back to the card host interrupt mask register.
525 */
526static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter)
527{
528 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
529 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
530 0x00000000)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530531 mwifiex_dbg(adapter, ERROR,
532 "Disable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700533 return -1;
534 }
535 }
536
Shengzhen Lieb2428fb2016-11-18 19:30:24 +0530537 atomic_set(&adapter->tx_hw_pending, 0);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700538 return 0;
539}
540
Brian Norrisd41376c2016-06-30 15:21:02 -0700541static void mwifiex_pcie_disable_host_int_noerr(struct mwifiex_adapter *adapter)
542{
543 WARN_ON(mwifiex_pcie_disable_host_int(adapter));
544}
545
Amitkumar Karward930fae2011-10-11 17:41:21 -0700546/*
547 * This function enables the host interrupt.
548 *
549 * The host interrupt enable mask is written to the card
550 * host interrupt mask register.
551 */
552static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
553{
554 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
555 /* Simply write the mask to the register */
556 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK,
557 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530558 mwifiex_dbg(adapter, ERROR,
559 "Enable host interrupt failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -0700560 return -1;
561 }
562 }
563
564 return 0;
565}
566
567/*
Avinash Patil07324842013-02-08 18:18:07 -0800568 * This function initializes TX buffer ring descriptors
569 */
570static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
571{
572 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800573 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800574 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800575 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800576 int i;
577
578 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
579 card->tx_buf_list[i] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -0800580 if (reg->pfu_enabled) {
581 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
582 (sizeof(*desc2) * i);
583 desc2 = card->txbd_ring[i];
584 memset(desc2, 0, sizeof(*desc2));
585 } else {
586 card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
587 (sizeof(*desc) * i);
588 desc = card->txbd_ring[i];
589 memset(desc, 0, sizeof(*desc));
590 }
Avinash Patil07324842013-02-08 18:18:07 -0800591 }
592
593 return 0;
594}
595
596/* This function initializes RX buffer ring descriptors. Each SKB is allocated
597 * here and after mapping PCI memory, its physical address is assigned to
598 * PCIE Rx buffer descriptor's physical address.
599 */
600static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
601{
602 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800603 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800604 struct sk_buff *skb;
605 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800606 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800607 dma_addr_t buf_pa;
608 int i;
609
610 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
611 /* Allocate skb here so that firmware can DMA data from it */
Avinash Patil62159942015-03-13 17:37:52 +0530612 skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
Mathias Krause5c87a552016-05-21 15:43:31 +0200613 GFP_KERNEL);
Avinash Patil07324842013-02-08 18:18:07 -0800614 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530615 mwifiex_dbg(adapter, ERROR,
616 "Unable to allocate skb for RX ring.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800617 kfree(card->rxbd_ring_vbase);
618 return -ENOMEM;
619 }
620
621 if (mwifiex_map_pci_memory(adapter, skb,
622 MWIFIEX_RX_DATA_BUF_SIZE,
623 PCI_DMA_FROMDEVICE))
624 return -1;
625
Aaron Durbindbccc922014-02-07 16:25:50 -0800626 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800627
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530628 mwifiex_dbg(adapter, INFO,
629 "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
630 skb, skb->len, skb->data, (u32)buf_pa,
631 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800632
633 card->rx_buf_list[i] = skb;
Avinash Patilca8f2112013-02-08 18:18:09 -0800634 if (reg->pfu_enabled) {
635 card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
636 (sizeof(*desc2) * i);
637 desc2 = card->rxbd_ring[i];
638 desc2->paddr = buf_pa;
639 desc2->len = (u16)skb->len;
640 desc2->frag_len = (u16)skb->len;
641 desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
642 desc2->offset = 0;
643 } else {
644 card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
645 (sizeof(*desc) * i));
646 desc = card->rxbd_ring[i];
647 desc->paddr = buf_pa;
648 desc->len = (u16)skb->len;
649 desc->flags = 0;
650 }
Avinash Patil07324842013-02-08 18:18:07 -0800651 }
652
653 return 0;
654}
655
656/* This function initializes event buffer ring descriptors. Each SKB is
657 * allocated here and after mapping PCI memory, its physical address is assigned
658 * to PCIE Rx buffer descriptor's physical address
659 */
660static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
661{
662 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800663 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800664 struct sk_buff *skb;
665 dma_addr_t buf_pa;
666 int i;
667
668 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
669 /* Allocate skb here so that firmware can DMA data from it */
670 skb = dev_alloc_skb(MAX_EVENT_SIZE);
671 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530672 mwifiex_dbg(adapter, ERROR,
673 "Unable to allocate skb for EVENT buf.\n");
Avinash Patil07324842013-02-08 18:18:07 -0800674 kfree(card->evtbd_ring_vbase);
675 return -ENOMEM;
676 }
677 skb_put(skb, MAX_EVENT_SIZE);
678
679 if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
680 PCI_DMA_FROMDEVICE))
681 return -1;
682
Aaron Durbindbccc922014-02-07 16:25:50 -0800683 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patil07324842013-02-08 18:18:07 -0800684
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530685 mwifiex_dbg(adapter, EVENT,
686 "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
687 skb, skb->len, skb->data, (u32)buf_pa,
688 (u32)((u64)buf_pa >> 32));
Avinash Patil07324842013-02-08 18:18:07 -0800689
690 card->evt_buf_list[i] = skb;
691 card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
692 (sizeof(*desc) * i));
Avinash Patil07324842013-02-08 18:18:07 -0800693 desc = card->evtbd_ring[i];
694 desc->paddr = buf_pa;
695 desc->len = (u16)skb->len;
696 desc->flags = 0;
697 }
698
699 return 0;
700}
701
702/* This function cleans up TX buffer rings. If any of the buffer list has valid
703 * SKB address, associated SKB is freed.
704 */
705static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
706{
707 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800708 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800709 struct sk_buff *skb;
710 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800711 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800712 int i;
713
714 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800715 if (reg->pfu_enabled) {
716 desc2 = card->txbd_ring[i];
717 if (card->tx_buf_list[i]) {
718 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800719 mwifiex_unmap_pci_memory(adapter, skb,
720 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800721 dev_kfree_skb_any(skb);
722 }
723 memset(desc2, 0, sizeof(*desc2));
724 } else {
725 desc = card->txbd_ring[i];
726 if (card->tx_buf_list[i]) {
727 skb = card->tx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800728 mwifiex_unmap_pci_memory(adapter, skb,
729 PCI_DMA_TODEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800730 dev_kfree_skb_any(skb);
731 }
732 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800733 }
734 card->tx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800735 }
736
Shengzhen Lieb2428fb2016-11-18 19:30:24 +0530737 atomic_set(&adapter->tx_hw_pending, 0);
Avinash Patil07324842013-02-08 18:18:07 -0800738 return;
739}
740
741/* This function cleans up RX buffer rings. If any of the buffer list has valid
742 * SKB address, associated SKB is freed.
743 */
744static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
745{
746 struct pcie_service_card *card = adapter->card;
Avinash Patilca8f2112013-02-08 18:18:09 -0800747 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patil07324842013-02-08 18:18:07 -0800748 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -0800749 struct mwifiex_pfu_buf_desc *desc2;
Avinash Patil07324842013-02-08 18:18:07 -0800750 struct sk_buff *skb;
751 int i;
752
753 for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
Avinash Patilca8f2112013-02-08 18:18:09 -0800754 if (reg->pfu_enabled) {
755 desc2 = card->rxbd_ring[i];
756 if (card->rx_buf_list[i]) {
757 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800758 mwifiex_unmap_pci_memory(adapter, skb,
759 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800760 dev_kfree_skb_any(skb);
761 }
762 memset(desc2, 0, sizeof(*desc2));
763 } else {
764 desc = card->rxbd_ring[i];
765 if (card->rx_buf_list[i]) {
766 skb = card->rx_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800767 mwifiex_unmap_pci_memory(adapter, skb,
768 PCI_DMA_FROMDEVICE);
Avinash Patilca8f2112013-02-08 18:18:09 -0800769 dev_kfree_skb_any(skb);
770 }
771 memset(desc, 0, sizeof(*desc));
Avinash Patil07324842013-02-08 18:18:07 -0800772 }
Avinash Patilca8f2112013-02-08 18:18:09 -0800773 card->rx_buf_list[i] = NULL;
Avinash Patil07324842013-02-08 18:18:07 -0800774 }
775
776 return;
777}
778
779/* This function cleans up event buffer rings. If any of the buffer list has
780 * valid SKB address, associated SKB is freed.
781 */
782static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
783{
784 struct pcie_service_card *card = adapter->card;
Avinash Patile05dc3e2013-02-08 18:18:08 -0800785 struct mwifiex_evt_buf_desc *desc;
Avinash Patil07324842013-02-08 18:18:07 -0800786 struct sk_buff *skb;
787 int i;
788
789 for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
790 desc = card->evtbd_ring[i];
791 if (card->evt_buf_list[i]) {
792 skb = card->evt_buf_list[i];
Aaron Durbindbccc922014-02-07 16:25:50 -0800793 mwifiex_unmap_pci_memory(adapter, skb,
794 PCI_DMA_FROMDEVICE);
Avinash Patil07324842013-02-08 18:18:07 -0800795 dev_kfree_skb_any(skb);
796 }
797 card->evt_buf_list[i] = NULL;
798 memset(desc, 0, sizeof(*desc));
799 }
800
801 return;
802}
803
804/* This function creates buffer descriptor ring for TX
Amitkumar Karward930fae2011-10-11 17:41:21 -0700805 */
806static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
807{
808 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800809 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700810
811 /*
812 * driver maintaines the write pointer and firmware maintaines the read
813 * pointer. The write pointer starts at 0 (zero) while the read pointer
814 * starts at zero with rollover bit set
815 */
816 card->txbd_wrptr = 0;
Avinash Patilca8f2112013-02-08 18:18:09 -0800817
818 if (reg->pfu_enabled)
819 card->txbd_rdptr = 0;
820 else
821 card->txbd_rdptr |= reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700822
823 /* allocate shared memory for the BD ring and divide the same in to
824 several descriptors */
Avinash Patilca8f2112013-02-08 18:18:09 -0800825 if (reg->pfu_enabled)
826 card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
827 MWIFIEX_MAX_TXRX_BD;
828 else
829 card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
830 MWIFIEX_MAX_TXRX_BD;
831
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530832 mwifiex_dbg(adapter, INFO,
833 "info: txbd_ring: Allocating %d bytes\n",
834 card->txbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800835 card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
836 card->txbd_ring_size,
837 &card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700838 if (!card->txbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530839 mwifiex_dbg(adapter, ERROR,
840 "allocate consistent memory (%d bytes) failed!\n",
841 card->txbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800842 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700843 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530844 mwifiex_dbg(adapter, DATA,
845 "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
846 card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
847 (u32)((u64)card->txbd_ring_pbase >> 32),
848 card->txbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700849
Avinash Patil07324842013-02-08 18:18:07 -0800850 return mwifiex_init_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700851}
852
853static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
854{
855 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800856 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700857
Avinash Patil07324842013-02-08 18:18:07 -0800858 mwifiex_cleanup_txq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700859
Avinash Patilfc331462013-01-03 21:21:30 -0800860 if (card->txbd_ring_vbase)
861 pci_free_consistent(card->dev, card->txbd_ring_size,
862 card->txbd_ring_vbase,
863 card->txbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700864 card->txbd_ring_size = 0;
865 card->txbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800866 card->txbd_rdptr = 0 | reg->tx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700867 card->txbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800868 card->txbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700869
870 return 0;
871}
872
873/*
874 * This function creates buffer descriptor ring for RX
875 */
876static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
877{
878 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800879 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700880
881 /*
882 * driver maintaines the read pointer and firmware maintaines the write
883 * pointer. The write pointer starts at 0 (zero) while the read pointer
884 * starts at zero with rollover bit set
885 */
886 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800887 card->rxbd_rdptr = reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700888
Avinash Patilca8f2112013-02-08 18:18:09 -0800889 if (reg->pfu_enabled)
890 card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
891 MWIFIEX_MAX_TXRX_BD;
892 else
893 card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
894 MWIFIEX_MAX_TXRX_BD;
895
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530896 mwifiex_dbg(adapter, INFO,
897 "info: rxbd_ring: Allocating %d bytes\n",
898 card->rxbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800899 card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
900 card->rxbd_ring_size,
901 &card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700902 if (!card->rxbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530903 mwifiex_dbg(adapter, ERROR,
904 "allocate consistent memory (%d bytes) failed!\n",
905 card->rxbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800906 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700907 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700908
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530909 mwifiex_dbg(adapter, DATA,
910 "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
911 card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase,
912 (u32)((u64)card->rxbd_ring_pbase >> 32),
913 card->rxbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700914
Avinash Patil07324842013-02-08 18:18:07 -0800915 return mwifiex_init_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700916}
917
918/*
919 * This function deletes Buffer descriptor ring for RX
920 */
921static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
922{
923 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800924 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700925
Avinash Patil07324842013-02-08 18:18:07 -0800926 mwifiex_cleanup_rxq_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700927
Avinash Patilfc331462013-01-03 21:21:30 -0800928 if (card->rxbd_ring_vbase)
929 pci_free_consistent(card->dev, card->rxbd_ring_size,
930 card->rxbd_ring_vbase,
931 card->rxbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700932 card->rxbd_ring_size = 0;
933 card->rxbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800934 card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700935 card->rxbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -0800936 card->rxbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700937
938 return 0;
939}
940
941/*
942 * This function creates buffer descriptor ring for Events
943 */
944static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
945{
946 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800947 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700948
949 /*
950 * driver maintaines the read pointer and firmware maintaines the write
951 * pointer. The write pointer starts at 0 (zero) while the read pointer
952 * starts at zero with rollover bit set
953 */
954 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800955 card->evtbd_rdptr = reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700956
Avinash Patile05dc3e2013-02-08 18:18:08 -0800957 card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
Avinash Patilca8f2112013-02-08 18:18:09 -0800958 MWIFIEX_MAX_EVT_BD;
959
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530960 mwifiex_dbg(adapter, INFO,
961 "info: evtbd_ring: Allocating %d bytes\n",
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -0700962 card->evtbd_ring_size);
Avinash Patilfc331462013-01-03 21:21:30 -0800963 card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
964 card->evtbd_ring_size,
965 &card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700966 if (!card->evtbd_ring_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530967 mwifiex_dbg(adapter, ERROR,
968 "allocate consistent memory (%d bytes) failed!\n",
969 card->evtbd_ring_size);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -0800970 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700971 }
Amitkumar Karward930fae2011-10-11 17:41:21 -0700972
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +0530973 mwifiex_dbg(adapter, EVENT,
974 "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
975 card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase,
976 (u32)((u64)card->evtbd_ring_pbase >> 32),
977 card->evtbd_ring_size);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700978
Avinash Patil07324842013-02-08 18:18:07 -0800979 return mwifiex_pcie_init_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700980}
981
982/*
983 * This function deletes Buffer descriptor ring for Events
984 */
985static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
986{
987 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800988 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700989
Avinash Patil07324842013-02-08 18:18:07 -0800990 mwifiex_cleanup_evt_ring(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700991
Avinash Patilfc331462013-01-03 21:21:30 -0800992 if (card->evtbd_ring_vbase)
993 pci_free_consistent(card->dev, card->evtbd_ring_size,
994 card->evtbd_ring_vbase,
995 card->evtbd_ring_pbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -0700996 card->evtbd_wrptr = 0;
Avinash Patildd04e6a2013-02-08 18:18:06 -0800997 card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
Amitkumar Karward930fae2011-10-11 17:41:21 -0700998 card->evtbd_ring_size = 0;
999 card->evtbd_ring_vbase = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -08001000 card->evtbd_ring_pbase = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001001
1002 return 0;
1003}
1004
1005/*
1006 * This function allocates a buffer for CMDRSP
1007 */
1008static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
1009{
1010 struct pcie_service_card *card = adapter->card;
1011 struct sk_buff *skb;
1012
1013 /* Allocate memory for receiving command response data */
1014 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
1015 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301016 mwifiex_dbg(adapter, ERROR,
1017 "Unable to allocate skb for command response data.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001018 return -ENOMEM;
1019 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001020 skb_put(skb, MWIFIEX_UPLD_SIZE);
Avinash Patilfc331462013-01-03 21:21:30 -08001021 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1022 PCI_DMA_FROMDEVICE))
1023 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001024
Avinash Patilfc331462013-01-03 21:21:30 -08001025 card->cmdrsp_buf = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001026
1027 return 0;
1028}
1029
1030/*
1031 * This function deletes a buffer for CMDRSP
1032 */
1033static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
1034{
1035 struct pcie_service_card *card;
1036
1037 if (!adapter)
1038 return 0;
1039
1040 card = adapter->card;
1041
Avinash Patilfc331462013-01-03 21:21:30 -08001042 if (card && card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001043 mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
1044 PCI_DMA_FROMDEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001045 dev_kfree_skb_any(card->cmdrsp_buf);
Brian Norris7dc4a6b2017-07-24 18:13:19 -07001046 card->cmdrsp_buf = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -08001047 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001048
Avinash Patilfc331462013-01-03 21:21:30 -08001049 if (card && card->cmd_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001050 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1051 PCI_DMA_TODEVICE);
Brian Norris3c8cb9a2017-04-14 14:51:17 -07001052 dev_kfree_skb_any(card->cmd_buf);
Brian Norris7dc4a6b2017-07-24 18:13:19 -07001053 card->cmd_buf = NULL;
Avinash Patilfc331462013-01-03 21:21:30 -08001054 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001055 return 0;
1056}
1057
1058/*
1059 * This function allocates a buffer for sleep cookie
1060 */
1061static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
1062{
Amitkumar Karward930fae2011-10-11 17:41:21 -07001063 struct pcie_service_card *card = adapter->card;
Devidas Puranik92c70a92017-03-09 14:06:17 +05301064 u32 tmp;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001065
Avinash Patilfc331462013-01-03 21:21:30 -08001066 card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
1067 &card->sleep_cookie_pbase);
1068 if (!card->sleep_cookie_vbase) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301069 mwifiex_dbg(adapter, ERROR,
1070 "pci_alloc_consistent failed!\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001071 return -ENOMEM;
1072 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001073 /* Init val of Sleep Cookie */
Devidas Puranik92c70a92017-03-09 14:06:17 +05301074 tmp = FW_AWAKE_COOKIE;
1075 put_unaligned(tmp, card->sleep_cookie_vbase);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001076
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301077 mwifiex_dbg(adapter, INFO,
1078 "alloc_scook: sleep cookie=0x%x\n",
Devidas Puranik92c70a92017-03-09 14:06:17 +05301079 get_unaligned(card->sleep_cookie_vbase));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001080
1081 return 0;
1082}
1083
1084/*
1085 * This function deletes buffer for sleep cookie
1086 */
1087static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
1088{
1089 struct pcie_service_card *card;
1090
1091 if (!adapter)
1092 return 0;
1093
1094 card = adapter->card;
1095
Avinash Patilfc331462013-01-03 21:21:30 -08001096 if (card && card->sleep_cookie_vbase) {
1097 pci_free_consistent(card->dev, sizeof(u32),
1098 card->sleep_cookie_vbase,
1099 card->sleep_cookie_pbase);
1100 card->sleep_cookie_vbase = NULL;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001101 }
1102
1103 return 0;
1104}
1105
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001106/* This function flushes the TX buffer descriptor ring
1107 * This function defined as handler is also called while cleaning TXRX
1108 * during disconnect/ bss stop.
1109 */
1110static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
1111{
1112 struct pcie_service_card *card = adapter->card;
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001113
Avinash Patil48f4d912013-02-20 21:12:58 -08001114 if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) {
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001115 card->txbd_flush = 1;
1116 /* write pointer already set at last send
1117 * send dnld-rdy intr again, wait for completion.
1118 */
1119 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1120 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301121 mwifiex_dbg(adapter, ERROR,
1122 "failed to assert dnld-rdy interrupt.\n");
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08001123 return -1;
1124 }
1125 }
1126 return 0;
1127}
1128
Amitkumar Karward930fae2011-10-11 17:41:21 -07001129/*
Avinash Patile7f767a2013-01-03 21:21:32 -08001130 * This function unmaps and frees downloaded data buffer
Amitkumar Karward930fae2011-10-11 17:41:21 -07001131 */
Avinash Patile7f767a2013-01-03 21:21:32 -08001132static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001133{
Avinash Patile7f767a2013-01-03 21:21:32 -08001134 struct sk_buff *skb;
Avinash Patilca8f2112013-02-08 18:18:09 -08001135 u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001136 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001137 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001138 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001139 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001140
1141 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1142 mwifiex_pm_wakeup_card(adapter);
1143
1144 /* Read the TX ring read pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001145 if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301146 mwifiex_dbg(adapter, ERROR,
1147 "SEND COMP: failed to read reg->tx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001148 return -1;
1149 }
1150
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301151 mwifiex_dbg(adapter, DATA,
1152 "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
1153 card->txbd_rdptr, rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001154
Avinash Patilca8f2112013-02-08 18:18:09 -08001155 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001156 /* free from previous txbd_rdptr to current txbd_rdptr */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001157 while (((card->txbd_rdptr & reg->tx_mask) !=
1158 (rdptr & reg->tx_mask)) ||
1159 ((card->txbd_rdptr & reg->tx_rollover_ind) !=
1160 (rdptr & reg->tx_rollover_ind))) {
Avinash Patilca8f2112013-02-08 18:18:09 -08001161 wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
1162 reg->tx_start_ptr;
Avinash Patile7f767a2013-01-03 21:21:32 -08001163
1164 skb = card->tx_buf_list[wrdoneidx];
Aaron Durbindbccc922014-02-07 16:25:50 -08001165
Avinash Patile7f767a2013-01-03 21:21:32 -08001166 if (skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301167 mwifiex_dbg(adapter, DATA,
1168 "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
1169 skb, wrdoneidx);
Aaron Durbindbccc922014-02-07 16:25:50 -08001170 mwifiex_unmap_pci_memory(adapter, skb,
1171 PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001172
1173 unmap_count++;
1174
1175 if (card->txbd_flush)
1176 mwifiex_write_data_complete(adapter, skb, 0,
1177 -1);
1178 else
1179 mwifiex_write_data_complete(adapter, skb, 0, 0);
Shengzhen Lieb2428fb2016-11-18 19:30:24 +05301180 atomic_dec(&adapter->tx_hw_pending);
Avinash Patile7f767a2013-01-03 21:21:32 -08001181 }
1182
1183 card->tx_buf_list[wrdoneidx] = NULL;
Avinash Patilca8f2112013-02-08 18:18:09 -08001184
1185 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001186 desc2 = card->txbd_ring[wrdoneidx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001187 memset(desc2, 0, sizeof(*desc2));
1188 } else {
1189 desc = card->txbd_ring[wrdoneidx];
1190 memset(desc, 0, sizeof(*desc));
1191 }
1192 switch (card->dev->device) {
1193 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1194 card->txbd_rdptr++;
1195 break;
1196 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001197 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001198 card->txbd_rdptr += reg->ring_tx_start_ptr;
1199 break;
1200 }
1201
Avinash Patile7f767a2013-01-03 21:21:32 -08001202
Avinash Patildd04e6a2013-02-08 18:18:06 -08001203 if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
Avinash Patile7f767a2013-01-03 21:21:32 -08001204 card->txbd_rdptr = ((card->txbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001205 reg->tx_rollover_ind) ^
1206 reg->tx_rollover_ind);
Avinash Patile7f767a2013-01-03 21:21:32 -08001207 }
1208
1209 if (unmap_count)
1210 adapter->data_sent = false;
1211
1212 if (card->txbd_flush) {
Avinash Patil3d482032013-02-15 21:37:54 -08001213 if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
Avinash Patile7f767a2013-01-03 21:21:32 -08001214 card->txbd_flush = 0;
1215 else
1216 mwifiex_clean_pcie_ring_buf(adapter);
1217 }
1218
1219 return 0;
1220}
1221
1222/* This function sends data buffer to device. First 4 bytes of payload
1223 * are filled with payload length and payload type. Then this payload
1224 * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
1225 * Download ready interrupt to FW is deffered if Tx ring is not full and
1226 * additional payload can be accomodated.
Avinash Patil8d767dc2014-05-13 19:50:13 -07001227 * Caller must ensure tx_param parameter to this function is not NULL.
Avinash Patile7f767a2013-01-03 21:21:32 -08001228 */
1229static int
1230mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
1231 struct mwifiex_tx_param *tx_param)
1232{
1233 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001234 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001235 u32 wrindx, num_tx_buffs, rx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001236 int ret;
1237 dma_addr_t buf_pa;
Bing Zhao99310782013-03-04 16:27:55 -08001238 struct mwifiex_pcie_buf_desc *desc = NULL;
1239 struct mwifiex_pfu_buf_desc *desc2 = NULL;
Avinash Patile7f767a2013-01-03 21:21:32 -08001240
1241 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301242 mwifiex_dbg(adapter, ERROR,
1243 "%s(): invalid parameter <%p, %#x>\n",
1244 __func__, skb->data, skb->len);
Avinash Patile7f767a2013-01-03 21:21:32 -08001245 return -1;
1246 }
1247
1248 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1249 mwifiex_pm_wakeup_card(adapter);
1250
Avinash Patilca8f2112013-02-08 18:18:09 -08001251 num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301252 mwifiex_dbg(adapter, DATA,
1253 "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
Avinash Patile7f767a2013-01-03 21:21:32 -08001254 card->txbd_rdptr, card->txbd_wrptr);
1255 if (mwifiex_pcie_txbd_not_full(card)) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001256 u8 *payload;
1257
1258 adapter->data_sent = true;
Avinash Patile7f767a2013-01-03 21:21:32 -08001259 payload = skb->data;
Devidas Puranik92c70a92017-03-09 14:06:17 +05301260 put_unaligned_le16((u16)skb->len, payload + 0);
1261 put_unaligned_le16(MWIFIEX_TYPE_DATA, payload + 2);
Avinash Patile7f767a2013-01-03 21:21:32 -08001262
Aaron Durbindbccc922014-02-07 16:25:50 -08001263 if (mwifiex_map_pci_memory(adapter, skb, skb->len,
Avinash Patile7f767a2013-01-03 21:21:32 -08001264 PCI_DMA_TODEVICE))
1265 return -1;
1266
Avinash Patilca8f2112013-02-08 18:18:09 -08001267 wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
Aaron Durbindbccc922014-02-07 16:25:50 -08001268 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile7f767a2013-01-03 21:21:32 -08001269 card->tx_buf_list[wrindx] = skb;
Shengzhen Lieb2428fb2016-11-18 19:30:24 +05301270 atomic_inc(&adapter->tx_hw_pending);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001271
Avinash Patilca8f2112013-02-08 18:18:09 -08001272 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001273 desc2 = card->txbd_ring[wrindx];
Avinash Patilca8f2112013-02-08 18:18:09 -08001274 desc2->paddr = buf_pa;
1275 desc2->len = (u16)skb->len;
1276 desc2->frag_len = (u16)skb->len;
1277 desc2->offset = 0;
1278 desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1279 MWIFIEX_BD_FLAG_LAST_DESC;
1280 } else {
1281 desc = card->txbd_ring[wrindx];
1282 desc->paddr = buf_pa;
1283 desc->len = (u16)skb->len;
1284 desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
1285 MWIFIEX_BD_FLAG_LAST_DESC;
1286 }
1287
1288 switch (card->dev->device) {
1289 case PCIE_DEVICE_ID_MARVELL_88W8766P:
1290 card->txbd_wrptr++;
1291 break;
1292 case PCIE_DEVICE_ID_MARVELL_88W8897:
Zhaoyang Liu6d85ef02015-08-05 06:09:40 -07001293 case PCIE_DEVICE_ID_MARVELL_88W8997:
Avinash Patilca8f2112013-02-08 18:18:09 -08001294 card->txbd_wrptr += reg->ring_tx_start_ptr;
1295 break;
1296 }
1297
1298 if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
Amitkumar Karward930fae2011-10-11 17:41:21 -07001299 card->txbd_wrptr = ((card->txbd_wrptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001300 reg->tx_rollover_ind) ^
1301 reg->tx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001302
Avinash Patilca8f2112013-02-08 18:18:09 -08001303 rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001304 /* Write the TX ring write pointer in to reg->tx_wrptr */
1305 if (mwifiex_write_reg(adapter, reg->tx_wrptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001306 card->txbd_wrptr | rx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301307 mwifiex_dbg(adapter, ERROR,
1308 "SEND DATA: failed to write reg->tx_wrptr\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001309 ret = -1;
1310 goto done_unmap;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001311 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001312 if ((mwifiex_pcie_txbd_not_full(card)) &&
1313 tx_param->next_pkt_len) {
1314 /* have more packets and TxBD still can hold more */
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301315 mwifiex_dbg(adapter, DATA,
1316 "SEND DATA: delay dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001317 adapter->data_sent = false;
1318 } else {
1319 /* Send the TX ready interrupt */
1320 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1321 CPU_INTR_DNLD_RDY)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301322 mwifiex_dbg(adapter, ERROR,
1323 "SEND DATA: failed to assert dnld-rdy interrupt.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001324 ret = -1;
1325 goto done_unmap;
1326 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001327 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301328 mwifiex_dbg(adapter, DATA,
1329 "info: SEND DATA: Updated <Rd: %#x, Wr:\t"
1330 "%#x> and sent packet to firmware successfully\n",
1331 card->txbd_rdptr, card->txbd_wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001332 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301333 mwifiex_dbg(adapter, DATA,
1334 "info: TX Ring full, can't send packets to fw\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001335 adapter->data_sent = true;
1336 /* Send the TX ready interrupt */
1337 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1338 CPU_INTR_DNLD_RDY))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301339 mwifiex_dbg(adapter, ERROR,
1340 "SEND DATA: failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001341 return -EBUSY;
1342 }
1343
Avinash Patile7f767a2013-01-03 21:21:32 -08001344 return -EINPROGRESS;
1345done_unmap:
Aaron Durbindbccc922014-02-07 16:25:50 -08001346 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001347 card->tx_buf_list[wrindx] = NULL;
Shengzhen Lieb2428fb2016-11-18 19:30:24 +05301348 atomic_dec(&adapter->tx_hw_pending);
Avinash Patilca8f2112013-02-08 18:18:09 -08001349 if (reg->pfu_enabled)
1350 memset(desc2, 0, sizeof(*desc2));
1351 else
1352 memset(desc, 0, sizeof(*desc));
1353
Avinash Patile7f767a2013-01-03 21:21:32 -08001354 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001355}
1356
1357/*
1358 * This function handles received buffer ring and
1359 * dispatches packets to upper
1360 */
1361static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
1362{
1363 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001364 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001365 u32 wrptr, rd_index, tx_val;
Avinash Patile7f767a2013-01-03 21:21:32 -08001366 dma_addr_t buf_pa;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001367 int ret = 0;
1368 struct sk_buff *skb_tmp = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001369 struct mwifiex_pcie_buf_desc *desc;
Avinash Patilca8f2112013-02-08 18:18:09 -08001370 struct mwifiex_pfu_buf_desc *desc2;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001371
Avinash Patile7f767a2013-01-03 21:21:32 -08001372 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1373 mwifiex_pm_wakeup_card(adapter);
1374
Amitkumar Karward930fae2011-10-11 17:41:21 -07001375 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001376 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301377 mwifiex_dbg(adapter, ERROR,
1378 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001379 ret = -1;
1380 goto done;
1381 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001382 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001383
Avinash Patildd04e6a2013-02-08 18:18:06 -08001384 while (((wrptr & reg->rx_mask) !=
1385 (card->rxbd_rdptr & reg->rx_mask)) ||
1386 ((wrptr & reg->rx_rollover_ind) ==
1387 (card->rxbd_rdptr & reg->rx_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001388 struct sk_buff *skb_data;
1389 u16 rx_len;
1390
Avinash Patildd04e6a2013-02-08 18:18:06 -08001391 rd_index = card->rxbd_rdptr & reg->rx_mask;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001392 skb_data = card->rx_buf_list[rd_index];
1393
Amitkumar Karwarbb8e6a12014-02-18 15:41:55 -08001394 /* If skb allocation was failed earlier for Rx packet,
1395 * rx_buf_list[rd_index] would have been left with a NULL.
1396 */
1397 if (!skb_data)
1398 return -ENOMEM;
1399
Aaron Durbindbccc922014-02-07 16:25:50 -08001400 mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
Avinash Patile7f767a2013-01-03 21:21:32 -08001401 card->rx_buf_list[rd_index] = NULL;
1402
Amitkumar Karward930fae2011-10-11 17:41:21 -07001403 /* Get data length from interface header -
Avinash Patile7f767a2013-01-03 21:21:32 -08001404 * first 2 bytes for len, next 2 bytes is for type
1405 */
Devidas Puranik92c70a92017-03-09 14:06:17 +05301406 rx_len = get_unaligned_le16(skb_data->data);
Xinming Huf4c5d599152017-05-23 07:12:30 +00001407 if (WARN_ON(rx_len <= adapter->intf_hdr_len ||
Avinash Patil42a028a2014-09-12 20:08:47 +05301408 rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301409 mwifiex_dbg(adapter, ERROR,
1410 "Invalid RX len %d, Rd=%#x, Wr=%#x\n",
1411 rx_len, card->rxbd_rdptr, wrptr);
Avinash Patil42a028a2014-09-12 20:08:47 +05301412 dev_kfree_skb_any(skb_data);
1413 } else {
1414 skb_put(skb_data, rx_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301415 mwifiex_dbg(adapter, DATA,
1416 "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
1417 card->rxbd_rdptr, wrptr, rx_len);
Xinming Huf4c5d599152017-05-23 07:12:30 +00001418 skb_pull(skb_data, adapter->intf_hdr_len);
Avinash Patil6e251172014-09-12 20:08:59 +05301419 if (adapter->rx_work_enabled) {
Avinash Patil6e251172014-09-12 20:08:59 +05301420 skb_queue_tail(&adapter->rx_data_q, skb_data);
Avinash Patil6e251172014-09-12 20:08:59 +05301421 adapter->data_received = true;
1422 atomic_inc(&adapter->rx_pending);
1423 } else {
1424 mwifiex_handle_rx_packet(adapter, skb_data);
1425 }
Avinash Patil42a028a2014-09-12 20:08:47 +05301426 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001427
Avinash Patil62159942015-03-13 17:37:52 +05301428 skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE,
Mathias Krause5c87a552016-05-21 15:43:31 +02001429 GFP_KERNEL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001430 if (!skb_tmp) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301431 mwifiex_dbg(adapter, ERROR,
1432 "Unable to allocate skb.\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001433 return -ENOMEM;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001434 }
1435
Avinash Patile7f767a2013-01-03 21:21:32 -08001436 if (mwifiex_map_pci_memory(adapter, skb_tmp,
1437 MWIFIEX_RX_DATA_BUF_SIZE,
1438 PCI_DMA_FROMDEVICE))
1439 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001440
Aaron Durbindbccc922014-02-07 16:25:50 -08001441 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
Avinash Patile7f767a2013-01-03 21:21:32 -08001442
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301443 mwifiex_dbg(adapter, INFO,
1444 "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
1445 skb_tmp, rd_index);
Avinash Patile7f767a2013-01-03 21:21:32 -08001446 card->rx_buf_list[rd_index] = skb_tmp;
Avinash Patilca8f2112013-02-08 18:18:09 -08001447
1448 if (reg->pfu_enabled) {
Joe Perches45d18c52014-03-24 13:15:39 -07001449 desc2 = card->rxbd_ring[rd_index];
Avinash Patilca8f2112013-02-08 18:18:09 -08001450 desc2->paddr = buf_pa;
1451 desc2->len = skb_tmp->len;
1452 desc2->frag_len = skb_tmp->len;
1453 desc2->offset = 0;
1454 desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
1455 } else {
1456 desc = card->rxbd_ring[rd_index];
1457 desc->paddr = buf_pa;
1458 desc->len = skb_tmp->len;
1459 desc->flags = 0;
1460 }
Avinash Patile7f767a2013-01-03 21:21:32 -08001461
Avinash Patildd04e6a2013-02-08 18:18:06 -08001462 if ((++card->rxbd_rdptr & reg->rx_mask) ==
Amitkumar Karward930fae2011-10-11 17:41:21 -07001463 MWIFIEX_MAX_TXRX_BD) {
1464 card->rxbd_rdptr = ((card->rxbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001465 reg->rx_rollover_ind) ^
1466 reg->rx_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001467 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301468 mwifiex_dbg(adapter, DATA,
1469 "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
1470 card->rxbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001471
Avinash Patilca8f2112013-02-08 18:18:09 -08001472 tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001473 /* Write the RX ring read pointer in to reg->rx_rdptr */
1474 if (mwifiex_write_reg(adapter, reg->rx_rdptr,
Avinash Patilca8f2112013-02-08 18:18:09 -08001475 card->rxbd_rdptr | tx_val)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301476 mwifiex_dbg(adapter, DATA,
1477 "RECV DATA: failed to write reg->rx_rdptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001478 ret = -1;
1479 goto done;
1480 }
1481
1482 /* Read the RX ring Write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001483 if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301484 mwifiex_dbg(adapter, ERROR,
1485 "RECV DATA: failed to read reg->rx_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001486 ret = -1;
1487 goto done;
1488 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301489 mwifiex_dbg(adapter, DATA,
1490 "info: RECV DATA: Rcvd packet from fw successfully\n");
Avinash Patile7f767a2013-01-03 21:21:32 -08001491 card->rxbd_wrptr = wrptr;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001492 }
1493
1494done:
Amitkumar Karward930fae2011-10-11 17:41:21 -07001495 return ret;
1496}
1497
1498/*
1499 * This function downloads the boot command to device
1500 */
1501static int
1502mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1503{
Avinash Patilfc331462013-01-03 21:21:30 -08001504 dma_addr_t buf_pa;
1505 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001506 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001507
Avinash Patilfc331462013-01-03 21:21:30 -08001508 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301509 mwifiex_dbg(adapter, ERROR,
1510 "Invalid parameter in %s <%p. len %d>\n",
1511 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001512 return -1;
1513 }
1514
Ujjal Roy3a968d72016-02-25 00:49:43 +05301515 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
Avinash Patilfc331462013-01-03 21:21:30 -08001516 return -1;
1517
Aaron Durbindbccc922014-02-07 16:25:50 -08001518 buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patilfc331462013-01-03 21:21:30 -08001519
Avinash Patildd04e6a2013-02-08 18:18:06 -08001520 /* Write the lower 32bits of the physical address to low command
1521 * address scratch register
1522 */
1523 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301524 mwifiex_dbg(adapter, ERROR,
1525 "%s: failed to write download command to boot code.\n",
1526 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001527 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001528 return -1;
1529 }
1530
Avinash Patildd04e6a2013-02-08 18:18:06 -08001531 /* Write the upper 32bits of the physical address to high command
1532 * address scratch register
1533 */
1534 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001535 (u32)((u64)buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301536 mwifiex_dbg(adapter, ERROR,
1537 "%s: failed to write download command to boot code.\n",
1538 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001539 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001540 return -1;
1541 }
1542
Avinash Patildd04e6a2013-02-08 18:18:06 -08001543 /* Write the command length to cmd_size scratch register */
1544 if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301545 mwifiex_dbg(adapter, ERROR,
1546 "%s: failed to write command len to cmd_size scratch reg\n",
1547 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001548 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001549 return -1;
1550 }
1551
1552 /* Ring the door bell */
1553 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1554 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301555 mwifiex_dbg(adapter, ERROR,
1556 "%s: failed to assert door-bell intr\n", __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08001557 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001558 return -1;
1559 }
1560
1561 return 0;
1562}
1563
Avinash Patilc6d1d872013-01-03 21:21:29 -08001564/* This function init rx port in firmware which in turn enables to receive data
1565 * from device before transmitting any packet.
1566 */
1567static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
1568{
1569 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001570 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Avinash Patilca8f2112013-02-08 18:18:09 -08001571 int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
Avinash Patilc6d1d872013-01-03 21:21:29 -08001572
Avinash Patildd04e6a2013-02-08 18:18:06 -08001573 /* Write the RX ring read pointer in to reg->rx_rdptr */
Avinash Patilca8f2112013-02-08 18:18:09 -08001574 if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
1575 tx_wrap)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301576 mwifiex_dbg(adapter, ERROR,
1577 "RECV DATA: failed to write reg->rx_rdptr\n");
Avinash Patilc6d1d872013-01-03 21:21:29 -08001578 return -1;
1579 }
1580 return 0;
1581}
1582
1583/* This function downloads commands to the device
Amitkumar Karward930fae2011-10-11 17:41:21 -07001584 */
1585static int
1586mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
1587{
1588 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001589 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001590 int ret = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001591 dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
1592 u8 *payload = (u8 *)skb->data;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001593
1594 if (!(skb->data && skb->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301595 mwifiex_dbg(adapter, ERROR,
1596 "Invalid parameter in %s <%p, %#x>\n",
1597 __func__, skb->data, skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001598 return -1;
1599 }
1600
1601 /* Make sure a command response buffer is available */
1602 if (!card->cmdrsp_buf) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301603 mwifiex_dbg(adapter, ERROR,
1604 "No response buffer available, send command failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001605 return -EBUSY;
1606 }
1607
Avinash Patilfc331462013-01-03 21:21:30 -08001608 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1609 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001610
1611 adapter->cmd_sent = true;
Avinash Patilfc331462013-01-03 21:21:30 -08001612
Devidas Puranik92c70a92017-03-09 14:06:17 +05301613 put_unaligned_le16((u16)skb->len, &payload[0]);
1614 put_unaligned_le16(MWIFIEX_TYPE_CMD, &payload[2]);
Avinash Patilfc331462013-01-03 21:21:30 -08001615
1616 if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
1617 return -1;
1618
1619 card->cmd_buf = skb;
Brian Norris3c8cb9a2017-04-14 14:51:17 -07001620 /*
1621 * Need to keep a reference, since core driver might free up this
1622 * buffer before we've unmapped it.
1623 */
1624 skb_get(skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001625
1626 /* To send a command, the driver will:
1627 1. Write the 64bit physical address of the data buffer to
Avinash Patildd04e6a2013-02-08 18:18:06 -08001628 cmd response address low + cmd response address high
Amitkumar Karward930fae2011-10-11 17:41:21 -07001629 2. Ring the door bell (i.e. set the door bell interrupt)
1630
1631 In response to door bell interrupt, the firmware will perform
1632 the DMA of the command packet (first header to obtain the total
1633 length and then rest of the command).
1634 */
1635
1636 if (card->cmdrsp_buf) {
Aaron Durbindbccc922014-02-07 16:25:50 -08001637 cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001638 /* Write the lower 32bits of the cmdrsp buffer physical
1639 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001640 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
Avinash Patilfc331462013-01-03 21:21:30 -08001641 (u32)cmdrsp_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301642 mwifiex_dbg(adapter, ERROR,
1643 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001644 ret = -1;
1645 goto done;
1646 }
1647 /* Write the upper 32bits of the cmdrsp buffer physical
1648 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001649 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001650 (u32)((u64)cmdrsp_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301651 mwifiex_dbg(adapter, ERROR,
1652 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001653 ret = -1;
1654 goto done;
1655 }
1656 }
1657
Aaron Durbindbccc922014-02-07 16:25:50 -08001658 cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf);
Avinash Patildd04e6a2013-02-08 18:18:06 -08001659 /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
1660 if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
1661 (u32)cmd_buf_pa)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301662 mwifiex_dbg(adapter, ERROR,
1663 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001664 ret = -1;
1665 goto done;
1666 }
Avinash Patildd04e6a2013-02-08 18:18:06 -08001667 /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
1668 if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
Avinash Patilfc331462013-01-03 21:21:30 -08001669 (u32)((u64)cmd_buf_pa >> 32))) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301670 mwifiex_dbg(adapter, ERROR,
1671 "Failed to write download cmd to boot code.\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001672 ret = -1;
1673 goto done;
1674 }
1675
Avinash Patildd04e6a2013-02-08 18:18:06 -08001676 /* Write the command length to reg->cmd_size */
1677 if (mwifiex_write_reg(adapter, reg->cmd_size,
1678 card->cmd_buf->len)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301679 mwifiex_dbg(adapter, ERROR,
1680 "Failed to write cmd len to reg->cmd_size\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001681 ret = -1;
1682 goto done;
1683 }
1684
1685 /* Ring the door bell */
1686 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1687 CPU_INTR_DOOR_BELL)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301688 mwifiex_dbg(adapter, ERROR,
1689 "Failed to assert door-bell intr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001690 ret = -1;
1691 goto done;
1692 }
1693
1694done:
1695 if (ret)
1696 adapter->cmd_sent = false;
1697
1698 return 0;
1699}
1700
1701/*
1702 * This function handles command complete interrupt
1703 */
1704static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
1705{
1706 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001707 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001708 struct sk_buff *skb = card->cmdrsp_buf;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001709 int count = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08001710 u16 rx_len;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001711
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301712 mwifiex_dbg(adapter, CMD,
1713 "info: Rx CMD Response\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001714
Amitkumar Karwar3e668492017-01-24 19:05:44 +05301715 if (adapter->curr_cmd)
1716 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
1717 else
1718 pci_dma_sync_single_for_cpu(card->dev,
1719 MWIFIEX_SKB_DMA_ADDR(skb),
1720 MWIFIEX_UPLD_SIZE,
1721 PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001722
Aaron Durbin189b3292014-02-07 16:25:51 -08001723 /* Unmap the command as a response has been received. */
1724 if (card->cmd_buf) {
1725 mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
1726 PCI_DMA_TODEVICE);
Brian Norris3c8cb9a2017-04-14 14:51:17 -07001727 dev_kfree_skb_any(card->cmd_buf);
Aaron Durbin189b3292014-02-07 16:25:51 -08001728 card->cmd_buf = NULL;
1729 }
1730
Devidas Puranik92c70a92017-03-09 14:06:17 +05301731 rx_len = get_unaligned_le16(skb->data);
Amitkumar Karwar2fd40d22016-07-15 19:07:05 +05301732 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001733 skb_trim(skb, rx_len);
Avinash Patilfc331462013-01-03 21:21:30 -08001734
Amitkumar Karward930fae2011-10-11 17:41:21 -07001735 if (!adapter->curr_cmd) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001736 if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
Amitkumar Karwar3e668492017-01-24 19:05:44 +05301737 pci_dma_sync_single_for_device(card->dev,
1738 MWIFIEX_SKB_DMA_ADDR(skb),
1739 MWIFIEX_SLEEP_COOKIE_SIZE,
1740 PCI_DMA_FROMDEVICE);
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001741 if (mwifiex_write_reg(adapter,
1742 PCIE_CPU_INT_EVENT,
1743 CPU_INTR_SLEEP_CFM_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301744 mwifiex_dbg(adapter, ERROR,
1745 "Write register failed\n");
Amitkumar Karwar1c975602014-02-18 15:41:56 -08001746 return -1;
1747 }
Avinash Patilc4bc9802014-03-18 22:19:17 -07001748 mwifiex_delay_for_sleep_cookie(adapter,
1749 MWIFIEX_MAX_DELAY_COUNT);
Amitkumar Karwar3e668492017-01-24 19:05:44 +05301750 mwifiex_unmap_pci_memory(adapter, skb,
1751 PCI_DMA_FROMDEVICE);
Xinming Huf4c5d599152017-05-23 07:12:30 +00001752 skb_pull(skb, adapter->intf_hdr_len);
Avinash Patil52301a82013-02-12 14:38:32 -08001753 while (reg->sleep_cookie && (count++ < 10) &&
1754 mwifiex_pcie_ok_to_access_hw(adapter))
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07001755 usleep_range(50, 60);
Amitkumar Karwarec815dd2016-09-28 18:18:21 +05301756 mwifiex_pcie_enable_host_int(adapter);
1757 mwifiex_process_sleep_confirm_resp(adapter, skb->data,
1758 skb->len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001759 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301760 mwifiex_dbg(adapter, ERROR,
1761 "There is no command but got cmdrsp\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001762 }
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001763 memcpy(adapter->upld_buf, skb->data,
1764 min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
Xinming Huf4c5d599152017-05-23 07:12:30 +00001765 skb_push(skb, adapter->intf_hdr_len);
Avinash Patilfc331462013-01-03 21:21:30 -08001766 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1767 PCI_DMA_FROMDEVICE))
1768 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001769 } else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
Xinming Huf4c5d599152017-05-23 07:12:30 +00001770 skb_pull(skb, adapter->intf_hdr_len);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001771 adapter->curr_cmd->resp_skb = skb;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001772 adapter->cmd_resp_received = true;
1773 /* Take the pointer and set it to CMD node and will
1774 return in the response complete callback */
1775 card->cmdrsp_buf = NULL;
1776
1777 /* Clear the cmd-rsp buffer address in scratch registers. This
1778 will prevent firmware from writing to the same response
1779 buffer again. */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001780 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301781 mwifiex_dbg(adapter, ERROR,
1782 "cmd_done: failed to clear cmd_rsp_addr_lo\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001783 return -1;
1784 }
1785 /* Write the upper 32bits of the cmdrsp buffer physical
1786 address */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001787 if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301788 mwifiex_dbg(adapter, ERROR,
1789 "cmd_done: failed to clear cmd_rsp_addr_hi\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001790 return -1;
1791 }
1792 }
1793
1794 return 0;
1795}
1796
1797/*
1798 * Command Response processing complete handler
1799 */
1800static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
1801 struct sk_buff *skb)
1802{
1803 struct pcie_service_card *card = adapter->card;
1804
1805 if (skb) {
1806 card->cmdrsp_buf = skb;
Xinming Huf4c5d599152017-05-23 07:12:30 +00001807 skb_push(card->cmdrsp_buf, adapter->intf_hdr_len);
Avinash Patilfc331462013-01-03 21:21:30 -08001808 if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
1809 PCI_DMA_FROMDEVICE))
1810 return -1;
1811 }
1812
Amitkumar Karward930fae2011-10-11 17:41:21 -07001813 return 0;
1814}
1815
1816/*
1817 * This function handles firmware event ready interrupt
1818 */
1819static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
1820{
1821 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001822 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001823 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1824 u32 wrptr, event;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001825 struct mwifiex_evt_buf_desc *desc;
Avinash Patilfc331462013-01-03 21:21:30 -08001826
1827 if (!mwifiex_pcie_ok_to_access_hw(adapter))
1828 mwifiex_pm_wakeup_card(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001829
1830 if (adapter->event_received) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301831 mwifiex_dbg(adapter, EVENT,
1832 "info: Event being processed,\t"
1833 "do not process this interrupt just yet\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001834 return 0;
1835 }
1836
1837 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301838 mwifiex_dbg(adapter, ERROR,
1839 "info: Invalid read pointer...\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001840 return -1;
1841 }
1842
1843 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001844 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301845 mwifiex_dbg(adapter, ERROR,
1846 "EventReady: failed to read reg->evt_wrptr\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001847 return -1;
1848 }
1849
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301850 mwifiex_dbg(adapter, EVENT,
1851 "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>",
1852 card->evtbd_rdptr, wrptr);
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07001853 if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
1854 & MWIFIEX_EVTBD_MASK)) ||
Avinash Patildd04e6a2013-02-08 18:18:06 -08001855 ((wrptr & reg->evt_rollover_ind) ==
1856 (card->evtbd_rdptr & reg->evt_rollover_ind))) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07001857 struct sk_buff *skb_cmd;
1858 __le16 data_len = 0;
1859 u16 evt_len;
1860
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301861 mwifiex_dbg(adapter, INFO,
1862 "info: Read Index: %d\n", rdptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001863 skb_cmd = card->evt_buf_list[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001864 mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08001865
Amitkumar Karward930fae2011-10-11 17:41:21 -07001866 /* Take the pointer and set it to event pointer in adapter
1867 and will return back after event handling callback */
1868 card->evt_buf_list[rdptr] = NULL;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001869 desc = card->evtbd_ring[rdptr];
1870 memset(desc, 0, sizeof(*desc));
Amitkumar Karward930fae2011-10-11 17:41:21 -07001871
Xinming Huf4c5d599152017-05-23 07:12:30 +00001872 event = get_unaligned_le32(
1873 &skb_cmd->data[adapter->intf_hdr_len]);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001874 adapter->event_cause = event;
1875 /* The first 4bytes will be the event transfer header
1876 len is 2 bytes followed by type which is 2 bytes */
1877 memcpy(&data_len, skb_cmd->data, sizeof(__le16));
1878 evt_len = le16_to_cpu(data_len);
Zhaoyang Liu868093a2015-05-12 00:48:19 +05301879 skb_trim(skb_cmd, evt_len);
Xinming Huf4c5d599152017-05-23 07:12:30 +00001880 skb_pull(skb_cmd, adapter->intf_hdr_len);
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301881 mwifiex_dbg(adapter, EVENT,
1882 "info: Event length: %d\n", evt_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001883
1884 if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE))
1885 memcpy(adapter->event_body, skb_cmd->data +
1886 MWIFIEX_EVENT_HEADER_LEN, evt_len -
1887 MWIFIEX_EVENT_HEADER_LEN);
1888
1889 adapter->event_received = true;
1890 adapter->event_skb = skb_cmd;
1891
1892 /* Do not update the event read pointer here, wait till the
1893 buffer is released. This is just to make things simpler,
1894 we need to find a better method of managing these buffers.
1895 */
Avinash Patil2703a662014-09-12 20:08:49 +05301896 } else {
1897 if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
1898 CPU_INTR_EVENT_DONE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301899 mwifiex_dbg(adapter, ERROR,
1900 "Write register failed\n");
Avinash Patil2703a662014-09-12 20:08:49 +05301901 return -1;
1902 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001903 }
1904
1905 return 0;
1906}
1907
1908/*
1909 * Event processing complete handler
1910 */
1911static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
1912 struct sk_buff *skb)
1913{
1914 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08001915 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001916 int ret = 0;
1917 u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
1918 u32 wrptr;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001919 struct mwifiex_evt_buf_desc *desc;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001920
1921 if (!skb)
1922 return 0;
1923
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001924 if (rdptr >= MWIFIEX_MAX_EVT_BD) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301925 mwifiex_dbg(adapter, ERROR,
1926 "event_complete: Invalid rdptr 0x%x\n",
1927 rdptr);
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001928 return -EINVAL;
Dan Carpenter1eb54c82011-11-07 19:31:47 -08001929 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07001930
1931 /* Read the event ring write pointer set by firmware */
Avinash Patildd04e6a2013-02-08 18:18:06 -08001932 if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301933 mwifiex_dbg(adapter, ERROR,
1934 "event_complete: failed to read reg->evt_wrptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001935 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001936 }
1937
1938 if (!card->evt_buf_list[rdptr]) {
Xinming Huf4c5d599152017-05-23 07:12:30 +00001939 skb_push(skb, adapter->intf_hdr_len);
Amitkumar Karwar2728cec2015-07-22 04:53:45 -07001940 skb_put(skb, MAX_EVENT_SIZE - skb->len);
Avinash Patilfc331462013-01-03 21:21:30 -08001941 if (mwifiex_map_pci_memory(adapter, skb,
1942 MAX_EVENT_SIZE,
1943 PCI_DMA_FROMDEVICE))
1944 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001945 card->evt_buf_list[rdptr] = skb;
Avinash Patile05dc3e2013-02-08 18:18:08 -08001946 desc = card->evtbd_ring[rdptr];
Aaron Durbindbccc922014-02-07 16:25:50 -08001947 desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb);
Avinash Patile05dc3e2013-02-08 18:18:08 -08001948 desc->len = (u16)skb->len;
1949 desc->flags = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001950 skb = NULL;
1951 } else {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301952 mwifiex_dbg(adapter, ERROR,
1953 "info: ERROR: buf still valid at index %d, <%p, %p>\n",
1954 rdptr, card->evt_buf_list[rdptr], skb);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001955 }
1956
1957 if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
1958 card->evtbd_rdptr = ((card->evtbd_rdptr &
Avinash Patildd04e6a2013-02-08 18:18:06 -08001959 reg->evt_rollover_ind) ^
1960 reg->evt_rollover_ind);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001961 }
1962
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301963 mwifiex_dbg(adapter, EVENT,
1964 "info: Updated <Rd: 0x%x, Wr: 0x%x>",
1965 card->evtbd_rdptr, wrptr);
Amitkumar Karward930fae2011-10-11 17:41:21 -07001966
Avinash Patildd04e6a2013-02-08 18:18:06 -08001967 /* Write the event ring read pointer in to reg->evt_rdptr */
1968 if (mwifiex_write_reg(adapter, reg->evt_rdptr,
1969 card->evtbd_rdptr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301970 mwifiex_dbg(adapter, ERROR,
1971 "event_complete: failed to read reg->evt_rdptr\n");
Amitkumar Karwar8c53e422011-12-08 20:41:03 -08001972 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07001973 }
1974
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05301975 mwifiex_dbg(adapter, EVENT,
1976 "info: Check Events Again\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07001977 ret = mwifiex_pcie_process_event_ready(adapter);
1978
1979 return ret;
1980}
1981
Xinming Huefde6642017-04-13 13:10:33 -07001982/* Combo firmware image is a combination of
1983 * (1) combo crc heaer, start with CMD5
1984 * (2) bluetooth image, start with CMD7, end with CMD6, data wrapped in CMD1.
1985 * (3) wifi image.
1986 *
1987 * This function bypass the header and bluetooth part, return
Xinming Hue7ece052017-08-01 01:38:24 +00001988 * the offset of tail wifi-only part. If the image is already wifi-only,
1989 * that is start with CMD1, return 0.
Xinming Huefde6642017-04-13 13:10:33 -07001990 */
1991
1992static int mwifiex_extract_wifi_fw(struct mwifiex_adapter *adapter,
1993 const void *firmware, u32 firmware_len) {
1994 const struct mwifiex_fw_data *fwdata;
1995 u32 offset = 0, data_len, dnld_cmd;
1996 int ret = 0;
Xinming Hue7ece052017-08-01 01:38:24 +00001997 bool cmd7_before = false, first_cmd = false;
Xinming Huefde6642017-04-13 13:10:33 -07001998
1999 while (1) {
2000 /* Check for integer and buffer overflow */
2001 if (offset + sizeof(fwdata->header) < sizeof(fwdata->header) ||
2002 offset + sizeof(fwdata->header) >= firmware_len) {
2003 mwifiex_dbg(adapter, ERROR,
2004 "extract wifi-only fw failure!\n");
2005 ret = -1;
2006 goto done;
2007 }
2008
2009 fwdata = firmware + offset;
2010 dnld_cmd = le32_to_cpu(fwdata->header.dnld_cmd);
2011 data_len = le32_to_cpu(fwdata->header.data_length);
2012
2013 /* Skip past header */
2014 offset += sizeof(fwdata->header);
2015
2016 switch (dnld_cmd) {
2017 case MWIFIEX_FW_DNLD_CMD_1:
Xinming Hue7ece052017-08-01 01:38:24 +00002018 if (offset + data_len < data_len) {
2019 mwifiex_dbg(adapter, ERROR, "bad FW parse\n");
2020 ret = -1;
2021 goto done;
2022 }
2023
2024 /* Image start with cmd1, already wifi-only firmware */
2025 if (!first_cmd) {
2026 mwifiex_dbg(adapter, MSG,
2027 "input wifi-only firmware\n");
2028 return 0;
2029 }
2030
Xinming Huefde6642017-04-13 13:10:33 -07002031 if (!cmd7_before) {
2032 mwifiex_dbg(adapter, ERROR,
2033 "no cmd7 before cmd1!\n");
2034 ret = -1;
2035 goto done;
2036 }
Xinming Huefde6642017-04-13 13:10:33 -07002037 offset += data_len;
2038 break;
2039 case MWIFIEX_FW_DNLD_CMD_5:
Xinming Hue7ece052017-08-01 01:38:24 +00002040 first_cmd = true;
Xinming Huefde6642017-04-13 13:10:33 -07002041 /* Check for integer overflow */
2042 if (offset + data_len < data_len) {
2043 mwifiex_dbg(adapter, ERROR, "bad FW parse\n");
2044 ret = -1;
2045 goto done;
2046 }
2047 offset += data_len;
2048 break;
2049 case MWIFIEX_FW_DNLD_CMD_6:
Xinming Hue7ece052017-08-01 01:38:24 +00002050 first_cmd = true;
Xinming Huefde6642017-04-13 13:10:33 -07002051 /* Check for integer overflow */
2052 if (offset + data_len < data_len) {
2053 mwifiex_dbg(adapter, ERROR, "bad FW parse\n");
2054 ret = -1;
2055 goto done;
2056 }
2057 offset += data_len;
2058 if (offset >= firmware_len) {
2059 mwifiex_dbg(adapter, ERROR,
2060 "extract wifi-only fw failure!\n");
2061 ret = -1;
2062 } else {
2063 ret = offset;
2064 }
2065 goto done;
2066 case MWIFIEX_FW_DNLD_CMD_7:
Xinming Hue7ece052017-08-01 01:38:24 +00002067 first_cmd = true;
Xinming Huefde6642017-04-13 13:10:33 -07002068 cmd7_before = true;
2069 break;
2070 default:
2071 mwifiex_dbg(adapter, ERROR, "unknown dnld_cmd %d\n",
2072 dnld_cmd);
2073 ret = -1;
2074 goto done;
2075 }
2076 }
2077
2078done:
2079 return ret;
2080}
2081
Amitkumar Karward930fae2011-10-11 17:41:21 -07002082/*
2083 * This function downloads the firmware to the card.
2084 *
2085 * Firmware is downloaded to the card in blocks. Every block download
2086 * is tested for CRC errors, and retried a number of times before
2087 * returning failure.
2088 */
2089static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
2090 struct mwifiex_fw_image *fw)
2091{
2092 int ret;
2093 u8 *firmware = fw->fw_buf;
2094 u32 firmware_len = fw->fw_len;
2095 u32 offset = 0;
2096 struct sk_buff *skb;
Xinming Huefde6642017-04-13 13:10:33 -07002097 u32 txlen, tx_blocks = 0, tries, len, val;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002098 u32 block_retry_cnt = 0;
Avinash Patilfc331462013-01-03 21:21:30 -08002099 struct pcie_service_card *card = adapter->card;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002100 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002101
2102 if (!firmware || !firmware_len) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302103 mwifiex_dbg(adapter, ERROR,
2104 "No firmware image found! Terminating download\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002105 return -1;
2106 }
2107
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302108 mwifiex_dbg(adapter, INFO,
2109 "info: Downloading FW image (%d bytes)\n",
2110 firmware_len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002111
2112 if (mwifiex_pcie_disable_host_int(adapter)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302113 mwifiex_dbg(adapter, ERROR,
2114 "%s: Disabling interrupts failed.\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002115 return -1;
2116 }
2117
2118 skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE);
2119 if (!skb) {
2120 ret = -ENOMEM;
2121 goto done;
2122 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002123
Xinming Huefde6642017-04-13 13:10:33 -07002124 ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_13_REG, &val);
2125 if (ret) {
2126 mwifiex_dbg(adapter, FATAL, "Failed to read scratch register 13\n");
2127 goto done;
2128 }
2129
2130 /* PCIE FLR case: extract wifi part from combo firmware*/
2131 if (val == MWIFIEX_PCIE_FLR_HAPPENS) {
2132 ret = mwifiex_extract_wifi_fw(adapter, firmware, firmware_len);
2133 if (ret < 0) {
2134 mwifiex_dbg(adapter, ERROR, "Failed to extract wifi fw\n");
2135 goto done;
2136 }
2137 offset = ret;
2138 mwifiex_dbg(adapter, MSG,
2139 "info: dnld wifi firmware from %d bytes\n", offset);
2140 }
2141
Amitkumar Karward930fae2011-10-11 17:41:21 -07002142 /* Perform firmware data transfer */
2143 do {
2144 u32 ireg_intr = 0;
2145
2146 /* More data? */
2147 if (offset >= firmware_len)
2148 break;
2149
2150 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002151 ret = mwifiex_read_reg(adapter, reg->cmd_size,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002152 &len);
2153 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302154 mwifiex_dbg(adapter, FATAL,
2155 "Failed reading len from boot code\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002156 goto done;
2157 }
2158 if (len)
2159 break;
Yogesh Ashok Poware7891ba2012-03-12 19:35:11 -07002160 usleep_range(10, 20);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002161 }
2162
2163 if (!len) {
2164 break;
2165 } else if (len > MWIFIEX_UPLD_SIZE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302166 mwifiex_dbg(adapter, ERROR,
2167 "FW download failure @ %d, invalid length %d\n",
2168 offset, len);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002169 ret = -1;
2170 goto done;
2171 }
2172
2173 txlen = len;
2174
2175 if (len & BIT(0)) {
2176 block_retry_cnt++;
2177 if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302178 mwifiex_dbg(adapter, ERROR,
2179 "FW download failure @ %d, over max\t"
2180 "retry count\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002181 ret = -1;
2182 goto done;
2183 }
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302184 mwifiex_dbg(adapter, ERROR,
2185 "FW CRC error indicated by the\t"
2186 "helper: len = 0x%04X, txlen = %d\n",
2187 len, txlen);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002188 len &= ~BIT(0);
2189 /* Setting this to 0 to resend from same offset */
2190 txlen = 0;
2191 } else {
2192 block_retry_cnt = 0;
2193 /* Set blocksize to transfer - checking for
2194 last block */
2195 if (firmware_len - offset < txlen)
2196 txlen = firmware_len - offset;
2197
Avinash Patildd04e6a2013-02-08 18:18:06 -08002198 tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
2199 card->pcie.blksz_fw_dl;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002200
2201 /* Copy payload to buffer */
2202 memmove(skb->data, &firmware[offset], txlen);
2203 }
2204
2205 skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
Avinash Patildd04e6a2013-02-08 18:18:06 -08002206 skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002207
2208 /* Send the boot command to device */
2209 if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302210 mwifiex_dbg(adapter, ERROR,
2211 "Failed to send firmware download command\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002212 ret = -1;
2213 goto done;
2214 }
Avinash Patilfc331462013-01-03 21:21:30 -08002215
Amitkumar Karward930fae2011-10-11 17:41:21 -07002216 /* Wait for the command done interrupt */
Brian Norris22dde1e2016-11-22 18:39:45 -08002217 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
Amitkumar Karward930fae2011-10-11 17:41:21 -07002218 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
2219 &ireg_intr)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302220 mwifiex_dbg(adapter, ERROR,
2221 "%s: Failed to read\t"
2222 "interrupt status during fw dnld.\n",
2223 __func__);
Aaron Durbindbccc922014-02-07 16:25:50 -08002224 mwifiex_unmap_pci_memory(adapter, skb,
2225 PCI_DMA_TODEVICE);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002226 ret = -1;
2227 goto done;
2228 }
Brian Norris22dde1e2016-11-22 18:39:45 -08002229 if (!(ireg_intr & CPU_INTR_DOOR_BELL))
2230 break;
2231 usleep_range(10, 20);
2232 }
2233 if (ireg_intr & CPU_INTR_DOOR_BELL) {
2234 mwifiex_dbg(adapter, ERROR, "%s: Card failed to ACK download\n",
2235 __func__);
2236 mwifiex_unmap_pci_memory(adapter, skb,
2237 PCI_DMA_TODEVICE);
2238 ret = -1;
2239 goto done;
2240 }
Avinash Patilfc331462013-01-03 21:21:30 -08002241
Aaron Durbindbccc922014-02-07 16:25:50 -08002242 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
Avinash Patilfc331462013-01-03 21:21:30 -08002243
Amitkumar Karward930fae2011-10-11 17:41:21 -07002244 offset += txlen;
2245 } while (true);
2246
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302247 mwifiex_dbg(adapter, MSG,
2248 "info: FW download over, size %d bytes\n", offset);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002249
2250 ret = 0;
2251
2252done:
2253 dev_kfree_skb_any(skb);
2254 return ret;
2255}
2256
2257/*
2258 * This function checks the firmware status in card.
Amitkumar Karward930fae2011-10-11 17:41:21 -07002259 */
2260static int
2261mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
2262{
2263 int ret = 0;
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002264 u32 firmware_stat;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002265 struct pcie_service_card *card = adapter->card;
2266 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002267 u32 tries;
2268
2269 /* Mask spurios interrupts */
2270 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK,
Yogesh Ashok Powarf57c1ed2012-03-13 19:22:37 -07002271 HOST_INTR_MASK)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302272 mwifiex_dbg(adapter, ERROR,
2273 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002274 return -1;
2275 }
2276
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302277 mwifiex_dbg(adapter, INFO,
2278 "Setting driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002279 if (mwifiex_write_reg(adapter, reg->drv_rdy,
2280 FIRMWARE_READY_PCIE)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302281 mwifiex_dbg(adapter, ERROR,
2282 "Failed to write driver ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002283 return -1;
2284 }
2285
2286 /* Wait for firmware initialization event */
2287 for (tries = 0; tries < poll_num; tries++) {
Avinash Patildd04e6a2013-02-08 18:18:06 -08002288 if (mwifiex_read_reg(adapter, reg->fw_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07002289 &firmware_stat))
2290 ret = -1;
2291 else
2292 ret = 0;
Stanislaw Gruszka09dd9ec2016-08-25 17:05:17 +02002293
2294 mwifiex_dbg(adapter, INFO, "Try %d if FW is ready <%d,%#x>",
2295 tries, ret, firmware_stat);
2296
Amitkumar Karward930fae2011-10-11 17:41:21 -07002297 if (ret)
2298 continue;
2299 if (firmware_stat == FIRMWARE_READY_PCIE) {
2300 ret = 0;
2301 break;
2302 } else {
Amitkumar Karwara76b20e2013-07-22 19:17:53 -07002303 msleep(100);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002304 ret = -1;
2305 }
2306 }
2307
chunfan chen2fd5c6e2016-01-06 23:40:47 -08002308 return ret;
2309}
2310
2311/* This function checks if WLAN is the winner.
2312 */
2313static int
2314mwifiex_check_winner_status(struct mwifiex_adapter *adapter)
2315{
2316 u32 winner = 0;
2317 int ret = 0;
2318 struct pcie_service_card *card = adapter->card;
2319 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2320
2321 if (mwifiex_read_reg(adapter, reg->fw_status, &winner)) {
2322 ret = -1;
2323 } else if (!winner) {
2324 mwifiex_dbg(adapter, INFO, "PCI-E is the winner\n");
2325 adapter->winner = 1;
2326 } else {
2327 mwifiex_dbg(adapter, ERROR,
Stanislaw Gruszkafd3fbb62016-08-25 17:05:16 +02002328 "PCI-E is not the winner <%#x>", winner);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002329 }
2330
2331 return ret;
2332}
2333
2334/*
2335 * This function reads the interrupt status from card.
2336 */
Xinming Hu99074fc2016-01-11 02:16:40 -08002337static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter,
2338 int msg_id)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002339{
2340 u32 pcie_ireg;
2341 unsigned long flags;
Xinming Hu99074fc2016-01-11 02:16:40 -08002342 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002343
Shengzhen Li5781fc22016-07-01 18:26:52 +05302344 if (card->msi_enable) {
2345 spin_lock_irqsave(&adapter->int_lock, flags);
2346 adapter->int_status = 1;
2347 spin_unlock_irqrestore(&adapter->int_lock, flags);
2348 return;
2349 }
2350
Amitkumar Karward930fae2011-10-11 17:41:21 -07002351 if (!mwifiex_pcie_ok_to_access_hw(adapter))
2352 return;
2353
Xinming Hu99074fc2016-01-11 02:16:40 -08002354 if (card->msix_enable && msg_id >= 0) {
2355 pcie_ireg = BIT(msg_id);
2356 } else {
2357 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2358 &pcie_ireg)) {
2359 mwifiex_dbg(adapter, ERROR, "Read register failed\n");
2360 return;
2361 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002362
Xinming Hu99074fc2016-01-11 02:16:40 -08002363 if ((pcie_ireg == 0xFFFFFFFF) || !pcie_ireg)
2364 return;
2365
Amitkumar Karward930fae2011-10-11 17:41:21 -07002366
2367 mwifiex_pcie_disable_host_int(adapter);
2368
2369 /* Clear the pending interrupts */
2370 if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS,
2371 ~pcie_ireg)) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302372 mwifiex_dbg(adapter, ERROR,
2373 "Write register failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002374 return;
2375 }
Xinming Hu99074fc2016-01-11 02:16:40 -08002376 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002377
Xinming Hu99074fc2016-01-11 02:16:40 -08002378 if (!adapter->pps_uapsd_mode &&
2379 adapter->ps_state == PS_STATE_SLEEP &&
2380 mwifiex_pcie_ok_to_access_hw(adapter)) {
2381 /* Potentially for PCIe we could get other
2382 * interrupts like shared. Don't change power
2383 * state until cookie is set
2384 */
2385 adapter->ps_state = PS_STATE_AWAKE;
2386 adapter->pm_wakeup_fw_try = false;
2387 del_timer(&adapter->wakeup_timer);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002388 }
Shengzhen Lidc896b12016-01-12 05:43:16 -08002389
2390 spin_lock_irqsave(&adapter->int_lock, flags);
2391 adapter->int_status |= pcie_ireg;
2392 spin_unlock_irqrestore(&adapter->int_lock, flags);
2393 mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002394}
2395
2396/*
2397 * Interrupt handler for PCIe root port
2398 *
2399 * This function reads the interrupt status from firmware and assigns
2400 * the main process in workqueue which will handle the interrupt.
2401 */
2402static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
2403{
Xinming Hu99074fc2016-01-11 02:16:40 -08002404 struct mwifiex_msix_context *ctx = context;
2405 struct pci_dev *pdev = ctx->dev;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002406 struct pcie_service_card *card;
2407 struct mwifiex_adapter *adapter;
2408
Jingoo Hanb2a31202013-09-09 14:26:51 +09002409 card = pci_get_drvdata(pdev);
Brian Norrise98fb112016-11-18 19:30:33 +05302410
2411 if (!card->adapter) {
Xinming Hu91442432015-12-31 06:24:14 -08002412 pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
2413 card ? card->adapter : NULL);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002414 goto exit;
2415 }
2416 adapter = card->adapter;
2417
2418 if (adapter->surprise_removed)
2419 goto exit;
2420
Xinming Hu99074fc2016-01-11 02:16:40 -08002421 if (card->msix_enable)
2422 mwifiex_interrupt_status(adapter, ctx->msg_id);
2423 else
2424 mwifiex_interrupt_status(adapter, -1);
2425
Shengzhen Lib2713f62015-03-13 17:37:54 +05302426 mwifiex_queue_main_work(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002427
2428exit:
2429 return IRQ_HANDLED;
2430}
2431
2432/*
2433 * This function checks the current interrupt status.
2434 *
2435 * The following interrupts are checked and handled by this function -
2436 * - Data sent
2437 * - Command sent
2438 * - Command received
2439 * - Packets received
2440 * - Events received
2441 *
2442 * In case of Rx packets received, the packets are uploaded from card to
2443 * host and processed accordingly.
2444 */
Brian Norris87a60212017-07-24 18:13:31 -07002445static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002446{
2447 int ret;
Shengzhen Li5781fc22016-07-01 18:26:52 +05302448 u32 pcie_ireg = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002449 unsigned long flags;
Shengzhen Li5781fc22016-07-01 18:26:52 +05302450 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002451
2452 spin_lock_irqsave(&adapter->int_lock, flags);
Shengzhen Li5781fc22016-07-01 18:26:52 +05302453 if (!card->msi_enable) {
2454 /* Clear out unused interrupts */
2455 pcie_ireg = adapter->int_status;
2456 }
Avinash Patil659c4782013-01-03 21:21:28 -08002457 adapter->int_status = 0;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002458 spin_unlock_irqrestore(&adapter->int_lock, flags);
2459
Shengzhen Li5781fc22016-07-01 18:26:52 +05302460 if (card->msi_enable) {
2461 if (mwifiex_pcie_ok_to_access_hw(adapter)) {
2462 if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
2463 &pcie_ireg)) {
2464 mwifiex_dbg(adapter, ERROR,
2465 "Read register failed\n");
2466 return -1;
2467 }
2468
2469 if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
2470 if (mwifiex_write_reg(adapter,
2471 PCIE_HOST_INT_STATUS,
2472 ~pcie_ireg)) {
2473 mwifiex_dbg(adapter, ERROR,
2474 "Write register failed\n");
2475 return -1;
2476 }
2477 if (!adapter->pps_uapsd_mode &&
2478 adapter->ps_state == PS_STATE_SLEEP) {
2479 adapter->ps_state = PS_STATE_AWAKE;
2480 adapter->pm_wakeup_fw_try = false;
2481 del_timer(&adapter->wakeup_timer);
2482 }
2483 }
2484 }
2485 }
Amitkumar Karward930fae2011-10-11 17:41:21 -07002486
Brian Norris5d5ddb52017-01-13 15:35:37 -08002487 if (pcie_ireg & HOST_INTR_DNLD_DONE) {
Brian Norris5d5ddb52017-01-13 15:35:37 -08002488 mwifiex_dbg(adapter, INTR, "info: TX DNLD Done\n");
2489 ret = mwifiex_pcie_send_data_complete(adapter);
2490 if (ret)
2491 return ret;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002492 }
Brian Norris5d5ddb52017-01-13 15:35:37 -08002493 if (pcie_ireg & HOST_INTR_UPLD_RDY) {
Brian Norris5d5ddb52017-01-13 15:35:37 -08002494 mwifiex_dbg(adapter, INTR, "info: Rx DATA\n");
2495 ret = mwifiex_pcie_process_recv_data(adapter);
2496 if (ret)
2497 return ret;
2498 }
2499 if (pcie_ireg & HOST_INTR_EVENT_RDY) {
Brian Norris5d5ddb52017-01-13 15:35:37 -08002500 mwifiex_dbg(adapter, INTR, "info: Rx EVENT\n");
2501 ret = mwifiex_pcie_process_event_ready(adapter);
2502 if (ret)
2503 return ret;
2504 }
2505 if (pcie_ireg & HOST_INTR_CMD_DONE) {
Brian Norris5d5ddb52017-01-13 15:35:37 -08002506 if (adapter->cmd_sent) {
2507 mwifiex_dbg(adapter, INTR,
2508 "info: CMD sent Interrupt\n");
2509 adapter->cmd_sent = false;
2510 }
2511 /* Handle command response */
2512 ret = mwifiex_pcie_process_cmd_complete(adapter);
2513 if (ret)
2514 return ret;
2515 }
2516
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302517 mwifiex_dbg(adapter, INTR,
2518 "info: cmd_sent=%d data_sent=%d\n",
2519 adapter->cmd_sent, adapter->data_sent);
Brian Norris87a60212017-07-24 18:13:31 -07002520 if (!card->msi_enable && !card->msix_enable &&
2521 adapter->ps_state != PS_STATE_SLEEP)
Avinash Patilb2fda1f2013-03-22 21:49:05 -07002522 mwifiex_pcie_enable_host_int(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002523
2524 return 0;
2525}
2526
2527/*
2528 * This function downloads data from driver to card.
2529 *
2530 * Both commands and data packets are transferred to the card by this
2531 * function.
2532 *
2533 * This function adds the PCIE specific header to the front of the buffer
2534 * before transferring. The header contains the length of the packet and
2535 * the type. The firmware handles the packets based upon this set type.
2536 */
2537static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
2538 struct sk_buff *skb,
2539 struct mwifiex_tx_param *tx_param)
2540{
Dan Carpenterfa161cb2011-11-07 19:31:45 -08002541 if (!skb) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302542 mwifiex_dbg(adapter, ERROR,
2543 "Passed NULL skb to %s\n", __func__);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002544 return -1;
2545 }
2546
2547 if (type == MWIFIEX_TYPE_DATA)
Avinash Patile7f767a2013-01-03 21:21:32 -08002548 return mwifiex_pcie_send_data(adapter, skb, tx_param);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002549 else if (type == MWIFIEX_TYPE_CMD)
2550 return mwifiex_pcie_send_cmd(adapter, skb);
2551
2552 return 0;
2553}
2554
Xinming Hu46469682016-04-05 01:04:40 -07002555/* Function to dump PCIE scratch registers in case of FW crash
2556 */
2557static int
2558mwifiex_pcie_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf)
2559{
2560 char *p = drv_buf;
2561 char buf[256], *ptr;
2562 int i;
2563 u32 value;
2564 struct pcie_service_card *card = adapter->card;
2565 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2566 int pcie_scratch_reg[] = {PCIE_SCRATCH_12_REG,
Xinming Hu127ee1d2017-04-13 06:48:21 +00002567 PCIE_SCRATCH_14_REG,
2568 PCIE_SCRATCH_15_REG};
Xinming Hu46469682016-04-05 01:04:40 -07002569
2570 if (!p)
2571 return 0;
2572
2573 mwifiex_dbg(adapter, MSG, "PCIE register dump start\n");
2574
2575 if (mwifiex_read_reg(adapter, reg->fw_status, &value)) {
2576 mwifiex_dbg(adapter, ERROR, "failed to read firmware status");
2577 return 0;
2578 }
2579
2580 ptr = buf;
2581 mwifiex_dbg(adapter, MSG, "pcie scratch register:");
2582 for (i = 0; i < ARRAY_SIZE(pcie_scratch_reg); i++) {
2583 mwifiex_read_reg(adapter, pcie_scratch_reg[i], &value);
2584 ptr += sprintf(ptr, "reg:0x%x, value=0x%x\n",
2585 pcie_scratch_reg[i], value);
2586 }
2587
2588 mwifiex_dbg(adapter, MSG, "%s\n", buf);
2589 p += sprintf(p, "%s\n", buf);
2590
2591 mwifiex_dbg(adapter, MSG, "PCIE register dump end\n");
2592
2593 return p - drv_buf;
2594}
2595
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002596/* This function read/write firmware */
2597static enum rdwr_status
2598mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag)
2599{
2600 int ret, tries;
2601 u8 ctrl_data;
Xinming Hu01724042016-02-02 22:05:04 -08002602 u32 fw_status;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002603 struct pcie_service_card *card = adapter->card;
2604 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2605
Xinming Hu01724042016-02-02 22:05:04 -08002606 if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status))
2607 return RDWR_STATUS_FAILURE;
2608
Xinming Hu50632092016-02-02 22:05:06 -08002609 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
2610 reg->fw_dump_host_ready);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002611 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302612 mwifiex_dbg(adapter, ERROR,
2613 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002614 return RDWR_STATUS_FAILURE;
2615 }
2616
2617 for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2618 mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data);
2619 if (ctrl_data == FW_DUMP_DONE)
2620 return RDWR_STATUS_SUCCESS;
2621 if (doneflag && ctrl_data == doneflag)
2622 return RDWR_STATUS_DONE;
Xinming Hu50632092016-02-02 22:05:06 -08002623 if (ctrl_data != reg->fw_dump_host_ready) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302624 mwifiex_dbg(adapter, WARN,
2625 "The ctrl reg was changed, re-try again!\n");
Amitkumar Karwar24716872014-09-18 08:04:01 -04002626 ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl,
Xinming Hu50632092016-02-02 22:05:06 -08002627 reg->fw_dump_host_ready);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002628 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302629 mwifiex_dbg(adapter, ERROR,
2630 "PCIE write err\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002631 return RDWR_STATUS_FAILURE;
2632 }
2633 }
2634 usleep_range(100, 200);
2635 }
2636
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302637 mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002638 return RDWR_STATUS_FAILURE;
2639}
2640
2641/* This function dump firmware memory to file */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002642static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002643{
2644 struct pcie_service_card *card = adapter->card;
2645 const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
2646 unsigned int reg, reg_start, reg_end;
Xinming Hu11e70822016-02-02 22:05:09 -08002647 u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num;
Xinming Hu56486022016-02-02 22:05:07 -08002648 u8 idx, i, read_reg, doneflag = 0;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002649 enum rdwr_status stat;
2650 u32 memory_size;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002651 int ret;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002652
Avinash Patilb4e8aeb2015-02-11 23:12:26 +05302653 if (!card->pcie.can_dump_fw)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002654 return;
2655
Xinming Hu50632092016-02-02 22:05:06 -08002656 for (idx = 0; idx < adapter->num_mem_types; idx++) {
2657 struct memory_type_mapping *entry =
2658 &adapter->mem_type_mapping_tbl[idx];
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002659
2660 if (entry->mem_ptr) {
2661 vfree(entry->mem_ptr);
2662 entry->mem_ptr = NULL;
2663 }
2664 entry->mem_size = 0;
2665 }
2666
Amitkumar Karwar03f0f7c2016-02-02 22:05:08 -08002667 mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002668
2669 /* Read the number of the memories which will dump */
2670 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2671 if (stat == RDWR_STATUS_FAILURE)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002672 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002673
2674 reg = creg->fw_dump_start;
Xinming Hu11e70822016-02-02 22:05:09 -08002675 mwifiex_read_reg_byte(adapter, reg, &fw_dump_num);
2676
2677 /* W8997 chipset firmware dump will be restore in single region*/
2678 if (fw_dump_num == 0)
2679 dump_num = 1;
2680 else
2681 dump_num = fw_dump_num;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002682
2683 /* Read the length of every memory which will dump */
2684 for (idx = 0; idx < dump_num; idx++) {
Xinming Hu50632092016-02-02 22:05:06 -08002685 struct memory_type_mapping *entry =
2686 &adapter->mem_type_mapping_tbl[idx];
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002687 memory_size = 0;
Xinming Hu11e70822016-02-02 22:05:09 -08002688 if (fw_dump_num != 0) {
2689 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2690 if (stat == RDWR_STATUS_FAILURE)
2691 return;
2692
2693 reg = creg->fw_dump_start;
2694 for (i = 0; i < 4; i++) {
2695 mwifiex_read_reg_byte(adapter, reg, &read_reg);
2696 memory_size |= (read_reg << (i * 8));
Dan Carpenterccf5fa42016-02-09 14:15:36 +03002697 reg++;
Xinming Hu11e70822016-02-02 22:05:09 -08002698 }
2699 } else {
2700 memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002701 }
2702
2703 if (memory_size == 0) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302704 mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n");
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002705 ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl,
Xinming Hu50632092016-02-02 22:05:06 -08002706 creg->fw_dump_read_done);
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002707 if (ret) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302708 mwifiex_dbg(adapter, ERROR, "PCIE write err\n");
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002709 return;
Amitkumar Karwar7e174832014-09-18 07:18:50 -04002710 }
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002711 break;
2712 }
2713
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302714 mwifiex_dbg(adapter, DUMP,
2715 "%s_SIZE=0x%x\n", entry->mem_name, memory_size);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002716 entry->mem_ptr = vmalloc(memory_size + 1);
2717 entry->mem_size = memory_size;
2718 if (!entry->mem_ptr) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302719 mwifiex_dbg(adapter, ERROR,
2720 "Vmalloc %s failed\n", entry->mem_name);
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002721 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002722 }
2723 dbg_ptr = entry->mem_ptr;
2724 end_ptr = dbg_ptr + memory_size;
2725
2726 doneflag = entry->done_flag;
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302727 mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n",
2728 entry->mem_name);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002729
2730 do {
2731 stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
2732 if (RDWR_STATUS_FAILURE == stat)
Amitkumar Karwar57670ee2015-05-26 06:34:32 -07002733 return;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002734
2735 reg_start = creg->fw_dump_start;
2736 reg_end = creg->fw_dump_end;
2737 for (reg = reg_start; reg <= reg_end; reg++) {
2738 mwifiex_read_reg_byte(adapter, reg, dbg_ptr);
Amitkumar Karwar24716872014-09-18 08:04:01 -04002739 if (dbg_ptr < end_ptr) {
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002740 dbg_ptr++;
Xinming Hu56486022016-02-02 22:05:07 -08002741 continue;
Amitkumar Karwar24716872014-09-18 08:04:01 -04002742 }
Xinming Hu56486022016-02-02 22:05:07 -08002743 mwifiex_dbg(adapter, ERROR,
2744 "pre-allocated buf not enough\n");
2745 tmp_ptr =
2746 vzalloc(memory_size + MWIFIEX_SIZE_4K);
2747 if (!tmp_ptr)
2748 return;
2749 memcpy(tmp_ptr, entry->mem_ptr, memory_size);
2750 vfree(entry->mem_ptr);
2751 entry->mem_ptr = tmp_ptr;
2752 tmp_ptr = NULL;
2753 dbg_ptr = entry->mem_ptr + memory_size;
2754 memory_size += MWIFIEX_SIZE_4K;
2755 end_ptr = entry->mem_ptr + memory_size;
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002756 }
2757
2758 if (stat != RDWR_STATUS_DONE)
2759 continue;
2760
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302761 mwifiex_dbg(adapter, DUMP,
2762 "%s done: size=0x%tx\n",
2763 entry->mem_name, dbg_ptr - entry->mem_ptr);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002764 break;
2765 } while (true);
2766 }
Amitkumar Karwar03f0f7c2016-02-02 22:05:08 -08002767 mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n");
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002768}
2769
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002770static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter)
2771{
Xinming Hud27121f2016-11-16 18:39:07 +05302772 int drv_info_size;
2773 void *drv_info;
2774
2775 drv_info_size = mwifiex_drv_info_dump(adapter, &drv_info);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002776 mwifiex_pcie_fw_dump(adapter);
Xinming Hud27121f2016-11-16 18:39:07 +05302777 mwifiex_upload_device_dump(adapter, drv_info, drv_info_size);
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002778}
2779
Brian Norris6d7d5792017-05-01 12:37:00 -07002780static void mwifiex_pcie_card_reset_work(struct mwifiex_adapter *adapter)
2781{
2782 struct pcie_service_card *card = adapter->card;
2783
2784 pci_reset_function(card->dev);
2785}
2786
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002787static void mwifiex_pcie_work(struct work_struct *work)
2788{
Ganapathi Bhat3860e5e2016-11-16 18:39:09 +05302789 struct pcie_service_card *card =
2790 container_of(work, struct pcie_service_card, work);
2791
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002792 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
Ganapathi Bhat3860e5e2016-11-16 18:39:09 +05302793 &card->work_flags))
2794 mwifiex_pcie_device_dump_work(card->adapter);
Brian Norris6d7d5792017-05-01 12:37:00 -07002795 if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET,
2796 &card->work_flags))
2797 mwifiex_pcie_card_reset_work(card->adapter);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002798}
2799
2800/* This function dumps FW information */
Amitkumar Karwarfc697152015-05-26 06:34:31 -07002801static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter)
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002802{
Ganapathi Bhat3860e5e2016-11-16 18:39:09 +05302803 struct pcie_service_card *card = adapter->card;
2804
Brian Norris21f569a2017-05-01 12:36:59 -07002805 if (!test_and_set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP,
2806 &card->work_flags))
2807 schedule_work(&card->work);
Amitkumar Karwar92c25382014-06-19 21:38:52 -07002808}
2809
Brian Norris6d7d5792017-05-01 12:37:00 -07002810static void mwifiex_pcie_card_reset(struct mwifiex_adapter *adapter)
2811{
2812 struct pcie_service_card *card = adapter->card;
2813
2814 if (!test_and_set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags))
2815 schedule_work(&card->work);
2816}
2817
Brian Norrisd41bf5c2017-05-18 09:34:47 -07002818static int mwifiex_pcie_alloc_buffers(struct mwifiex_adapter *adapter)
2819{
2820 struct pcie_service_card *card = adapter->card;
2821 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2822 int ret;
2823
2824 card->cmdrsp_buf = NULL;
2825 ret = mwifiex_pcie_create_txbd_ring(adapter);
2826 if (ret) {
2827 mwifiex_dbg(adapter, ERROR, "Failed to create txbd ring\n");
2828 goto err_cre_txbd;
2829 }
2830
2831 ret = mwifiex_pcie_create_rxbd_ring(adapter);
2832 if (ret) {
2833 mwifiex_dbg(adapter, ERROR, "Failed to create rxbd ring\n");
2834 goto err_cre_rxbd;
2835 }
2836
2837 ret = mwifiex_pcie_create_evtbd_ring(adapter);
2838 if (ret) {
2839 mwifiex_dbg(adapter, ERROR, "Failed to create evtbd ring\n");
2840 goto err_cre_evtbd;
2841 }
2842
2843 ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
2844 if (ret) {
2845 mwifiex_dbg(adapter, ERROR, "Failed to allocate cmdbuf buffer\n");
2846 goto err_alloc_cmdbuf;
2847 }
2848
2849 if (reg->sleep_cookie) {
2850 ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
2851 if (ret) {
2852 mwifiex_dbg(adapter, ERROR, "Failed to allocate sleep_cookie buffer\n");
2853 goto err_alloc_cookie;
2854 }
2855 } else {
2856 card->sleep_cookie_vbase = NULL;
2857 }
2858
2859 return 0;
2860
2861err_alloc_cookie:
2862 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2863err_alloc_cmdbuf:
2864 mwifiex_pcie_delete_evtbd_ring(adapter);
2865err_cre_evtbd:
2866 mwifiex_pcie_delete_rxbd_ring(adapter);
2867err_cre_rxbd:
2868 mwifiex_pcie_delete_txbd_ring(adapter);
2869err_cre_txbd:
2870 return ret;
2871}
2872
Brian Norris4e841d32017-03-10 17:39:21 -08002873static void mwifiex_pcie_free_buffers(struct mwifiex_adapter *adapter)
2874{
2875 struct pcie_service_card *card = adapter->card;
2876 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
2877
2878 if (reg->sleep_cookie)
2879 mwifiex_pcie_delete_sleep_cookie_buf(adapter);
2880
2881 mwifiex_pcie_delete_cmdrsp_buf(adapter);
2882 mwifiex_pcie_delete_evtbd_ring(adapter);
2883 mwifiex_pcie_delete_rxbd_ring(adapter);
2884 mwifiex_pcie_delete_txbd_ring(adapter);
Brian Norris4e841d32017-03-10 17:39:21 -08002885}
2886
Amitkumar Karward930fae2011-10-11 17:41:21 -07002887/*
2888 * This function initializes the PCI-E host memory space, WCB rings, etc.
Amitkumar Karward930fae2011-10-11 17:41:21 -07002889 */
Amitkumar Karwarc0e6aa42016-12-01 18:38:20 +05302890static int mwifiex_init_pcie(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002891{
2892 struct pcie_service_card *card = adapter->card;
2893 int ret;
2894 struct pci_dev *pdev = card->dev;
2895
2896 pci_set_drvdata(pdev, card);
2897
2898 ret = pci_enable_device(pdev);
2899 if (ret)
2900 goto err_enable_dev;
2901
2902 pci_set_master(pdev);
2903
Xinming Hufdb1e282015-12-31 06:24:12 -08002904 pr_notice("try set_consistent_dma_mask(32)\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002905 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
2906 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002907 pr_err("set_dma_mask(32) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002908 goto err_set_dma_mask;
2909 }
2910
2911 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
2912 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002913 pr_err("set_consistent_dma_mask(64) failed\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002914 goto err_set_dma_mask;
2915 }
2916
2917 ret = pci_request_region(pdev, 0, DRV_NAME);
2918 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002919 pr_err("req_reg(0) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002920 goto err_req_region0;
2921 }
2922 card->pci_mmap = pci_iomap(pdev, 0, 0);
2923 if (!card->pci_mmap) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002924 pr_err("iomap(0) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002925 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002926 goto err_iomap0;
2927 }
2928 ret = pci_request_region(pdev, 2, DRV_NAME);
2929 if (ret) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002930 pr_err("req_reg(2) error\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002931 goto err_req_region2;
2932 }
2933 card->pci_mmap1 = pci_iomap(pdev, 2, 0);
2934 if (!card->pci_mmap1) {
Xinming Hufdb1e282015-12-31 06:24:12 -08002935 pr_err("iomap(2) error\n");
Alexey Khoroshilov32207122013-01-26 00:56:03 +04002936 ret = -EIO;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002937 goto err_iomap2;
2938 }
2939
Xinming Hufdb1e282015-12-31 06:24:12 -08002940 pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
2941 card->pci_mmap, card->pci_mmap1);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002942
Brian Norrisd41bf5c2017-05-18 09:34:47 -07002943 ret = mwifiex_pcie_alloc_buffers(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002944 if (ret)
Brian Norrisd41bf5c2017-05-18 09:34:47 -07002945 goto err_alloc_buffers;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002946
Brian Norrisd41bf5c2017-05-18 09:34:47 -07002947 return 0;
2948
2949err_alloc_buffers:
Amitkumar Karward930fae2011-10-11 17:41:21 -07002950 pci_iounmap(pdev, card->pci_mmap1);
2951err_iomap2:
2952 pci_release_region(pdev, 2);
2953err_req_region2:
2954 pci_iounmap(pdev, card->pci_mmap);
2955err_iomap0:
2956 pci_release_region(pdev, 0);
2957err_req_region0:
2958err_set_dma_mask:
2959 pci_disable_device(pdev);
2960err_enable_dev:
Amitkumar Karward930fae2011-10-11 17:41:21 -07002961 return ret;
2962}
2963
2964/*
2965 * This function cleans up the allocated card buffers.
Amitkumar Karward930fae2011-10-11 17:41:21 -07002966 */
Amitkumar Karwarc0e6aa42016-12-01 18:38:20 +05302967static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
Amitkumar Karward930fae2011-10-11 17:41:21 -07002968{
2969 struct pcie_service_card *card = adapter->card;
2970 struct pci_dev *pdev = card->dev;
Avinash Patildd04e6a2013-02-08 18:18:06 -08002971 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Xinming Hu045f0c12016-11-30 20:22:17 +05302972 int ret;
2973 u32 fw_status;
Amitkumar Karward930fae2011-10-11 17:41:21 -07002974
Brian Norris5caa7f32017-03-16 14:36:07 -07002975 cancel_work_sync(&card->work);
2976
Xinming Hu045f0c12016-11-30 20:22:17 +05302977 ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
2978 if (fw_status == FIRMWARE_READY_PCIE) {
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302979 mwifiex_dbg(adapter, INFO,
2980 "Clearing driver ready signature\n");
Avinash Patildd04e6a2013-02-08 18:18:06 -08002981 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
Zhaoyang Liuacebe8c2015-05-12 00:48:20 +05302982 mwifiex_dbg(adapter, ERROR,
2983 "Failed to write driver not-ready signature\n");
Amitkumar Karward930fae2011-10-11 17:41:21 -07002984 }
2985
Brian Norris43a0c9a2017-07-24 18:13:34 -07002986 pci_disable_device(pdev);
Brian Norris2f471502017-07-24 18:13:33 -07002987
Brian Norris43a0c9a2017-07-24 18:13:34 -07002988 pci_iounmap(pdev, card->pci_mmap);
2989 pci_iounmap(pdev, card->pci_mmap1);
2990 pci_release_region(pdev, 2);
2991 pci_release_region(pdev, 0);
Brian Norris2f471502017-07-24 18:13:33 -07002992
2993 mwifiex_pcie_free_buffers(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07002994}
2995
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002996static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
2997{
Xinming Hu99074fc2016-01-11 02:16:40 -08002998 int ret, i, j;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08002999 struct pcie_service_card *card = adapter->card;
3000 struct pci_dev *pdev = card->dev;
3001
Xinming Hu99074fc2016-01-11 02:16:40 -08003002 if (card->pcie.reg->msix_support) {
3003 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
3004 card->msix_entries[i].entry = i;
3005 ret = pci_enable_msix_exact(pdev, card->msix_entries,
3006 MWIFIEX_NUM_MSIX_VECTORS);
3007 if (!ret) {
3008 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) {
3009 card->msix_ctx[i].dev = pdev;
3010 card->msix_ctx[i].msg_id = i;
3011
3012 ret = request_irq(card->msix_entries[i].vector,
3013 mwifiex_pcie_interrupt, 0,
3014 "MWIFIEX_PCIE_MSIX",
3015 &card->msix_ctx[i]);
3016 if (ret)
3017 break;
3018 }
3019
3020 if (ret) {
3021 mwifiex_dbg(adapter, INFO, "request_irq fail: %d\n",
3022 ret);
3023 for (j = 0; j < i; j++)
3024 free_irq(card->msix_entries[j].vector,
3025 &card->msix_ctx[i]);
3026 pci_disable_msix(pdev);
3027 } else {
3028 mwifiex_dbg(adapter, MSG, "MSIx enabled!");
3029 card->msix_enable = 1;
3030 return 0;
3031 }
3032 }
3033 }
3034
Avinash Patil7be0f5b2015-12-16 04:21:45 -08003035 if (pci_enable_msi(pdev) != 0)
3036 pci_disable_msi(pdev);
3037 else
3038 card->msi_enable = 1;
3039
3040 mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable);
3041
Xinming Hu99074fc2016-01-11 02:16:40 -08003042 card->share_irq_ctx.dev = pdev;
3043 card->share_irq_ctx.msg_id = -1;
Avinash Patil7be0f5b2015-12-16 04:21:45 -08003044 ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
Xinming Hu99074fc2016-01-11 02:16:40 -08003045 "MRVL_PCIE", &card->share_irq_ctx);
Avinash Patil7be0f5b2015-12-16 04:21:45 -08003046 if (ret) {
3047 pr_err("request_irq failed: ret=%d\n", ret);
Avinash Patil7be0f5b2015-12-16 04:21:45 -08003048 return -1;
3049 }
3050
3051 return 0;
3052}
3053
Amitkumar Karward930fae2011-10-11 17:41:21 -07003054/*
Julia Lawall47ce90f2016-05-17 16:38:46 +02003055 * This function gets the firmware name for downloading by revision id
Shengzhen Lia362e162016-04-05 01:04:36 -07003056 *
3057 * Read revision id register to get revision id
3058 */
3059static void mwifiex_pcie_get_fw_name(struct mwifiex_adapter *adapter)
3060{
3061 int revision_id = 0;
Amitkumar Karwar75696fe2016-07-29 16:08:51 +05303062 int version, magic;
Shengzhen Lia362e162016-04-05 01:04:36 -07003063 struct pcie_service_card *card = adapter->card;
3064
3065 switch (card->dev->device) {
3066 case PCIE_DEVICE_ID_MARVELL_88W8766P:
3067 strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME);
3068 break;
3069 case PCIE_DEVICE_ID_MARVELL_88W8897:
3070 mwifiex_write_reg(adapter, 0x0c58, 0x80c00000);
3071 mwifiex_read_reg(adapter, 0x0c58, &revision_id);
3072 revision_id &= 0xff00;
3073 switch (revision_id) {
3074 case PCIE8897_A0:
3075 strcpy(adapter->fw_name, PCIE8897_A0_FW_NAME);
3076 break;
3077 case PCIE8897_B0:
3078 strcpy(adapter->fw_name, PCIE8897_B0_FW_NAME);
3079 break;
3080 default:
Shengzhen Lib9db3972016-04-11 07:52:39 -07003081 strcpy(adapter->fw_name, PCIE8897_DEFAULT_FW_NAME);
3082
Shengzhen Lia362e162016-04-05 01:04:36 -07003083 break;
3084 }
Amitkumar Karwarc865a702016-04-11 07:52:37 -07003085 break;
Shengzhen Lia362e162016-04-05 01:04:36 -07003086 case PCIE_DEVICE_ID_MARVELL_88W8997:
Amitkumar Karwar75696fe2016-07-29 16:08:51 +05303087 mwifiex_read_reg(adapter, 0x8, &revision_id);
Shengzhen Lie87650b2016-04-11 07:52:38 -07003088 mwifiex_read_reg(adapter, 0x0cd0, &version);
Amitkumar Karwar75696fe2016-07-29 16:08:51 +05303089 mwifiex_read_reg(adapter, 0x0cd4, &magic);
3090 revision_id &= 0xff;
Shengzhen Lie87650b2016-04-11 07:52:38 -07003091 version &= 0x7;
Amitkumar Karwar75696fe2016-07-29 16:08:51 +05303092 magic &= 0xff;
3093 if (revision_id == PCIE8997_A1 &&
3094 magic == CHIP_MAGIC_VALUE &&
3095 version == CHIP_VER_PCIEUART)
3096 strcpy(adapter->fw_name, PCIEUART8997_FW_NAME_V4);
3097 else
3098 strcpy(adapter->fw_name, PCIEUSB8997_FW_NAME_V4);
3099 break;
Shengzhen Lia362e162016-04-05 01:04:36 -07003100 default:
3101 break;
3102 }
3103}
3104
3105/*
Amitkumar Karward930fae2011-10-11 17:41:21 -07003106 * This function registers the PCIE device.
3107 *
3108 * PCIE IRQ is claimed, block size is set and driver data is initialized.
3109 */
3110static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
3111{
Amitkumar Karward930fae2011-10-11 17:41:21 -07003112 struct pcie_service_card *card = adapter->card;
Amitkumar Karward930fae2011-10-11 17:41:21 -07003113
3114 /* save adapter pointer in card */
3115 card->adapter = adapter;
3116
Avinash Patil7be0f5b2015-12-16 04:21:45 -08003117 if (mwifiex_pcie_request_irq(adapter))
Amitkumar Karward930fae2011-10-11 17:41:21 -07003118 return -1;
Amitkumar Karward930fae2011-10-11 17:41:21 -07003119
Amitkumar Karwar828cf222014-02-27 19:35:13 -08003120 adapter->tx_buf_size = card->pcie.tx_buf_size;
Xinming Hu50632092016-02-02 22:05:06 -08003121 adapter->mem_type_mapping_tbl = card->pcie.mem_type_mapping_tbl;
3122 adapter->num_mem_types = card->pcie.num_mem_types;
Avinash Patil1fe192d2015-01-23 17:09:19 +05303123 adapter->ext_scan = card->pcie.can_ext_scan;
Shengzhen Lia362e162016-04-05 01:04:36 -07003124 mwifiex_pcie_get_fw_name(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07003125
3126 return 0;
3127}
3128
3129/*
3130 * This function unregisters the PCIE device.
3131 *
3132 * The PCIE IRQ is released, the function is disabled and driver
3133 * data is set to null.
3134 */
3135static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
3136{
3137 struct pcie_service_card *card = adapter->card;
Brian Norris97489c22016-11-18 19:30:34 +05303138 struct pci_dev *pdev = card->dev;
Xinming Hu99074fc2016-01-11 02:16:40 -08003139 int i;
Amitkumar Karward930fae2011-10-11 17:41:21 -07003140
Brian Norris97489c22016-11-18 19:30:34 +05303141 if (card->msix_enable) {
3142 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
3143 synchronize_irq(card->msix_entries[i].vector);
Xinming Hu99074fc2016-01-11 02:16:40 -08003144
Brian Norris97489c22016-11-18 19:30:34 +05303145 for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++)
3146 free_irq(card->msix_entries[i].vector,
3147 &card->msix_ctx[i]);
Xinming Hu99074fc2016-01-11 02:16:40 -08003148
Brian Norris97489c22016-11-18 19:30:34 +05303149 card->msix_enable = 0;
3150 pci_disable_msix(pdev);
3151 } else {
3152 mwifiex_dbg(adapter, INFO,
3153 "%s(): calling free_irq()\n", __func__);
3154 free_irq(card->dev->irq, &card->share_irq_ctx);
Xinming Hu99074fc2016-01-11 02:16:40 -08003155
Brian Norris97489c22016-11-18 19:30:34 +05303156 if (card->msi_enable)
3157 pci_disable_msi(pdev);
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303158 }
Brian Norris97489c22016-11-18 19:30:34 +05303159 card->adapter = NULL;
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303160}
Avinash Patilfc331462013-01-03 21:21:30 -08003161
Brian Norrisd41bf5c2017-05-18 09:34:47 -07003162/*
3163 * This function initializes the PCI-E host memory space, WCB rings, etc.,
3164 * similar to mwifiex_init_pcie(), but without resetting PCI-E state.
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303165 */
3166static void mwifiex_pcie_up_dev(struct mwifiex_adapter *adapter)
3167{
3168 struct pcie_service_card *card = adapter->card;
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303169 struct pci_dev *pdev = card->dev;
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303170
Xinming Huec750f12016-12-14 19:40:48 +05303171 /* tx_buf_size might be changed to 3584 by firmware during
3172 * data transfer, we should reset it to default size.
3173 */
3174 adapter->tx_buf_size = card->pcie.tx_buf_size;
3175
Brian Norris2f471502017-07-24 18:13:33 -07003176 mwifiex_pcie_alloc_buffers(adapter);
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303177
Brian Norris2f471502017-07-24 18:13:33 -07003178 pci_set_master(pdev);
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303179}
3180
Brian Norris4e841d32017-03-10 17:39:21 -08003181/* This function cleans up the PCI-E host memory space. */
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303182static void mwifiex_pcie_down_dev(struct mwifiex_adapter *adapter)
3183{
3184 struct pcie_service_card *card = adapter->card;
3185 const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
Brian Norris2f471502017-07-24 18:13:33 -07003186 struct pci_dev *pdev = card->dev;
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303187
3188 if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
3189 mwifiex_dbg(adapter, ERROR, "Failed to write driver not-ready signature\n");
3190
Brian Norris2f471502017-07-24 18:13:33 -07003191 pci_clear_master(pdev);
3192
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303193 adapter->seq_num = 0;
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303194
Brian Norris4e841d32017-03-10 17:39:21 -08003195 mwifiex_pcie_free_buffers(adapter);
Amitkumar Karward930fae2011-10-11 17:41:21 -07003196}
3197
3198static struct mwifiex_if_ops pcie_ops = {
Amitkumar Karwarc0e6aa42016-12-01 18:38:20 +05303199 .init_if = mwifiex_init_pcie,
3200 .cleanup_if = mwifiex_cleanup_pcie,
Amitkumar Karward930fae2011-10-11 17:41:21 -07003201 .check_fw_status = mwifiex_check_fw_status,
chunfan chen2fd5c6e2016-01-06 23:40:47 -08003202 .check_winner_status = mwifiex_check_winner_status,
Amitkumar Karward930fae2011-10-11 17:41:21 -07003203 .prog_fw = mwifiex_prog_fw_w_helper,
3204 .register_dev = mwifiex_register_dev,
3205 .unregister_dev = mwifiex_unregister_dev,
3206 .enable_int = mwifiex_pcie_enable_host_int,
Brian Norrisd41376c2016-06-30 15:21:02 -07003207 .disable_int = mwifiex_pcie_disable_host_int_noerr,
Amitkumar Karward930fae2011-10-11 17:41:21 -07003208 .process_int_status = mwifiex_process_int_status,
3209 .host_to_card = mwifiex_pcie_host_to_card,
3210 .wakeup = mwifiex_pm_wakeup_card,
3211 .wakeup_complete = mwifiex_pm_wakeup_card_complete,
3212
3213 /* PCIE specific */
3214 .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete,
3215 .event_complete = mwifiex_pcie_event_complete,
3216 .update_mp_end_port = NULL,
3217 .cleanup_mpa_buf = NULL,
Avinash Patilc6d1d872013-01-03 21:21:29 -08003218 .init_fw_port = mwifiex_pcie_init_fw_port,
Avinash Patilfbd7e7a2013-01-03 21:21:31 -08003219 .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
Brian Norris6d7d5792017-05-01 12:37:00 -07003220 .card_reset = mwifiex_pcie_card_reset,
Xinming Hu46469682016-04-05 01:04:40 -07003221 .reg_dump = mwifiex_pcie_reg_dump,
Amitkumar Karwarfc697152015-05-26 06:34:31 -07003222 .device_dump = mwifiex_pcie_device_dump,
Amitkumar Karwar4c5dae52016-07-26 19:31:44 +05303223 .down_dev = mwifiex_pcie_down_dev,
3224 .up_dev = mwifiex_pcie_up_dev,
Amitkumar Karward930fae2011-10-11 17:41:21 -07003225};
3226
Amitkumar Karwarc0e6aa42016-12-01 18:38:20 +05303227module_pci_driver(mwifiex_pcie);
Amitkumar Karward930fae2011-10-11 17:41:21 -07003228
3229MODULE_AUTHOR("Marvell International Ltd.");
3230MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
3231MODULE_VERSION(PCIE_VERSION);
3232MODULE_LICENSE("GPL v2");