diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/pcie/trans.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 137 |
1 files changed, 29 insertions, 108 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index e5160d620868..d2e69ad53b27 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -81,6 +81,7 @@ #include "fw/api/tx.h" #include "internal.h" #include "iwl-fh.h" +#include "iwl-context-info-gen3.h" /* extended range in FW SRAM */ #define IWL_FW_MEM_EXTENDED_START 0x40000 @@ -1607,11 +1608,15 @@ iwl_pcie_set_interrupt_capa(struct pci_dev *pdev, struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int max_irqs, num_irqs, i, ret; u16 pci_cmd; + u32 max_rx_queues = IWL_MAX_RX_HW_QUEUES; if (!cfg_trans->mq_rx_supported) goto enable_msi; - max_irqs = min_t(u32, num_online_cpus() + 2, IWL_MAX_RX_HW_QUEUES); + if (cfg_trans->device_family <= IWL_DEVICE_FAMILY_9000) + max_rx_queues = IWL_9000_MAX_RX_HW_QUEUES; + + max_irqs = min_t(u32, num_online_cpus() + 2, max_rx_queues); for (i = 0; i < max_irqs; i++) trans_pcie->msix_entries[i].entry = i; @@ -1907,6 +1912,9 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, trans->txqs.cmd.q_id = trans_cfg->cmd_queue; trans->txqs.cmd.fifo = trans_cfg->cmd_fifo; trans->txqs.cmd.wdg_timeout = trans_cfg->cmd_q_wdg_timeout; + trans->txqs.page_offs = trans_cfg->cb_data_offs; + trans->txqs.dev_cmd_offs = trans_cfg->cb_data_offs + sizeof(void *); + if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS)) trans_pcie->n_no_reclaim_cmds = 0; else @@ -1924,13 +1932,10 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) trans_pcie->supported_dma_mask = DMA_BIT_MASK(11); - trans_pcie->bc_table_dword = trans_cfg->bc_table_dword; + trans->txqs.bc_table_dword = trans_cfg->bc_table_dword; trans_pcie->scd_set_active = trans_cfg->scd_set_active; trans_pcie->sw_csum_tx = trans_cfg->sw_csum_tx; - trans_pcie->page_offs = trans_cfg->cb_data_offs; - trans_pcie->dev_cmd_offs = trans_cfg->cb_data_offs + sizeof(void *); - trans->command_groups = trans_cfg->command_groups; trans->command_groups_size = trans_cfg->command_groups_size; @@ -1951,7 +1956,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_synchronize_irqs(trans); if (trans->trans_cfg->gen2) - iwl_pcie_gen2_tx_free(trans); + iwl_txq_gen2_tx_free(trans); else iwl_pcie_tx_free(trans); iwl_pcie_rx_free(trans); @@ -1975,15 +1980,11 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_free_fw_monitor(trans); - for_each_possible_cpu(i) { - struct iwl_tso_hdr_page *p = - per_cpu_ptr(trans_pcie->tso_hdr_page, i); - - if (p->page) - __free_page(p->page); - } + if (trans_pcie->pnvm_dram.size) + dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size, + trans_pcie->pnvm_dram.block, + trans_pcie->pnvm_dram.physical); - free_percpu(trans_pcie->tso_hdr_page); mutex_destroy(&trans_pcie->mutex); iwl_trans_free(trans); } @@ -2276,36 +2277,6 @@ static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block) #define IWL_FLUSH_WAIT_MS 2000 -void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq) -{ - u32 txq_id = txq->id; - u32 status; - bool active; - u8 fifo; - - if (trans->trans_cfg->use_tfh) { - IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id, - txq->read_ptr, txq->write_ptr); - /* TODO: access new SCD registers and dump them */ - return; - } - - status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id)); - fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; - active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); - - IWL_ERR(trans, - "Queue %d is %sactive on fifo %d and stuck for %u ms. SW [%d, %d] HW [%d, %d] FH TRB=0x0%x\n", - txq_id, active ? "" : "in", fifo, - jiffies_to_msecs(txq->wd_timeout), - txq->read_ptr, txq->write_ptr, - iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & - (trans->trans_cfg->base_params->max_tfd_queue_size - 1), - iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) & - (trans->trans_cfg->base_params->max_tfd_queue_size - 1), - iwl_read_direct32(trans, FH_TX_TRB_REG(fifo))); -} - static int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue, struct iwl_trans_rxq_dma_data *data) { @@ -2374,7 +2345,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) if (txq->read_ptr != txq->write_ptr) { IWL_ERR(trans, "fail to flush all tx fifo queues Q %d\n", txq_idx); - iwl_trans_pcie_log_scd_error(trans, txq); + iwl_txq_log_scd_error(trans, txq); return -ETIMEDOUT; } @@ -2985,12 +2956,11 @@ static void iwl_trans_pcie_debugfs_cleanup(struct iwl_trans *trans) static u32 iwl_trans_pcie_get_cmdlen(struct iwl_trans *trans, void *tfd) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 cmdlen = 0; int i; - for (i = 0; i < trans_pcie->max_tbs; i++) - cmdlen += iwl_pcie_tfd_tb_get_len(trans, tfd, i); + for (i = 0; i < trans->txqs.tfd.max_tbs; i++) + cmdlen += iwl_txq_gen1_tfd_tb_get_len(trans, tfd, i); return cmdlen; } @@ -3329,14 +3299,14 @@ static struct iwl_trans_dump_data data = (void *)dump_data->data; if (dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD) && cmdq) { - u16 tfd_size = trans_pcie->tfd_size; + u16 tfd_size = trans->txqs.tfd.size; data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD); txcmd = (void *)data->data; spin_lock_bh(&cmdq->lock); ptr = cmdq->write_ptr; for (i = 0; i < cmdq->n_window; i++) { - u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr); + u8 idx = iwl_txq_get_cmd_index(cmdq, ptr); u8 tfdidx; u32 caplen, cmdlen; @@ -3359,7 +3329,7 @@ static struct iwl_trans_dump_data txcmd = (void *)((u8 *)txcmd->data + caplen); } - ptr = iwl_queue_dec_wrap(trans, ptr); + ptr = iwl_txq_dec_wrap(trans, ptr); } spin_unlock_bh(&cmdq->lock); @@ -3478,15 +3448,16 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = { .send_cmd = iwl_trans_pcie_gen2_send_hcmd, - .tx = iwl_trans_pcie_gen2_tx, + .tx = iwl_txq_gen2_tx, .reclaim = iwl_trans_pcie_reclaim, .set_q_ptrs = iwl_trans_pcie_set_q_ptrs, - .txq_alloc = iwl_trans_pcie_dyn_txq_alloc, - .txq_free = iwl_trans_pcie_dyn_txq_free, + .txq_alloc = iwl_txq_dyn_alloc, + .txq_free = iwl_txq_dyn_free, .wait_txq_empty = iwl_trans_pcie_wait_txq_empty, .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, + .set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm, #ifdef CONFIG_IWLWIFI_DEBUGFS .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, #endif @@ -3498,34 +3469,18 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, { struct iwl_trans_pcie *trans_pcie; struct iwl_trans *trans; - int ret, addr_size, txcmd_size, txcmd_align; + int ret, addr_size; const struct iwl_trans_ops *ops = &trans_ops_pcie_gen2; - if (!cfg_trans->gen2) { + if (!cfg_trans->gen2) ops = &trans_ops_pcie; - txcmd_size = sizeof(struct iwl_tx_cmd); - txcmd_align = sizeof(void *); - } else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) { - txcmd_size = sizeof(struct iwl_tx_cmd_gen2); - txcmd_align = 64; - } else { - txcmd_size = sizeof(struct iwl_tx_cmd_gen3); - txcmd_align = 128; - } - - txcmd_size += sizeof(struct iwl_cmd_header); - txcmd_size += 36; /* biggest possible 802.11 header */ - - /* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */ - if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align)) - return ERR_PTR(-EINVAL); ret = pcim_enable_device(pdev); if (ret) return ERR_PTR(ret); trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, ops, - txcmd_size, txcmd_align); + cfg_trans); if (!trans) return ERR_PTR(-ENOMEM); @@ -3547,11 +3502,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } INIT_WORK(&trans_pcie->rba.rx_alloc, iwl_pcie_rx_allocator_work); - trans_pcie->tso_hdr_page = alloc_percpu(struct iwl_tso_hdr_page); - if (!trans_pcie->tso_hdr_page) { - ret = -ENOMEM; - goto out_no_pci; - } trans_pcie->debug_rfkill = -1; if (!cfg_trans->base_params->pcie_l1_allowed) { @@ -3567,19 +3517,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->def_rx_queue = 0; - if (cfg_trans->use_tfh) { - addr_size = 64; - trans_pcie->max_tbs = IWL_TFH_NUM_TBS; - trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd); - } else { - addr_size = 36; - trans_pcie->max_tbs = IWL_NUM_OF_TBS; - trans_pcie->tfd_size = sizeof(struct iwl_tfd); - } - trans->max_skb_frags = IWL_PCIE_MAX_FRAGS(trans_pcie); - pci_set_master(pdev); + addr_size = trans->txqs.tfd.addr_size; ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(addr_size)); if (!ret) ret = pci_set_consistent_dma_mask(pdev, @@ -3661,24 +3601,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, init_waitqueue_head(&trans_pcie->sx_waitq); - /* - * For gen2 devices, we use a single allocation for each byte-count - * table, but they're pretty small (1k) so use a DMA pool that we - * allocate here. - */ - if (cfg_trans->gen2) { - size_t bc_tbl_size; - - if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_AX210) - bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); - else - bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl); - - trans_pcie->bc_pool = dmam_pool_create("iwlwifi:bc", &pdev->dev, - bc_tbl_size, 256, 0); - if (!trans_pcie->bc_pool) - goto out_no_pci; - } if (trans_pcie->msix_enabled) { ret = iwl_pcie_init_msix_handler(pdev, trans_pcie); @@ -3712,7 +3634,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, out_free_ict: iwl_pcie_free_ict(trans); out_no_pci: - free_percpu(trans_pcie->tso_hdr_page); destroy_workqueue(trans_pcie->rba.alloc_wq); out_free_trans: iwl_trans_free(trans); |