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"); |
|