示例#1
0
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);
}
示例#2
0
文件: ahb.c 项目: Anjali05/linux
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;
}