static int athp_pci_detach(device_t dev) { struct ath10k_pci *ar_pci = device_get_softc(dev); struct ath10k *ar = &ar_pci->sc_sc; ath10k_warn(ar, "%s: called\n", __func__); /* Signal things we're going down.. */ ATHP_LOCK(ar); ar->sc_invalid = 1; ATHP_UNLOCK(ar); /* Shutdown ioctl handler */ athp_ioctl_teardown(ar); /* XXX TODO: synchronise with running things first */ /* * Do a config read to clear pre-existing pci error status. */ (void) pci_read_config(dev, PCIR_COMMAND, 4); /* stop/free the core - this detaches net80211 state */ ath10k_core_unregister(ar); /* kill tasklet(s) */ /* deinit irq - stop getting more interrupts */ ath10k_pci_deinit_irq(ar_pci); /* ce deinit */ ath10k_pci_ce_deinit(ar); /* free pipes */ ath10k_pci_free_pipes(ar); /* free HTT RX buffers */ ath10k_htt_rx_free_desc(ar, &ar->htt); /* pci release */ /* sleep sync */ /* buffers */ athp_pci_free_bufs(ar_pci); /* core itself - destroys taskqueues, etc */ ath10k_core_destroy(ar); /* Free bus resources */ bus_generic_detach(dev); /* Tear down interrupt */ ath10k_pci_free_irq(ar_pci); bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, ar_pci->sc_sr); /* XXX disable busmastering? */ /* Free BMI buffers */ athp_descdma_free(ar, &ar_pci->sc_bmi_txbuf); athp_descdma_free(ar, &ar_pci->sc_bmi_rxbuf); athp_trace_close(ar); /* Free locks */ mtx_destroy(&ar_pci->ps_mtx); mtx_destroy(&ar_pci->ce_mtx); mtx_destroy(&ar->sc_conf_mtx); mtx_destroy(&ar->sc_data_mtx); mtx_destroy(&ar->sc_buf_mtx); mtx_destroy(&ar->sc_dma_mtx); mtx_destroy(&ar->sc_mtx); /* Tear down the pipe taskqueue */ if (ar_pci->pipe_taskq) { taskqueue_drain_all(ar_pci->pipe_taskq); taskqueue_free(ar_pci->pipe_taskq); } return (0); }
static int ath10k_ahb_probe(struct platform_device *pdev) { struct ath10k *ar; struct ath10k_ahb *ar_ahb; struct ath10k_pci *ar_pci; const struct of_device_id *of_id; enum ath10k_hw_rev hw_rev; size_t size; int ret; struct ath10k_bus_params bus_params; of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); if (!of_id) { dev_err(&pdev->dev, "failed to find matching device tree id\n"); return -EINVAL; } hw_rev = (enum ath10k_hw_rev)of_id->data; size = sizeof(*ar_pci) + sizeof(*ar_ahb); ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, hw_rev, &ath10k_ahb_hif_ops); if (!ar) { dev_err(&pdev->dev, "failed to allocate core\n"); return -ENOMEM; } ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n"); ar_pci = ath10k_pci_priv(ar); ar_ahb = ath10k_ahb_priv(ar); ar_ahb->pdev = pdev; platform_set_drvdata(pdev, ar); ret = ath10k_ahb_resource_init(ar); if (ret) goto err_core_destroy; ar->dev_id = 0; ar_pci->mem = ar_ahb->mem; ar_pci->mem_len = ar_ahb->mem_len; ar_pci->ar = ar; ar_pci->ce.bus_ops = &ath10k_ahb_bus_ops; ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr; ar->ce_priv = &ar_pci->ce; ret = ath10k_pci_setup_resource(ar); if (ret) { ath10k_err(ar, "failed to setup resource: %d\n", ret); goto err_resource_deinit; } ath10k_pci_init_napi(ar); ret = ath10k_ahb_request_irq_legacy(ar); if (ret) goto err_free_pipes; ret = ath10k_ahb_prepare_device(ar); if (ret) goto err_free_irq; ath10k_pci_ce_deinit(ar); bus_params.dev_type = ATH10K_DEV_TYPE_LL; bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id == 0xffffffff) { ath10k_err(ar, "failed to get chip id\n"); ret = -ENODEV; goto err_halt_device; } ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_err(ar, "failed to register driver core: %d\n", ret); goto err_halt_device; } return 0; err_halt_device: ath10k_ahb_halt_chip(ar); ath10k_ahb_clock_disable(ar); err_free_irq: ath10k_ahb_release_irq_legacy(ar); err_free_pipes: ath10k_pci_free_pipes(ar); err_resource_deinit: ath10k_ahb_resource_deinit(ar); err_core_destroy: ath10k_core_destroy(ar); platform_set_drvdata(pdev, NULL); return ret; }