static void wcn36xx_stop(struct ieee80211_hw *hw) { struct wcn36xx *wcn = hw->priv; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop"); wcn36xx_debugfs_exit(wcn); wcn36xx_smd_stop(wcn); wcn36xx_dxe_deinit(wcn); wcn36xx_smd_close(wcn); wcn36xx_dxe_free_mem_pools(wcn); wcn36xx_dxe_free_ctl_blks(wcn); kfree(wcn->smd_buf); }
int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) { size_t s; void *cpu_addr; /* Allocate BD headers for MGMT frames */ /* Where this come from ask QC */ wcn->mgmt_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, GFP_KERNEL); if (!cpu_addr) goto out_err; wcn->mgmt_mem_pool.virt_addr = cpu_addr; memset(cpu_addr, 0, s); /* Allocate BD headers for DATA frames */ /* Where this come from ask QC */ wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE + 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, GFP_KERNEL); if (!cpu_addr) goto out_err; wcn->data_mem_pool.virt_addr = cpu_addr; memset(cpu_addr, 0, s); return 0; out_err: wcn36xx_dxe_free_mem_pools(wcn); wcn36xx_err("Failed to allocate BD mempool\n"); return -ENOMEM; }
static int wcn36xx_start(struct ieee80211_hw *hw) { struct wcn36xx *wcn = hw->priv; int ret; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start"); /* SMD initialization */ ret = wcn36xx_smd_open(wcn); if (ret) { wcn36xx_error("Failed to open smd channel: %d", ret); goto out_err; } /* Not to receive INT until the whole buf from SMD is read */ smd_disable_read_intr(wcn->smd_ch); /* Allocate memory pools for Mgmt BD headers and Data BD headers */ ret = wcn36xx_dxe_allocate_mem_pools(wcn); if (ret) { wcn36xx_error("Failed to alloc DXE mempool: %d", ret); goto out_smd_close; } wcn36xx_dxe_alloc_ctl_blks(wcn); if (ret) { wcn36xx_error("Failed to alloc DXE ctl blocks: %d", ret); goto out_free_dxe_pool; } INIT_WORK(&wcn->rx_ready_work, wcn36xx_rx_ready_work); /* Maximum SMD message size is 4k */ wcn->smd_buf = kmalloc(4096, GFP_KERNEL); if (!wcn->smd_buf) { wcn36xx_error("Failed to allocate smd buf"); ret = -ENOMEM; goto out_free_dxe_ctl; } /* TODO pass configuration to FW */ ret = wcn36xx_smd_load_nv(wcn); if (ret) { wcn36xx_error("Failed to push NV to chip"); goto out_free_smd_buf; } ret = wcn36xx_smd_start(wcn); if (ret) { wcn36xx_error("Failed to start chip"); goto out_free_smd_buf; } /* DMA channel initialization */ ret = wcn36xx_dxe_init(wcn); if (ret) { wcn36xx_error("DXE init failed"); goto out_smd_stop; } wcn36xx_pmc_init(wcn); wcn36xx_debugfs_init(wcn); if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { ret = wcn36xx_smd_feature_caps_exchange(wcn); if (ret) wcn36xx_warn("Exchange feature caps failed"); } return 0; out_smd_stop: wcn36xx_smd_stop(wcn); out_free_smd_buf: kfree(wcn->smd_buf); out_free_dxe_pool: wcn36xx_dxe_free_mem_pools(wcn); out_free_dxe_ctl: wcn36xx_dxe_free_ctl_blks(wcn); out_smd_close: wcn36xx_smd_close(wcn); out_err: return ret; }