pcie.c (f0718d792b8a6d4b5ddc929e418ac57cc4897375) pcie.c (b7da53cd6cd13a782bb08e59b4a3358ec800f724)
1// SPDX-License-Identifier: GPL-2.0+
2/* Copyright (c) 2018 Quantenna Communications, Inc. All rights reserved. */
3
1// SPDX-License-Identifier: GPL-2.0+
2/* Copyright (c) 2018 Quantenna Communications, Inc. All rights reserved. */
3
4#include <linux/module.h>
4#include <linux/printk.h>
5#include <linux/pci.h>
6#include <linux/spinlock.h>
7#include <linux/mutex.h>
8#include <linux/netdevice.h>
9#include <linux/seq_file.h>
10#include <linux/workqueue.h>
11#include <linux/completion.h>
12
13#include "pcie_priv.h"
14#include "bus.h"
15#include "shm_ipc.h"
16#include "core.h"
17#include "debug.h"
5#include <linux/printk.h>
6#include <linux/pci.h>
7#include <linux/spinlock.h>
8#include <linux/mutex.h>
9#include <linux/netdevice.h>
10#include <linux/seq_file.h>
11#include <linux/workqueue.h>
12#include <linux/completion.h>
13
14#include "pcie_priv.h"
15#include "bus.h"
16#include "shm_ipc.h"
17#include "core.h"
18#include "debug.h"
19#include "util.h"
20#include "qtn_hw_ids.h"
18
21
19#undef pr_fmt
20#define pr_fmt(fmt) "qtnf_pcie: %s: " fmt, __func__
21
22#define QTN_SYSCTL_BAR 0
23#define QTN_SHMEM_BAR 2
24#define QTN_DMA_BAR 3
25
22#define QTN_SYSCTL_BAR 0
23#define QTN_SHMEM_BAR 2
24#define QTN_DMA_BAR 3
25
26#define QTN_PCIE_MAX_FW_BUFSZ (1 * 1024 * 1024)
27
28static bool use_msi = true;
29module_param(use_msi, bool, 0644);
30MODULE_PARM_DESC(use_msi, "set 0 to use legacy interrupt");
31
32static unsigned int tx_bd_size_param;
33module_param(tx_bd_size_param, uint, 0644);
34MODULE_PARM_DESC(tx_bd_size_param, "Tx descriptors queue size");
35
36static unsigned int rx_bd_size_param = 256;
37module_param(rx_bd_size_param, uint, 0644);
38MODULE_PARM_DESC(rx_bd_size_param, "Rx descriptors queue size");
39
40static u8 flashboot = 1;
41module_param(flashboot, byte, 0644);
42MODULE_PARM_DESC(flashboot, "set to 0 to use FW binary file on FS");
43
44static unsigned int fw_blksize_param = QTN_PCIE_MAX_FW_BUFSZ;
45module_param(fw_blksize_param, uint, 0644);
46MODULE_PARM_DESC(fw_blksize_param, "firmware loading block size in bytes");
47
48#define DRV_NAME "qtnfmac_pcie"
49
26int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
27{
28 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
29 int ret;
30
31 ret = qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len);
32
33 if (ret == -ETIMEDOUT) {

--- 19 unchanged lines hidden (view full) ---

53 priv->tx_skb = vaddr;
54
55 vaddr += priv->tx_bd_num;
56 priv->rx_skb = vaddr;
57
58 return 0;
59}
60
50int qtnf_pcie_control_tx(struct qtnf_bus *bus, struct sk_buff *skb)
51{
52 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
53 int ret;
54
55 ret = qtnf_shm_ipc_send(&priv->shm_ipc_ep_in, skb->data, skb->len);
56
57 if (ret == -ETIMEDOUT) {

--- 19 unchanged lines hidden (view full) ---

77 priv->tx_skb = vaddr;
78
79 vaddr += priv->tx_bd_num;
80 priv->rx_skb = vaddr;
81
82 return 0;
83}
84
61void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus)
85static void qtnf_pcie_bringup_fw_async(struct qtnf_bus *bus)
62{
63 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
64 struct pci_dev *pdev = priv->pdev;
65
66 get_device(&pdev->dev);
67 schedule_work(&bus->fw_work);
68}
69
70static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
71{
72 struct qtnf_bus *bus = dev_get_drvdata(s->private);
73 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
74
86{
87 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
88 struct pci_dev *pdev = priv->pdev;
89
90 get_device(&pdev->dev);
91 schedule_work(&bus->fw_work);
92}
93
94static int qtnf_dbg_mps_show(struct seq_file *s, void *data)
95{
96 struct qtnf_bus *bus = dev_get_drvdata(s->private);
97 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
98
75 seq_printf(s, "%d\n", priv->mps);
99 seq_printf(s, "%d\n", pcie_get_mps(priv->pdev));
76
77 return 0;
78}
79
80static int qtnf_dbg_msi_show(struct seq_file *s, void *data)
81{
82 struct qtnf_bus *bus = dev_get_drvdata(s->private);
83 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);

--- 15 unchanged lines hidden (view full) ---

99 seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n",
100 priv->shm_ipc_ep_out.tx_timeout_count);
101 seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n",
102 priv->shm_ipc_ep_out.rx_packet_count);
103
104 return 0;
105}
106
100
101 return 0;
102}
103
104static int qtnf_dbg_msi_show(struct seq_file *s, void *data)
105{
106 struct qtnf_bus *bus = dev_get_drvdata(s->private);
107 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);

