int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) { int ret; wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L; wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H; wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L; wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H; wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L; wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H; wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB; wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB; wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L; wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H; wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L; wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H; /* DXE control block allocation */ ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch); if (ret) goto out_err; ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch); if (ret) goto out_err; ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch); if (ret) goto out_err; ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch); if (ret) goto out_err; /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ ret = qcom_smem_state_update_bits(wcn->tx_enable_state, WCN36XX_SMSM_WLAN_TX_ENABLE | WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY, WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); if (ret) goto out_err; return 0; out_err: wcn36xx_err("Failed to allocate DXE control blocks\n"); wcn36xx_dxe_free_ctl_blks(wcn); return -ENOMEM; }
int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) { int ret; wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L; wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H; wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L; wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H; wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L; wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H; wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L; wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H; wcn->dxe_tx_l_ch.dxe_wq = WCN36XX_DXE_WQ_TX_L; wcn->dxe_tx_h_ch.dxe_wq = WCN36XX_DXE_WQ_TX_H; wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD; wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD; wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB; wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB; wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L; wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H; wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L; wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H; /* DXE control block allocation */ ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch); if (ret) goto out_err; ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch); if (ret) goto out_err; ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch); if (ret) goto out_err; ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch); if (ret) goto out_err; /* TODO most probably do not need this */ /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ ret = smsm_change_state(SMSM_APPS_STATE, WCN36XX_SMSM_WLAN_TX_ENABLE, WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); return 0; out_err: wcn36xx_error("Failed to allocate DXE control blocks"); wcn36xx_dxe_free_ctl_blks(wcn); return -ENOMEM; }
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); }
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; }