--- 15 unchanged lines hidden (view full) ---

123 seq_printf(s, "shm_ipc_ep_out.tx_packet_count(%zu)\n",
124 priv->shm_ipc_ep_out.tx_timeout_count);
125 seq_printf(s, "shm_ipc_ep_out.rx_packet_count(%zu)\n",
126 priv->shm_ipc_ep_out.rx_packet_count);
127
128 return 0;
129}
130
107void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success,
108 const char *drv_name)
131void qtnf_pcie_fw_boot_done(struct qtnf_bus *bus, bool boot_success)
109{
110 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
111 struct pci_dev *pdev = priv->pdev;
112 int ret;
113
114 if (boot_success) {
115 bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
116
117 ret = qtnf_core_attach(bus);
118 if (ret) {
119 pr_err("failed to attach core\n");
120 boot_success = false;
121 }
122 }
123
124 if (boot_success) {
132{
133 struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
134 struct pci_dev *pdev = priv->pdev;
135 int ret;
136
137 if (boot_success) {
138 bus->fw_state = QTNF_FW_STATE_FW_DNLD_DONE;
139
140 ret = qtnf_core_attach(bus);
141 if (ret) {
142 pr_err("failed to attach core\n");
143 boot_success = false;
144 }
145 }
146
147 if (boot_success) {
125 qtnf_debugfs_init(bus, drv_name);
148 qtnf_debugfs_init(bus, DRV_NAME);
126 qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
127 qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
128 qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
129 } else {
130 bus->fw_state = QTNF_FW_STATE_DETACHED;
131 }
132
133 put_device(&pdev->dev);
134}
135
149 qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
150 qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
151 qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
152 } else {
153 bus->fw_state = QTNF_FW_STATE_DETACHED;
154 }
155
156 put_device(&pdev->dev);
157}
158
136static void qtnf_tune_pcie_mps(struct qtnf_pcie_bus_priv *priv)
159static void qtnf_tune_pcie_mps(struct pci_dev *pdev)
137{
160{
138 struct pci_dev *pdev = priv->pdev;
139 struct pci_dev *parent;
140 int mps_p, mps_o, mps_m, mps;
141 int ret;
142
143 /* current mps */
144 mps_o = pcie_get_mps(pdev);
145
146 /* maximum supported mps */

--- 11 unchanged lines hidden (view full) ---

158 mps = min(mps_m, mps_p);
159 }
160 }
161
162 ret = pcie_set_mps(pdev, mps);
163 if (ret) {
164 pr_err("failed to set mps to %d, keep using current %d\n",
165 mps, mps_o);
161 struct pci_dev *parent;
162 int mps_p, mps_o, mps_m, mps;
163 int ret;
164
165 /* current mps */
166 mps_o = pcie_get_mps(pdev);
167
168 /* maximum supported mps */

--- 11 unchanged lines hidden (view full) ---

180 mps = min(mps_m, mps_p);
181 }
182 }
183
184 ret = pcie_set_mps(pdev, mps);
185 if (ret) {
186 pr_err("failed to set mps to %d, keep using current %d\n",
187 mps, mps_o);
166 priv->mps = mps_o;
167 return;
168 }
169
170 pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m);
188 return;
189 }
190
191 pr_debug("set mps to %d (was %d, max %d)\n", mps, mps_o, mps_m);
171 priv->mps = mps;
172}
173
174static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv, bool use_msi)
175{
176 struct pci_dev *pdev = priv->pdev;
177
178 /* fall back to legacy INTx interrupts by default */
179 priv->msi_enabled = 0;

--- 9 unchanged lines hidden (view full) ---

189 }
190
191 if (!priv->msi_enabled) {
192 pr_warn("legacy PCIE interrupts enabled\n");
193 pci_intx(pdev, 1);
194 }
195}
196
192}
193
194static void qtnf_pcie_init_irq(struct qtnf_pcie_bus_priv *priv, bool use_msi)
195{
196 struct pci_dev *pdev = priv->pdev;
197
198 /* fall back to legacy INTx interrupts by default */
199 priv->msi_enabled = 0;

--- 9 unchanged lines hidden (view full) ---

209 }
210
211 if (!priv->msi_enabled) {
212 pr_warn("legacy PCIE interrupts enabled\n");
213 pci_intx(pdev, 1);
214 }
215}
216
197static void __iomem *qtnf_map_bar(struct qtnf_pcie_bus_priv *priv, u8 index)
217static void __iomem *qtnf_map_bar(struct pci_dev *pdev, u8 index)
198{
199 void __iomem *vaddr;
200 dma_addr_t busaddr;
201 size_t len;
202 int ret;
203
218{
219 void __iomem *vaddr;
220 dma_addr_t busaddr;
221 size_t len;
222 int ret;
223
204 ret = pcim_iomap_regions(priv->pdev, 1 << index, "qtnfmac_pcie");
224 ret = pcim_iomap_regions(pdev, 1 << index, "qtnfmac_pcie");
205 if (ret)
206 return IOMEM_ERR_PTR(ret);
207
225 if (ret)
226 return IOMEM_ERR_PTR(ret);
227
208 busaddr = pci_resource_start(priv->pdev, index);
209 len = pci_resource_len(priv->pdev, index);
210 vaddr = pcim_iomap_table(priv->pdev)[index];
228 busaddr = pci_resource_start(pdev, index);
229 len = pci_resource_len(pdev, index);
230 vaddr = pcim_iomap_table(pdev)[index];
211 if (!vaddr)
212 return IOMEM_ERR_PTR(-ENOMEM);
213
214 pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n",
215 index, vaddr, &busaddr, (int)len);
216
217 return vaddr;
218}
219
231 if (!vaddr)
232 return IOMEM_ERR_PTR(-ENOMEM);
233
234 pr_debug("BAR%u vaddr=0x%p busaddr=%pad len=%u\n",
235 index, vaddr, &busaddr, (int)len);
236
237 return vaddr;
238}
239
220static int qtnf_pcie_init_memory(struct qtnf_pcie_bus_priv *priv)
221{
222 int ret = -ENOMEM;
223
224 priv->sysctl_bar = qtnf_map_bar(priv, QTN_SYSCTL_BAR);
225 if (IS_ERR(priv->sysctl_bar)) {
226 pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR);
227 return ret;
228 }
229
230 priv->dmareg_bar = qtnf_map_bar(priv, QTN_DMA_BAR);
231 if (IS_ERR(priv->dmareg_bar)) {
232 pr_err("failed to map BAR%u\n", QTN_DMA_BAR);
233 return ret;
234 }
235
236 priv->epmem_bar = qtnf_map_bar(priv, QTN_SHMEM_BAR);
237 if (IS_ERR(priv->epmem_bar)) {
238 pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR);
239 return ret;
240 }
241
242 return 0;
243}
244
245static void qtnf_pcie_control_rx_callback(void *arg, const u8 __iomem *buf,
246 size_t len)
247{
248 struct qtnf_pcie_bus_priv *priv = arg;
249 struct qtnf_bus *bus = pci_get_drvdata(priv->pdev);
250 struct sk_buff *skb;
251
252 if (unlikely(len == 0)) {

--- 24 unchanged lines hidden (view full) ---

277 qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND,
278 ipc_tx_reg, priv->workqueue,
279 ipc_int, &rx_callback);
280 qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND,
281 ipc_rx_reg, priv->workqueue,
282 ipc_int, &rx_callback);
283}
284
240static void qtnf_pcie_control_rx_callback(void *arg, const u8 __iomem *buf,
241 size_t len)
242{
243 struct qtnf_pcie_bus_priv *priv = arg;
244 struct qtnf_bus *bus = pci_get_drvdata(priv->pdev);
245 struct sk_buff *skb;
246
247 if (unlikely(len == 0)) {

--- 24 unchanged lines hidden (view full) ---

272 qtnf_shm_ipc_init(&priv->shm_ipc_ep_in, QTNF_SHM_IPC_OUTBOUND,
273 ipc_tx_reg, priv->workqueue,
274 ipc_int, &rx_callback);
275 qtnf_shm_ipc_init(&priv->shm_ipc_ep_out, QTNF_SHM_IPC_INBOUND,
276 ipc_rx_reg, priv->workqueue,
277 ipc_int, &rx_callback);
278}
279
285int qtnf_pcie_probe(struct pci_dev *pdev, size_t priv_size,
286 const struct qtnf_bus_ops *bus_ops, u64 dma_mask,
287 bool use_msi)
280static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
288{
289 struct qtnf_pcie_bus_priv *pcie_priv;
290 struct qtnf_bus *bus;
281{
282 struct qtnf_pcie_bus_priv *pcie_priv;
283 struct qtnf_bus *bus;
284 void __iomem *sysctl_bar;
285 void __iomem *epmem_bar;
286 void __iomem *dmareg_bar;
287 unsigned int chipid;
291 int ret;
292
288 int ret;
289
293 bus = devm_kzalloc(&pdev->dev,
294 sizeof(*bus) + priv_size, GFP_KERNEL);
290 if (!pci_is_pcie(pdev)) {
291 pr_err("device %s is not PCI Express\n", pci_name(pdev));
292 return -EIO;
293 }
294
295 qtnf_tune_pcie_mps(pdev);
296
297 ret = pcim_enable_device(pdev);
298 if (ret) {
299 pr_err("failed to init PCI device %x\n", pdev->device);
300 return ret;
301 }
302
303 pci_set_master(pdev);
304
305 sysctl_bar = qtnf_map_bar(pdev, QTN_SYSCTL_BAR);
306 if (IS_ERR(sysctl_bar)) {
307 pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR);
308 return ret;
309 }
310
311 dmareg_bar = qtnf_map_bar(pdev, QTN_DMA_BAR);
312 if (IS_ERR(dmareg_bar)) {
313 pr_err("failed to map BAR%u\n", QTN_DMA_BAR);
314 return ret;
315 }
316
317 epmem_bar = qtnf_map_bar(pdev, QTN_SHMEM_BAR);
318 if (IS_ERR(epmem_bar)) {
319 pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR);
320 return ret;
321 }
322
323 chipid = qtnf_chip_id_get(sysctl_bar);
324
325 pr_info("identified device: %s\n", qtnf_chipid_to_string(chipid));
326
327 switch (chipid) {
328 case QTN_CHIP_ID_PEARL:
329 case QTN_CHIP_ID_PEARL_B:
330 case QTN_CHIP_ID_PEARL_C:
331 bus = qtnf_pcie_pearl_alloc(pdev);
332 break;
333 default:
334 pr_err("unsupported chip ID 0x%x\n", chipid);
335 return -ENOTSUPP;
336 }
337
295 if (!bus)
296 return -ENOMEM;
297
298 pcie_priv = get_bus_priv(bus);
338 if (!bus)
339 return -ENOMEM;
340
341 pcie_priv = get_bus_priv(bus);
299
300 pci_set_drvdata(pdev, bus);
342 pci_set_drvdata(pdev, bus);
301 bus->bus_ops = bus_ops;
302 bus->dev = &pdev->dev;
303 bus->fw_state = QTNF_FW_STATE_RESET;
304 pcie_priv->pdev = pdev;
305 pcie_priv->tx_stopped = 0;
343 bus->dev = &pdev->dev;
344 bus->fw_state = QTNF_FW_STATE_RESET;
345 pcie_priv->pdev = pdev;
346 pcie_priv->tx_stopped = 0;
347 pcie_priv->rx_bd_num = rx_bd_size_param;
348 pcie_priv->flashboot = flashboot;
306
349
350 if (fw_blksize_param > QTN_PCIE_MAX_FW_BUFSZ)
351 pcie_priv->fw_blksize = QTN_PCIE_MAX_FW_BUFSZ;
352 else
353 pcie_priv->fw_blksize = fw_blksize_param;
354
307 mutex_init(&bus->bus_lock);
308 spin_lock_init(&pcie_priv->tx_lock);
309 spin_lock_init(&pcie_priv->tx_reclaim_lock);
310
311 pcie_priv->tx_full_count = 0;
312 pcie_priv->tx_done_count = 0;
313 pcie_priv->pcie_irq_count = 0;
314 pcie_priv->tx_reclaim_done = 0;
315 pcie_priv->tx_reclaim_req = 0;
316
317 pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PCIE");
318 if (!pcie_priv->workqueue) {
319 pr_err("failed to alloc bus workqueue\n");
355 mutex_init(&bus->bus_lock);
356 spin_lock_init(&pcie_priv->tx_lock);
357 spin_lock_init(&pcie_priv->tx_reclaim_lock);
358
359 pcie_priv->tx_full_count = 0;
360 pcie_priv->tx_done_count = 0;
361 pcie_priv->pcie_irq_count = 0;
362 pcie_priv->tx_reclaim_done = 0;
363 pcie_priv->tx_reclaim_req = 0;
364
365 pcie_priv->workqueue = create_singlethread_workqueue("QTNF_PCIE");
366 if (!pcie_priv->workqueue) {
367 pr_err("failed to alloc bus workqueue\n");
320 ret = -ENODEV;
321 goto err_init;
368 return -ENODEV;
322 }
323
369 }
370
324 init_dummy_netdev(&bus->mux_dev);
325
326 if (!pci_is_pcie(pdev)) {
327 pr_err("device %s is not PCI Express\n", pci_name(pdev));
328 ret = -EIO;
329 goto err_base;
330 }
331
332 qtnf_tune_pcie_mps(pcie_priv);
333
334 ret = pcim_enable_device(pdev);
371 ret = dma_set_mask_and_coherent(&pdev->dev,
372 pcie_priv->dma_mask_get_cb());
335 if (ret) {
373 if (ret) {
336 pr_err("failed to init PCI device %x\n", pdev->device);
337 goto err_base;
338 } else {
339 pr_debug("successful init of PCI device %x\n", pdev->device);
374 pr_err("PCIE DMA coherent mask init failed 0x%llx\n",
375 pcie_priv->dma_mask_get_cb());
376 goto error;
340 }
341
377 }
378
342 ret = dma_set_mask_and_coherent(&pdev->dev, dma_mask);
343 if (ret) {
344 pr_err("PCIE DMA coherent mask init failed\n");
345 goto err_base;
346 }
347
348 pci_set_master(pdev);
379 init_dummy_netdev(&bus->mux_dev);
349 qtnf_pcie_init_irq(pcie_priv, use_msi);
380 qtnf_pcie_init_irq(pcie_priv, use_msi);
350
351 ret = qtnf_pcie_init_memory(pcie_priv);
352 if (ret < 0) {
353 pr_err("PCIE memory init failed\n");
354 goto err_base;
355 }
356
381 pcie_priv->sysctl_bar = sysctl_bar;
382 pcie_priv->dmareg_bar = dmareg_bar;
383 pcie_priv->epmem_bar = epmem_bar;
357 pci_save_state(pdev);
358
384 pci_save_state(pdev);
385
386 ret = pcie_priv->probe_cb(bus, tx_bd_size_param);
387 if (ret)
388 goto error;
389
390 qtnf_pcie_bringup_fw_async(bus);
359 return 0;
360
391 return 0;
392
361err_base:
393error:
362 flush_workqueue(pcie_priv->workqueue);
363 destroy_workqueue(pcie_priv->workqueue);
394 flush_workqueue(pcie_priv->workqueue);
395 destroy_workqueue(pcie_priv->workqueue);
364err_init:
365 pci_set_drvdata(pdev, NULL);
396 pci_set_drvdata(pdev, NULL);
366
367 return ret;
368}
369
370static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv)
371{
372 qtnf_shm_ipc_free(&priv->shm_ipc_ep_in);
373 qtnf_shm_ipc_free(&priv->shm_ipc_ep_out);
374}
375
397 return ret;
398}
399
400static void qtnf_pcie_free_shm_ipc(struct qtnf_pcie_bus_priv *priv)
401{
402 qtnf_shm_ipc_free(&priv->shm_ipc_ep_in);
403 qtnf_shm_ipc_free(&priv->shm_ipc_ep_out);
404}
405
376void qtnf_pcie_remove(struct qtnf_bus *bus, struct qtnf_pcie_bus_priv *priv)
406static void qtnf_pcie_remove(struct pci_dev *dev)
377{
407{
408 struct qtnf_pcie_bus_priv *priv;
409 struct qtnf_bus *bus;
410
411 bus = pci_get_drvdata(dev);
412 if (!bus)
413 return;
414
415 priv = get_bus_priv(bus);
416
378 cancel_work_sync(&bus->fw_work);
379
380 if (bus->fw_state == QTNF_FW_STATE_ACTIVE ||
381 bus->fw_state == QTNF_FW_STATE_EP_DEAD)
382 qtnf_core_detach(bus);
383
384 netif_napi_del(&bus->mux_napi);
385 flush_workqueue(priv->workqueue);
386 destroy_workqueue(priv->workqueue);
387 tasklet_kill(&priv->reclaim_tq);
388
389 qtnf_pcie_free_shm_ipc(priv);
390 qtnf_debugfs_remove(bus);
417 cancel_work_sync(&bus->fw_work);
418
419 if (bus->fw_state == QTNF_FW_STATE_ACTIVE ||
420 bus->fw_state == QTNF_FW_STATE_EP_DEAD)
421 qtnf_core_detach(bus);
422
423 netif_napi_del(&bus->mux_napi);
424 flush_workqueue(priv->workqueue);
425 destroy_workqueue(priv->workqueue);
426 tasklet_kill(&priv->reclaim_tq);
427
428 qtnf_pcie_free_shm_ipc(priv);
429 qtnf_debugfs_remove(bus);
430 priv->remove_cb(bus);
391 pci_set_drvdata(priv->pdev, NULL);
392}
431 pci_set_drvdata(priv->pdev, NULL);
432}
433
434#ifdef CONFIG_PM_SLEEP
435static int qtnf_pcie_suspend(struct device *dev)
436{
437 struct qtnf_pcie_bus_priv *priv;
438 struct qtnf_bus *bus;
439
440 bus = pci_get_drvdata(to_pci_dev(dev));
441 if (!bus)
442 return -EFAULT;
443
444 priv = get_bus_priv(bus);
445 return priv->suspend_cb(bus);
446}
447
448static int qtnf_pcie_resume(struct device *dev)
449{
450 struct qtnf_pcie_bus_priv *priv;
451 struct qtnf_bus *bus;
452
453 bus = pci_get_drvdata(to_pci_dev(dev));
454 if (!bus)
455 return -EFAULT;
456
457 priv = get_bus_priv(bus);
458 return priv->resume_cb(bus);
459}
460
461/* Power Management Hooks */
462static SIMPLE_DEV_PM_OPS(qtnf_pcie_pm_ops, qtnf_pcie_suspend,
463 qtnf_pcie_resume);
464#endif
465
466static const struct pci_device_id qtnf_pcie_devid_table[] = {
467 {
468 PCIE_VENDOR_ID_QUANTENNA, PCIE_DEVICE_ID_QTN_PEARL,
469 PCI_ANY_ID, PCI_ANY_ID, 0, 0,
470 },
471 { },
472};
473
474MODULE_DEVICE_TABLE(pci, qtnf_pcie_devid_table);
475
476static struct pci_driver qtnf_pcie_drv_data = {
477 .name = DRV_NAME,
478 .id_table = qtnf_pcie_devid_table,
479 .probe = qtnf_pcie_probe,
480 .remove = qtnf_pcie_remove,
481#ifdef CONFIG_PM_SLEEP
482 .driver = {
483 .pm = &qtnf_pcie_pm_ops,
484 },
485#endif
486};
487
488static int __init qtnf_pcie_register(void)
489{
490 return pci_register_driver(&qtnf_pcie_drv_data);
491}
492
493static void __exit qtnf_pcie_exit(void)
494{
495 pci_unregister_driver(&qtnf_pcie_drv_data);
496}
497
498module_init(qtnf_pcie_register);
499module_exit(qtnf_pcie_exit);
500
501MODULE_AUTHOR("Quantenna Communications");
502MODULE_DESCRIPTION("Quantenna PCIe bus driver for 802.11 wireless LAN.");
503MODULE_LICENSE("GPL");