1bfcc09ddSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2bfcc09ddSBjoern A. Zeeb /* 3*a4128aadSBjoern A. Zeeb * Copyright (C) 2003-2014, 2018-2021, 2023-2024 Intel Corporation 4bfcc09ddSBjoern A. Zeeb * Copyright (C) 2013-2015 Intel Mobile Communications GmbH 5bfcc09ddSBjoern A. Zeeb * Copyright (C) 2016-2017 Intel Deutschland GmbH 6bfcc09ddSBjoern A. Zeeb */ 7bfcc09ddSBjoern A. Zeeb #include <linux/etherdevice.h> 8bfcc09ddSBjoern A. Zeeb #include <linux/ieee80211.h> 9*a4128aadSBjoern A. Zeeb #include <linux/dmapool.h> 10bfcc09ddSBjoern A. Zeeb #include <linux/slab.h> 11bfcc09ddSBjoern A. Zeeb #include <linux/sched.h> 12*a4128aadSBjoern A. Zeeb #include <linux/tcp.h> 13bfcc09ddSBjoern A. Zeeb #ifdef CONFIG_INET 14bfcc09ddSBjoern A. Zeeb #include <net/ip6_checksum.h> 15bfcc09ddSBjoern A. Zeeb #include <net/tso.h> 16bfcc09ddSBjoern A. Zeeb #endif 17bfcc09ddSBjoern A. Zeeb #if defined(__FreeBSD__) 18bfcc09ddSBjoern A. Zeeb #include <net/mac80211.h> 19bfcc09ddSBjoern A. Zeeb #endif 20bfcc09ddSBjoern A. Zeeb 21*a4128aadSBjoern A. Zeeb #include "fw/api/commands.h" 22*a4128aadSBjoern A. Zeeb #include "fw/api/datapath.h" 23*a4128aadSBjoern A. Zeeb #include "fw/api/debug.h" 24*a4128aadSBjoern A. Zeeb #include "iwl-fh.h" 25bfcc09ddSBjoern A. Zeeb #include "iwl-debug.h" 26bfcc09ddSBjoern A. Zeeb #include "iwl-csr.h" 27bfcc09ddSBjoern A. Zeeb #include "iwl-prph.h" 28bfcc09ddSBjoern A. Zeeb #include "iwl-io.h" 29bfcc09ddSBjoern A. Zeeb #include "iwl-scd.h" 30bfcc09ddSBjoern A. Zeeb #include "iwl-op-mode.h" 31bfcc09ddSBjoern A. Zeeb #include "internal.h" 32bfcc09ddSBjoern A. Zeeb #include "fw/api/tx.h" 33bfcc09ddSBjoern A. Zeeb 34bfcc09ddSBjoern A. Zeeb /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** 35bfcc09ddSBjoern A. Zeeb * DMA services 36bfcc09ddSBjoern A. Zeeb * 37bfcc09ddSBjoern A. Zeeb * Theory of operation 38bfcc09ddSBjoern A. Zeeb * 39bfcc09ddSBjoern A. Zeeb * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer 40bfcc09ddSBjoern A. Zeeb * of buffer descriptors, each of which points to one or more data buffers for 41bfcc09ddSBjoern A. Zeeb * the device to read from or fill. Driver and device exchange status of each 42bfcc09ddSBjoern A. Zeeb * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty 43bfcc09ddSBjoern A. Zeeb * entries in each circular buffer, to protect against confusing empty and full 44bfcc09ddSBjoern A. Zeeb * queue states. 45bfcc09ddSBjoern A. Zeeb * 46bfcc09ddSBjoern A. Zeeb * The device reads or writes the data in the queues via the device's several 47bfcc09ddSBjoern A. Zeeb * DMA/FIFO channels. Each queue is mapped to a single DMA channel. 48bfcc09ddSBjoern A. Zeeb * 49bfcc09ddSBjoern A. Zeeb * For Tx queue, there are low mark and high mark limits. If, after queuing 50bfcc09ddSBjoern A. Zeeb * the packet for Tx, free space become < low mark, Tx queue stopped. When 51bfcc09ddSBjoern A. Zeeb * reclaiming packets (on 'tx done IRQ), if free space become > high mark, 52bfcc09ddSBjoern A. Zeeb * Tx queue resumed. 53bfcc09ddSBjoern A. Zeeb * 54bfcc09ddSBjoern A. Zeeb ***************************************************/ 55bfcc09ddSBjoern A. Zeeb 56bfcc09ddSBjoern A. Zeeb 57bfcc09ddSBjoern A. Zeeb int iwl_pcie_alloc_dma_ptr(struct iwl_trans *trans, 58bfcc09ddSBjoern A. Zeeb struct iwl_dma_ptr *ptr, size_t size) 59bfcc09ddSBjoern A. Zeeb { 60bfcc09ddSBjoern A. Zeeb if (WARN_ON(ptr->addr)) 61bfcc09ddSBjoern A. Zeeb return -EINVAL; 62bfcc09ddSBjoern A. Zeeb 63bfcc09ddSBjoern A. Zeeb ptr->addr = dma_alloc_coherent(trans->dev, size, 64bfcc09ddSBjoern A. Zeeb &ptr->dma, GFP_KERNEL); 65bfcc09ddSBjoern A. Zeeb if (!ptr->addr) 66bfcc09ddSBjoern A. Zeeb return -ENOMEM; 67bfcc09ddSBjoern A. Zeeb ptr->size = size; 68bfcc09ddSBjoern A. Zeeb return 0; 69bfcc09ddSBjoern A. Zeeb } 70bfcc09ddSBjoern A. Zeeb 71bfcc09ddSBjoern A. Zeeb void iwl_pcie_free_dma_ptr(struct iwl_trans *trans, struct iwl_dma_ptr *ptr) 72bfcc09ddSBjoern A. Zeeb { 73bfcc09ddSBjoern A. Zeeb if (unlikely(!ptr->addr)) 74bfcc09ddSBjoern A. Zeeb return; 75bfcc09ddSBjoern A. Zeeb 76bfcc09ddSBjoern A. Zeeb dma_free_coherent(trans->dev, ptr->size, ptr->addr, ptr->dma); 77bfcc09ddSBjoern A. Zeeb memset(ptr, 0, sizeof(*ptr)); 78bfcc09ddSBjoern A. Zeeb } 79bfcc09ddSBjoern A. Zeeb 80bfcc09ddSBjoern A. Zeeb /* 81bfcc09ddSBjoern A. Zeeb * iwl_pcie_txq_inc_wr_ptr - Send new write index to hardware 82bfcc09ddSBjoern A. Zeeb */ 83bfcc09ddSBjoern A. Zeeb static void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, 84bfcc09ddSBjoern A. Zeeb struct iwl_txq *txq) 85bfcc09ddSBjoern A. Zeeb { 86*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 87bfcc09ddSBjoern A. Zeeb u32 reg = 0; 88bfcc09ddSBjoern A. Zeeb int txq_id = txq->id; 89bfcc09ddSBjoern A. Zeeb 90bfcc09ddSBjoern A. Zeeb lockdep_assert_held(&txq->lock); 91bfcc09ddSBjoern A. Zeeb 92bfcc09ddSBjoern A. Zeeb /* 93bfcc09ddSBjoern A. Zeeb * explicitly wake up the NIC if: 94bfcc09ddSBjoern A. Zeeb * 1. shadow registers aren't enabled 95bfcc09ddSBjoern A. Zeeb * 2. NIC is woken up for CMD regardless of shadow outside this function 96bfcc09ddSBjoern A. Zeeb * 3. there is a chance that the NIC is asleep 97bfcc09ddSBjoern A. Zeeb */ 98bfcc09ddSBjoern A. Zeeb if (!trans->trans_cfg->base_params->shadow_reg_enable && 99*a4128aadSBjoern A. Zeeb txq_id != trans_pcie->txqs.cmd.q_id && 100bfcc09ddSBjoern A. Zeeb test_bit(STATUS_TPOWER_PMI, &trans->status)) { 101bfcc09ddSBjoern A. Zeeb /* 102bfcc09ddSBjoern A. Zeeb * wake up nic if it's powered down ... 103bfcc09ddSBjoern A. Zeeb * uCode will wake up, and interrupt us again, so next 104bfcc09ddSBjoern A. Zeeb * time we'll skip this part. 105bfcc09ddSBjoern A. Zeeb */ 106bfcc09ddSBjoern A. Zeeb reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); 107bfcc09ddSBjoern A. Zeeb 108bfcc09ddSBjoern A. Zeeb if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { 109bfcc09ddSBjoern A. Zeeb IWL_DEBUG_INFO(trans, "Tx queue %d requesting wakeup, GP1 = 0x%x\n", 110bfcc09ddSBjoern A. Zeeb txq_id, reg); 111bfcc09ddSBjoern A. Zeeb iwl_set_bit(trans, CSR_GP_CNTRL, 112bfcc09ddSBjoern A. Zeeb CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 113bfcc09ddSBjoern A. Zeeb txq->need_update = true; 114bfcc09ddSBjoern A. Zeeb return; 115bfcc09ddSBjoern A. Zeeb } 116bfcc09ddSBjoern A. Zeeb } 117bfcc09ddSBjoern A. Zeeb 118bfcc09ddSBjoern A. Zeeb /* 119bfcc09ddSBjoern A. Zeeb * if not in power-save mode, uCode will never sleep when we're 120bfcc09ddSBjoern A. Zeeb * trying to tx (during RFKILL, we're not trying to tx). 121bfcc09ddSBjoern A. Zeeb */ 122bfcc09ddSBjoern A. Zeeb IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->write_ptr); 123bfcc09ddSBjoern A. Zeeb if (!txq->block) 124bfcc09ddSBjoern A. Zeeb iwl_write32(trans, HBUS_TARG_WRPTR, 125bfcc09ddSBjoern A. Zeeb txq->write_ptr | (txq_id << 8)); 126bfcc09ddSBjoern A. Zeeb } 127bfcc09ddSBjoern A. Zeeb 128bfcc09ddSBjoern A. Zeeb void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) 129bfcc09ddSBjoern A. Zeeb { 130*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 131bfcc09ddSBjoern A. Zeeb int i; 132bfcc09ddSBjoern A. Zeeb 133bfcc09ddSBjoern A. Zeeb for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) { 134*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[i]; 135bfcc09ddSBjoern A. Zeeb 136*a4128aadSBjoern A. Zeeb if (!test_bit(i, trans_pcie->txqs.queue_used)) 137bfcc09ddSBjoern A. Zeeb continue; 138bfcc09ddSBjoern A. Zeeb 139bfcc09ddSBjoern A. Zeeb spin_lock_bh(&txq->lock); 140bfcc09ddSBjoern A. Zeeb if (txq->need_update) { 141bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_inc_wr_ptr(trans, txq); 142bfcc09ddSBjoern A. Zeeb txq->need_update = false; 143bfcc09ddSBjoern A. Zeeb } 144bfcc09ddSBjoern A. Zeeb spin_unlock_bh(&txq->lock); 145bfcc09ddSBjoern A. Zeeb } 146bfcc09ddSBjoern A. Zeeb } 147bfcc09ddSBjoern A. Zeeb 148*a4128aadSBjoern A. Zeeb static inline void iwl_pcie_gen1_tfd_set_tb(struct iwl_tfd *tfd, 149bfcc09ddSBjoern A. Zeeb u8 idx, dma_addr_t addr, u16 len) 150bfcc09ddSBjoern A. Zeeb { 151*a4128aadSBjoern A. Zeeb struct iwl_tfd_tb *tb = &tfd->tbs[idx]; 152bfcc09ddSBjoern A. Zeeb u16 hi_n_len = len << 4; 153bfcc09ddSBjoern A. Zeeb 154bfcc09ddSBjoern A. Zeeb put_unaligned_le32(addr, &tb->lo); 155bfcc09ddSBjoern A. Zeeb hi_n_len |= iwl_get_dma_hi_addr(addr); 156bfcc09ddSBjoern A. Zeeb 157bfcc09ddSBjoern A. Zeeb tb->hi_n_len = cpu_to_le16(hi_n_len); 158bfcc09ddSBjoern A. Zeeb 159*a4128aadSBjoern A. Zeeb tfd->num_tbs = idx + 1; 160*a4128aadSBjoern A. Zeeb } 161*a4128aadSBjoern A. Zeeb 162*a4128aadSBjoern A. Zeeb static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_tfd *tfd) 163*a4128aadSBjoern A. Zeeb { 164*a4128aadSBjoern A. Zeeb return tfd->num_tbs & 0x1f; 165bfcc09ddSBjoern A. Zeeb } 166bfcc09ddSBjoern A. Zeeb 167bfcc09ddSBjoern A. Zeeb static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq, 168bfcc09ddSBjoern A. Zeeb dma_addr_t addr, u16 len, bool reset) 169bfcc09ddSBjoern A. Zeeb { 170*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 171bfcc09ddSBjoern A. Zeeb void *tfd; 172bfcc09ddSBjoern A. Zeeb u32 num_tbs; 173bfcc09ddSBjoern A. Zeeb 174*a4128aadSBjoern A. Zeeb tfd = (u8 *)txq->tfds + trans_pcie->txqs.tfd.size * txq->write_ptr; 175bfcc09ddSBjoern A. Zeeb 176bfcc09ddSBjoern A. Zeeb if (reset) 177*a4128aadSBjoern A. Zeeb memset(tfd, 0, trans_pcie->txqs.tfd.size); 178bfcc09ddSBjoern A. Zeeb 179*a4128aadSBjoern A. Zeeb num_tbs = iwl_txq_gen1_tfd_get_num_tbs(tfd); 180bfcc09ddSBjoern A. Zeeb 181bfcc09ddSBjoern A. Zeeb /* Each TFD can point to a maximum max_tbs Tx buffers */ 182*a4128aadSBjoern A. Zeeb if (num_tbs >= trans_pcie->txqs.tfd.max_tbs) { 183bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Error can not send more than %d chunks\n", 184*a4128aadSBjoern A. Zeeb trans_pcie->txqs.tfd.max_tbs); 185bfcc09ddSBjoern A. Zeeb return -EINVAL; 186bfcc09ddSBjoern A. Zeeb } 187bfcc09ddSBjoern A. Zeeb 188bfcc09ddSBjoern A. Zeeb if (WARN(addr & ~IWL_TX_DMA_MASK, 189bfcc09ddSBjoern A. Zeeb "Unaligned address = %llx\n", (unsigned long long)addr)) 190bfcc09ddSBjoern A. Zeeb return -EINVAL; 191bfcc09ddSBjoern A. Zeeb 192*a4128aadSBjoern A. Zeeb iwl_pcie_gen1_tfd_set_tb(tfd, num_tbs, addr, len); 193bfcc09ddSBjoern A. Zeeb 194bfcc09ddSBjoern A. Zeeb return num_tbs; 195bfcc09ddSBjoern A. Zeeb } 196bfcc09ddSBjoern A. Zeeb 197bfcc09ddSBjoern A. Zeeb static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans) 198bfcc09ddSBjoern A. Zeeb { 199bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 200bfcc09ddSBjoern A. Zeeb 201bfcc09ddSBjoern A. Zeeb if (!trans->trans_cfg->base_params->apmg_wake_up_wa) 202bfcc09ddSBjoern A. Zeeb return; 203bfcc09ddSBjoern A. Zeeb 204bfcc09ddSBjoern A. Zeeb spin_lock(&trans_pcie->reg_lock); 205bfcc09ddSBjoern A. Zeeb 206bfcc09ddSBjoern A. Zeeb if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) { 207bfcc09ddSBjoern A. Zeeb spin_unlock(&trans_pcie->reg_lock); 208bfcc09ddSBjoern A. Zeeb return; 209bfcc09ddSBjoern A. Zeeb } 210bfcc09ddSBjoern A. Zeeb 211bfcc09ddSBjoern A. Zeeb trans_pcie->cmd_hold_nic_awake = false; 212bfcc09ddSBjoern A. Zeeb __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, 213bfcc09ddSBjoern A. Zeeb CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 214bfcc09ddSBjoern A. Zeeb spin_unlock(&trans_pcie->reg_lock); 215bfcc09ddSBjoern A. Zeeb } 216bfcc09ddSBjoern A. Zeeb 217*a4128aadSBjoern A. Zeeb static void iwl_pcie_free_and_unmap_tso_page(struct iwl_trans *trans, 218*a4128aadSBjoern A. Zeeb struct page *page) 219*a4128aadSBjoern A. Zeeb { 220*a4128aadSBjoern A. Zeeb struct iwl_tso_page_info *info = IWL_TSO_PAGE_INFO(page_address(page)); 221*a4128aadSBjoern A. Zeeb 222*a4128aadSBjoern A. Zeeb /* Decrease internal use count and unmap/free page if needed */ 223*a4128aadSBjoern A. Zeeb if (refcount_dec_and_test(&info->use_count)) { 224*a4128aadSBjoern A. Zeeb dma_unmap_page(trans->dev, info->dma_addr, PAGE_SIZE, 225*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 226*a4128aadSBjoern A. Zeeb 227*a4128aadSBjoern A. Zeeb __free_page(page); 228*a4128aadSBjoern A. Zeeb } 229*a4128aadSBjoern A. Zeeb } 230*a4128aadSBjoern A. Zeeb 231*a4128aadSBjoern A. Zeeb void iwl_pcie_free_tso_pages(struct iwl_trans *trans, struct sk_buff *skb, 232*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *cmd_meta) 233*a4128aadSBjoern A. Zeeb { 234*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 235*a4128aadSBjoern A. Zeeb struct page **page_ptr; 236*a4128aadSBjoern A. Zeeb struct page *next; 237*a4128aadSBjoern A. Zeeb 238*a4128aadSBjoern A. Zeeb page_ptr = (void *)((u8 *)skb->cb + trans_pcie->txqs.page_offs); 239*a4128aadSBjoern A. Zeeb next = *page_ptr; 240*a4128aadSBjoern A. Zeeb *page_ptr = NULL; 241*a4128aadSBjoern A. Zeeb 242*a4128aadSBjoern A. Zeeb while (next) { 243*a4128aadSBjoern A. Zeeb struct iwl_tso_page_info *info; 244*a4128aadSBjoern A. Zeeb struct page *tmp = next; 245*a4128aadSBjoern A. Zeeb 246*a4128aadSBjoern A. Zeeb info = IWL_TSO_PAGE_INFO(page_address(next)); 247*a4128aadSBjoern A. Zeeb next = info->next; 248*a4128aadSBjoern A. Zeeb 249*a4128aadSBjoern A. Zeeb /* Unmap the scatter gather list that is on the last page */ 250*a4128aadSBjoern A. Zeeb if (!next && cmd_meta->sg_offset) { 251*a4128aadSBjoern A. Zeeb struct sg_table *sgt; 252*a4128aadSBjoern A. Zeeb 253*a4128aadSBjoern A. Zeeb sgt = (void *)((u8 *)page_address(tmp) + 254*a4128aadSBjoern A. Zeeb cmd_meta->sg_offset); 255*a4128aadSBjoern A. Zeeb 256*a4128aadSBjoern A. Zeeb dma_unmap_sgtable(trans->dev, sgt, DMA_TO_DEVICE, 0); 257*a4128aadSBjoern A. Zeeb } 258*a4128aadSBjoern A. Zeeb 259*a4128aadSBjoern A. Zeeb iwl_pcie_free_and_unmap_tso_page(trans, tmp); 260*a4128aadSBjoern A. Zeeb } 261*a4128aadSBjoern A. Zeeb } 262*a4128aadSBjoern A. Zeeb 263*a4128aadSBjoern A. Zeeb static inline dma_addr_t 264*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) 265*a4128aadSBjoern A. Zeeb { 266*a4128aadSBjoern A. Zeeb struct iwl_tfd_tb *tb = &tfd->tbs[idx]; 267*a4128aadSBjoern A. Zeeb dma_addr_t addr; 268*a4128aadSBjoern A. Zeeb dma_addr_t hi_len; 269*a4128aadSBjoern A. Zeeb 270*a4128aadSBjoern A. Zeeb addr = get_unaligned_le32(&tb->lo); 271*a4128aadSBjoern A. Zeeb 272*a4128aadSBjoern A. Zeeb if (sizeof(dma_addr_t) <= sizeof(u32)) 273*a4128aadSBjoern A. Zeeb return addr; 274*a4128aadSBjoern A. Zeeb 275*a4128aadSBjoern A. Zeeb hi_len = le16_to_cpu(tb->hi_n_len) & 0xF; 276*a4128aadSBjoern A. Zeeb 277*a4128aadSBjoern A. Zeeb /* 278*a4128aadSBjoern A. Zeeb * shift by 16 twice to avoid warnings on 32-bit 279*a4128aadSBjoern A. Zeeb * (where this code never runs anyway due to the 280*a4128aadSBjoern A. Zeeb * if statement above) 281*a4128aadSBjoern A. Zeeb */ 282*a4128aadSBjoern A. Zeeb return addr | ((hi_len << 16) << 16); 283*a4128aadSBjoern A. Zeeb } 284*a4128aadSBjoern A. Zeeb 285*a4128aadSBjoern A. Zeeb static void iwl_txq_set_tfd_invalid_gen1(struct iwl_trans *trans, 286*a4128aadSBjoern A. Zeeb struct iwl_tfd *tfd) 287*a4128aadSBjoern A. Zeeb { 288*a4128aadSBjoern A. Zeeb tfd->num_tbs = 0; 289*a4128aadSBjoern A. Zeeb 290*a4128aadSBjoern A. Zeeb iwl_pcie_gen1_tfd_set_tb(tfd, 0, trans->invalid_tx_cmd.dma, 291*a4128aadSBjoern A. Zeeb trans->invalid_tx_cmd.size); 292*a4128aadSBjoern A. Zeeb } 293*a4128aadSBjoern A. Zeeb 294*a4128aadSBjoern A. Zeeb static void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, 295*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *meta, 296*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, int index) 297*a4128aadSBjoern A. Zeeb { 298*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 299*a4128aadSBjoern A. Zeeb int i, num_tbs; 300*a4128aadSBjoern A. Zeeb struct iwl_tfd *tfd = iwl_txq_get_tfd(trans, txq, index); 301*a4128aadSBjoern A. Zeeb 302*a4128aadSBjoern A. Zeeb /* Sanity check on number of chunks */ 303*a4128aadSBjoern A. Zeeb num_tbs = iwl_txq_gen1_tfd_get_num_tbs(tfd); 304*a4128aadSBjoern A. Zeeb 305*a4128aadSBjoern A. Zeeb if (num_tbs > trans_pcie->txqs.tfd.max_tbs) { 306*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); 307*a4128aadSBjoern A. Zeeb /* @todo issue fatal error, it is quite serious situation */ 308*a4128aadSBjoern A. Zeeb return; 309*a4128aadSBjoern A. Zeeb } 310*a4128aadSBjoern A. Zeeb 311*a4128aadSBjoern A. Zeeb /* TB1 is mapped directly, the rest is the TSO page and SG list. */ 312*a4128aadSBjoern A. Zeeb if (meta->sg_offset) 313*a4128aadSBjoern A. Zeeb num_tbs = 2; 314*a4128aadSBjoern A. Zeeb 315*a4128aadSBjoern A. Zeeb /* first TB is never freed - it's the bidirectional DMA data */ 316*a4128aadSBjoern A. Zeeb 317*a4128aadSBjoern A. Zeeb for (i = 1; i < num_tbs; i++) { 318*a4128aadSBjoern A. Zeeb if (meta->tbs & BIT(i)) 319*a4128aadSBjoern A. Zeeb dma_unmap_page(trans->dev, 320*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_tb_get_addr(tfd, i), 321*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_tb_get_len(trans, 322*a4128aadSBjoern A. Zeeb tfd, i), 323*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 324*a4128aadSBjoern A. Zeeb else 325*a4128aadSBjoern A. Zeeb dma_unmap_single(trans->dev, 326*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_tb_get_addr(tfd, i), 327*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_tb_get_len(trans, 328*a4128aadSBjoern A. Zeeb tfd, i), 329*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 330*a4128aadSBjoern A. Zeeb } 331*a4128aadSBjoern A. Zeeb 332*a4128aadSBjoern A. Zeeb meta->tbs = 0; 333*a4128aadSBjoern A. Zeeb 334*a4128aadSBjoern A. Zeeb iwl_txq_set_tfd_invalid_gen1(trans, tfd); 335*a4128aadSBjoern A. Zeeb } 336*a4128aadSBjoern A. Zeeb 337*a4128aadSBjoern A. Zeeb /** 338*a4128aadSBjoern A. Zeeb * iwl_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] 339*a4128aadSBjoern A. Zeeb * @trans: transport private data 340*a4128aadSBjoern A. Zeeb * @txq: tx queue 341*a4128aadSBjoern A. Zeeb * @read_ptr: the TXQ read_ptr to free 342*a4128aadSBjoern A. Zeeb * 343*a4128aadSBjoern A. Zeeb * Does NOT advance any TFD circular buffer read/write indexes 344*a4128aadSBjoern A. Zeeb * Does NOT free the TFD itself (which is within circular buffer) 345*a4128aadSBjoern A. Zeeb */ 346*a4128aadSBjoern A. Zeeb static void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, 347*a4128aadSBjoern A. Zeeb int read_ptr) 348*a4128aadSBjoern A. Zeeb { 349*a4128aadSBjoern A. Zeeb /* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and 350*a4128aadSBjoern A. Zeeb * idx is bounded by n_window 351*a4128aadSBjoern A. Zeeb */ 352*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, read_ptr); 353*a4128aadSBjoern A. Zeeb struct sk_buff *skb; 354*a4128aadSBjoern A. Zeeb 355*a4128aadSBjoern A. Zeeb lockdep_assert_held(&txq->reclaim_lock); 356*a4128aadSBjoern A. Zeeb 357*a4128aadSBjoern A. Zeeb if (!txq->entries) 358*a4128aadSBjoern A. Zeeb return; 359*a4128aadSBjoern A. Zeeb 360*a4128aadSBjoern A. Zeeb /* We have only q->n_window txq->entries, but we use 361*a4128aadSBjoern A. Zeeb * TFD_QUEUE_SIZE_MAX tfds 362*a4128aadSBjoern A. Zeeb */ 363*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->gen2) 364*a4128aadSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, &txq->entries[idx].meta, 365*a4128aadSBjoern A. Zeeb iwl_txq_get_tfd(trans, txq, read_ptr)); 366*a4128aadSBjoern A. Zeeb else 367*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_unmap(trans, &txq->entries[idx].meta, 368*a4128aadSBjoern A. Zeeb txq, read_ptr); 369*a4128aadSBjoern A. Zeeb 370*a4128aadSBjoern A. Zeeb /* free SKB */ 371*a4128aadSBjoern A. Zeeb skb = txq->entries[idx].skb; 372*a4128aadSBjoern A. Zeeb 373*a4128aadSBjoern A. Zeeb /* Can be called from irqs-disabled context 374*a4128aadSBjoern A. Zeeb * If skb is not NULL, it means that the whole queue is being 375*a4128aadSBjoern A. Zeeb * freed and that the queue is not empty - free the skb 376*a4128aadSBjoern A. Zeeb */ 377*a4128aadSBjoern A. Zeeb if (skb) { 378*a4128aadSBjoern A. Zeeb iwl_op_mode_free_skb(trans->op_mode, skb); 379*a4128aadSBjoern A. Zeeb txq->entries[idx].skb = NULL; 380*a4128aadSBjoern A. Zeeb } 381*a4128aadSBjoern A. Zeeb } 382*a4128aadSBjoern A. Zeeb 383bfcc09ddSBjoern A. Zeeb /* 384bfcc09ddSBjoern A. Zeeb * iwl_pcie_txq_unmap - Unmap any remaining DMA mappings and free skb's 385bfcc09ddSBjoern A. Zeeb */ 386bfcc09ddSBjoern A. Zeeb static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) 387bfcc09ddSBjoern A. Zeeb { 388*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 389*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 390bfcc09ddSBjoern A. Zeeb 391bfcc09ddSBjoern A. Zeeb if (!txq) { 392bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Trying to free a queue that wasn't allocated?\n"); 393bfcc09ddSBjoern A. Zeeb return; 394bfcc09ddSBjoern A. Zeeb } 395bfcc09ddSBjoern A. Zeeb 396*a4128aadSBjoern A. Zeeb spin_lock_bh(&txq->reclaim_lock); 397*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 398bfcc09ddSBjoern A. Zeeb while (txq->write_ptr != txq->read_ptr) { 399bfcc09ddSBjoern A. Zeeb IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", 400bfcc09ddSBjoern A. Zeeb txq_id, txq->read_ptr); 401bfcc09ddSBjoern A. Zeeb 402*a4128aadSBjoern A. Zeeb if (txq_id != trans_pcie->txqs.cmd.q_id) { 403bfcc09ddSBjoern A. Zeeb struct sk_buff *skb = txq->entries[txq->read_ptr].skb; 404*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *cmd_meta = 405*a4128aadSBjoern A. Zeeb &txq->entries[txq->read_ptr].meta; 406bfcc09ddSBjoern A. Zeeb 407bfcc09ddSBjoern A. Zeeb if (WARN_ON_ONCE(!skb)) 408bfcc09ddSBjoern A. Zeeb continue; 409bfcc09ddSBjoern A. Zeeb 410*a4128aadSBjoern A. Zeeb iwl_pcie_free_tso_pages(trans, skb, cmd_meta); 411bfcc09ddSBjoern A. Zeeb } 412*a4128aadSBjoern A. Zeeb iwl_txq_free_tfd(trans, txq, txq->read_ptr); 413bfcc09ddSBjoern A. Zeeb txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr); 414bfcc09ddSBjoern A. Zeeb 415bfcc09ddSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr && 416*a4128aadSBjoern A. Zeeb txq_id == trans_pcie->txqs.cmd.q_id) 417bfcc09ddSBjoern A. Zeeb iwl_pcie_clear_cmd_in_flight(trans); 418bfcc09ddSBjoern A. Zeeb } 419bfcc09ddSBjoern A. Zeeb 420bfcc09ddSBjoern A. Zeeb while (!skb_queue_empty(&txq->overflow_q)) { 421bfcc09ddSBjoern A. Zeeb struct sk_buff *skb = __skb_dequeue(&txq->overflow_q); 422bfcc09ddSBjoern A. Zeeb 423bfcc09ddSBjoern A. Zeeb iwl_op_mode_free_skb(trans->op_mode, skb); 424bfcc09ddSBjoern A. Zeeb } 425bfcc09ddSBjoern A. Zeeb 426*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 427*a4128aadSBjoern A. Zeeb spin_unlock_bh(&txq->reclaim_lock); 428bfcc09ddSBjoern A. Zeeb 429bfcc09ddSBjoern A. Zeeb /* just in case - this queue may have been stopped */ 430*a4128aadSBjoern A. Zeeb iwl_trans_pcie_wake_queue(trans, txq); 431bfcc09ddSBjoern A. Zeeb } 432bfcc09ddSBjoern A. Zeeb 433bfcc09ddSBjoern A. Zeeb /* 434bfcc09ddSBjoern A. Zeeb * iwl_pcie_txq_free - Deallocate DMA queue. 435bfcc09ddSBjoern A. Zeeb * @txq: Transmit queue to deallocate. 436bfcc09ddSBjoern A. Zeeb * 437bfcc09ddSBjoern A. Zeeb * Empty queue by removing and destroying all BD's. 438bfcc09ddSBjoern A. Zeeb * Free all buffers. 439bfcc09ddSBjoern A. Zeeb * 0-fill, but do not free "txq" descriptor structure. 440bfcc09ddSBjoern A. Zeeb */ 441bfcc09ddSBjoern A. Zeeb static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) 442bfcc09ddSBjoern A. Zeeb { 443*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 444*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 445bfcc09ddSBjoern A. Zeeb struct device *dev = trans->dev; 446bfcc09ddSBjoern A. Zeeb int i; 447bfcc09ddSBjoern A. Zeeb 448bfcc09ddSBjoern A. Zeeb if (WARN_ON(!txq)) 449bfcc09ddSBjoern A. Zeeb return; 450bfcc09ddSBjoern A. Zeeb 451bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_unmap(trans, txq_id); 452bfcc09ddSBjoern A. Zeeb 453bfcc09ddSBjoern A. Zeeb /* De-alloc array of command/tx buffers */ 454*a4128aadSBjoern A. Zeeb if (txq_id == trans_pcie->txqs.cmd.q_id) 455bfcc09ddSBjoern A. Zeeb for (i = 0; i < txq->n_window; i++) { 456bfcc09ddSBjoern A. Zeeb kfree_sensitive(txq->entries[i].cmd); 457bfcc09ddSBjoern A. Zeeb kfree_sensitive(txq->entries[i].free_buf); 458bfcc09ddSBjoern A. Zeeb } 459bfcc09ddSBjoern A. Zeeb 460bfcc09ddSBjoern A. Zeeb /* De-alloc circular buffer of TFDs */ 461bfcc09ddSBjoern A. Zeeb if (txq->tfds) { 462bfcc09ddSBjoern A. Zeeb dma_free_coherent(dev, 463*a4128aadSBjoern A. Zeeb trans_pcie->txqs.tfd.size * 464bfcc09ddSBjoern A. Zeeb trans->trans_cfg->base_params->max_tfd_queue_size, 465bfcc09ddSBjoern A. Zeeb txq->tfds, txq->dma_addr); 466bfcc09ddSBjoern A. Zeeb txq->dma_addr = 0; 467bfcc09ddSBjoern A. Zeeb txq->tfds = NULL; 468bfcc09ddSBjoern A. Zeeb 469bfcc09ddSBjoern A. Zeeb dma_free_coherent(dev, 470bfcc09ddSBjoern A. Zeeb sizeof(*txq->first_tb_bufs) * txq->n_window, 471bfcc09ddSBjoern A. Zeeb txq->first_tb_bufs, txq->first_tb_dma); 472bfcc09ddSBjoern A. Zeeb } 473bfcc09ddSBjoern A. Zeeb 474bfcc09ddSBjoern A. Zeeb kfree(txq->entries); 475bfcc09ddSBjoern A. Zeeb txq->entries = NULL; 476bfcc09ddSBjoern A. Zeeb 477bfcc09ddSBjoern A. Zeeb del_timer_sync(&txq->stuck_timer); 478bfcc09ddSBjoern A. Zeeb 479bfcc09ddSBjoern A. Zeeb /* 0-fill queue descriptor structure */ 480bfcc09ddSBjoern A. Zeeb memset(txq, 0, sizeof(*txq)); 481bfcc09ddSBjoern A. Zeeb } 482bfcc09ddSBjoern A. Zeeb 483bfcc09ddSBjoern A. Zeeb void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr) 484bfcc09ddSBjoern A. Zeeb { 485bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 486bfcc09ddSBjoern A. Zeeb int nq = trans->trans_cfg->base_params->num_of_queues; 487bfcc09ddSBjoern A. Zeeb int chan; 488bfcc09ddSBjoern A. Zeeb u32 reg_val; 489bfcc09ddSBjoern A. Zeeb int clear_dwords = (SCD_TRANS_TBL_OFFSET_QUEUE(nq) - 490bfcc09ddSBjoern A. Zeeb SCD_CONTEXT_MEM_LOWER_BOUND) / sizeof(u32); 491bfcc09ddSBjoern A. Zeeb 492bfcc09ddSBjoern A. Zeeb /* make sure all queue are not stopped/used */ 493*a4128aadSBjoern A. Zeeb memset(trans_pcie->txqs.queue_stopped, 0, 494*a4128aadSBjoern A. Zeeb sizeof(trans_pcie->txqs.queue_stopped)); 495*a4128aadSBjoern A. Zeeb memset(trans_pcie->txqs.queue_used, 0, 496*a4128aadSBjoern A. Zeeb sizeof(trans_pcie->txqs.queue_used)); 497bfcc09ddSBjoern A. Zeeb 498bfcc09ddSBjoern A. Zeeb trans_pcie->scd_base_addr = 499bfcc09ddSBjoern A. Zeeb iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); 500bfcc09ddSBjoern A. Zeeb 501bfcc09ddSBjoern A. Zeeb WARN_ON(scd_base_addr != 0 && 502bfcc09ddSBjoern A. Zeeb scd_base_addr != trans_pcie->scd_base_addr); 503bfcc09ddSBjoern A. Zeeb 504bfcc09ddSBjoern A. Zeeb /* reset context data, TX status and translation data */ 505bfcc09ddSBjoern A. Zeeb iwl_trans_write_mem(trans, trans_pcie->scd_base_addr + 506bfcc09ddSBjoern A. Zeeb SCD_CONTEXT_MEM_LOWER_BOUND, 507bfcc09ddSBjoern A. Zeeb NULL, clear_dwords); 508bfcc09ddSBjoern A. Zeeb 509bfcc09ddSBjoern A. Zeeb iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, 510*a4128aadSBjoern A. Zeeb trans_pcie->txqs.scd_bc_tbls.dma >> 10); 511bfcc09ddSBjoern A. Zeeb 512bfcc09ddSBjoern A. Zeeb /* The chain extension of the SCD doesn't work well. This feature is 513bfcc09ddSBjoern A. Zeeb * enabled by default by the HW, so we need to disable it manually. 514bfcc09ddSBjoern A. Zeeb */ 515bfcc09ddSBjoern A. Zeeb if (trans->trans_cfg->base_params->scd_chain_ext_wa) 516bfcc09ddSBjoern A. Zeeb iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); 517bfcc09ddSBjoern A. Zeeb 518*a4128aadSBjoern A. Zeeb iwl_trans_ac_txq_enable(trans, trans_pcie->txqs.cmd.q_id, 519*a4128aadSBjoern A. Zeeb trans_pcie->txqs.cmd.fifo, 520*a4128aadSBjoern A. Zeeb trans_pcie->txqs.cmd.wdg_timeout); 521bfcc09ddSBjoern A. Zeeb 522bfcc09ddSBjoern A. Zeeb /* Activate all Tx DMA/FIFO channels */ 523bfcc09ddSBjoern A. Zeeb iwl_scd_activate_fifos(trans); 524bfcc09ddSBjoern A. Zeeb 525bfcc09ddSBjoern A. Zeeb /* Enable DMA channel */ 526bfcc09ddSBjoern A. Zeeb for (chan = 0; chan < FH_TCSR_CHNL_NUM; chan++) 527bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), 528bfcc09ddSBjoern A. Zeeb FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 529bfcc09ddSBjoern A. Zeeb FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); 530bfcc09ddSBjoern A. Zeeb 531bfcc09ddSBjoern A. Zeeb /* Update FH chicken bits */ 532bfcc09ddSBjoern A. Zeeb reg_val = iwl_read_direct32(trans, FH_TX_CHICKEN_BITS_REG); 533bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, 534bfcc09ddSBjoern A. Zeeb reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); 535bfcc09ddSBjoern A. Zeeb 536bfcc09ddSBjoern A. Zeeb /* Enable L1-Active */ 537bfcc09ddSBjoern A. Zeeb if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000) 538bfcc09ddSBjoern A. Zeeb iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG, 539bfcc09ddSBjoern A. Zeeb APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 540bfcc09ddSBjoern A. Zeeb } 541bfcc09ddSBjoern A. Zeeb 542bfcc09ddSBjoern A. Zeeb void iwl_trans_pcie_tx_reset(struct iwl_trans *trans) 543bfcc09ddSBjoern A. Zeeb { 544bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 545bfcc09ddSBjoern A. Zeeb int txq_id; 546bfcc09ddSBjoern A. Zeeb 547bfcc09ddSBjoern A. Zeeb /* 548bfcc09ddSBjoern A. Zeeb * we should never get here in gen2 trans mode return early to avoid 549bfcc09ddSBjoern A. Zeeb * having invalid accesses 550bfcc09ddSBjoern A. Zeeb */ 551bfcc09ddSBjoern A. Zeeb if (WARN_ON_ONCE(trans->trans_cfg->gen2)) 552bfcc09ddSBjoern A. Zeeb return; 553bfcc09ddSBjoern A. Zeeb 554bfcc09ddSBjoern A. Zeeb for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues; 555bfcc09ddSBjoern A. Zeeb txq_id++) { 556*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 5579af1bba4SBjoern A. Zeeb if (trans->trans_cfg->gen2) 558bfcc09ddSBjoern A. Zeeb iwl_write_direct64(trans, 559bfcc09ddSBjoern A. Zeeb FH_MEM_CBBC_QUEUE(trans, txq_id), 560bfcc09ddSBjoern A. Zeeb txq->dma_addr); 561bfcc09ddSBjoern A. Zeeb else 562bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, 563bfcc09ddSBjoern A. Zeeb FH_MEM_CBBC_QUEUE(trans, txq_id), 564bfcc09ddSBjoern A. Zeeb txq->dma_addr >> 8); 565bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_unmap(trans, txq_id); 566bfcc09ddSBjoern A. Zeeb txq->read_ptr = 0; 567bfcc09ddSBjoern A. Zeeb txq->write_ptr = 0; 568bfcc09ddSBjoern A. Zeeb } 569bfcc09ddSBjoern A. Zeeb 570bfcc09ddSBjoern A. Zeeb /* Tell NIC where to find the "keep warm" buffer */ 571bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, 572bfcc09ddSBjoern A. Zeeb trans_pcie->kw.dma >> 4); 573bfcc09ddSBjoern A. Zeeb 574bfcc09ddSBjoern A. Zeeb /* 575bfcc09ddSBjoern A. Zeeb * Send 0 as the scd_base_addr since the device may have be reset 576bfcc09ddSBjoern A. Zeeb * while we were in WoWLAN in which case SCD_SRAM_BASE_ADDR will 577bfcc09ddSBjoern A. Zeeb * contain garbage. 578bfcc09ddSBjoern A. Zeeb */ 579bfcc09ddSBjoern A. Zeeb iwl_pcie_tx_start(trans, 0); 580bfcc09ddSBjoern A. Zeeb } 581bfcc09ddSBjoern A. Zeeb 582bfcc09ddSBjoern A. Zeeb static void iwl_pcie_tx_stop_fh(struct iwl_trans *trans) 583bfcc09ddSBjoern A. Zeeb { 584bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 585bfcc09ddSBjoern A. Zeeb int ch, ret; 586bfcc09ddSBjoern A. Zeeb u32 mask = 0; 587bfcc09ddSBjoern A. Zeeb 588bfcc09ddSBjoern A. Zeeb spin_lock_bh(&trans_pcie->irq_lock); 589bfcc09ddSBjoern A. Zeeb 590bfcc09ddSBjoern A. Zeeb if (!iwl_trans_grab_nic_access(trans)) 591bfcc09ddSBjoern A. Zeeb goto out; 592bfcc09ddSBjoern A. Zeeb 593bfcc09ddSBjoern A. Zeeb /* Stop each Tx DMA channel */ 594bfcc09ddSBjoern A. Zeeb for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { 595bfcc09ddSBjoern A. Zeeb iwl_write32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); 596bfcc09ddSBjoern A. Zeeb mask |= FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch); 597bfcc09ddSBjoern A. Zeeb } 598bfcc09ddSBjoern A. Zeeb 599bfcc09ddSBjoern A. Zeeb /* Wait for DMA channels to be idle */ 600bfcc09ddSBjoern A. Zeeb ret = iwl_poll_bit(trans, FH_TSSR_TX_STATUS_REG, mask, mask, 5000); 601bfcc09ddSBjoern A. Zeeb if (ret < 0) 602bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, 603bfcc09ddSBjoern A. Zeeb "Failing on timeout while stopping DMA channel %d [0x%08x]\n", 604bfcc09ddSBjoern A. Zeeb ch, iwl_read32(trans, FH_TSSR_TX_STATUS_REG)); 605bfcc09ddSBjoern A. Zeeb 606bfcc09ddSBjoern A. Zeeb iwl_trans_release_nic_access(trans); 607bfcc09ddSBjoern A. Zeeb 608bfcc09ddSBjoern A. Zeeb out: 609bfcc09ddSBjoern A. Zeeb spin_unlock_bh(&trans_pcie->irq_lock); 610bfcc09ddSBjoern A. Zeeb } 611bfcc09ddSBjoern A. Zeeb 612bfcc09ddSBjoern A. Zeeb /* 613bfcc09ddSBjoern A. Zeeb * iwl_pcie_tx_stop - Stop all Tx DMA channels 614bfcc09ddSBjoern A. Zeeb */ 615bfcc09ddSBjoern A. Zeeb int iwl_pcie_tx_stop(struct iwl_trans *trans) 616bfcc09ddSBjoern A. Zeeb { 617bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 618bfcc09ddSBjoern A. Zeeb int txq_id; 619bfcc09ddSBjoern A. Zeeb 620bfcc09ddSBjoern A. Zeeb /* Turn off all Tx DMA fifos */ 621bfcc09ddSBjoern A. Zeeb iwl_scd_deactivate_fifos(trans); 622bfcc09ddSBjoern A. Zeeb 623bfcc09ddSBjoern A. Zeeb /* Turn off all Tx DMA channels */ 624bfcc09ddSBjoern A. Zeeb iwl_pcie_tx_stop_fh(trans); 625bfcc09ddSBjoern A. Zeeb 626bfcc09ddSBjoern A. Zeeb /* 627bfcc09ddSBjoern A. Zeeb * This function can be called before the op_mode disabled the 628bfcc09ddSBjoern A. Zeeb * queues. This happens when we have an rfkill interrupt. 629bfcc09ddSBjoern A. Zeeb * Since we stop Tx altogether - mark the queues as stopped. 630bfcc09ddSBjoern A. Zeeb */ 631*a4128aadSBjoern A. Zeeb memset(trans_pcie->txqs.queue_stopped, 0, 632*a4128aadSBjoern A. Zeeb sizeof(trans_pcie->txqs.queue_stopped)); 633*a4128aadSBjoern A. Zeeb memset(trans_pcie->txqs.queue_used, 0, 634*a4128aadSBjoern A. Zeeb sizeof(trans_pcie->txqs.queue_used)); 635bfcc09ddSBjoern A. Zeeb 636bfcc09ddSBjoern A. Zeeb /* This can happen: start_hw, stop_device */ 637bfcc09ddSBjoern A. Zeeb if (!trans_pcie->txq_memory) 638bfcc09ddSBjoern A. Zeeb return 0; 639bfcc09ddSBjoern A. Zeeb 640bfcc09ddSBjoern A. Zeeb /* Unmap DMA from host system and free skb's */ 641bfcc09ddSBjoern A. Zeeb for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues; 642bfcc09ddSBjoern A. Zeeb txq_id++) 643bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_unmap(trans, txq_id); 644bfcc09ddSBjoern A. Zeeb 645bfcc09ddSBjoern A. Zeeb return 0; 646bfcc09ddSBjoern A. Zeeb } 647bfcc09ddSBjoern A. Zeeb 648bfcc09ddSBjoern A. Zeeb /* 649bfcc09ddSBjoern A. Zeeb * iwl_trans_tx_free - Free TXQ Context 650bfcc09ddSBjoern A. Zeeb * 651bfcc09ddSBjoern A. Zeeb * Destroy all TX DMA queues and structures 652bfcc09ddSBjoern A. Zeeb */ 653bfcc09ddSBjoern A. Zeeb void iwl_pcie_tx_free(struct iwl_trans *trans) 654bfcc09ddSBjoern A. Zeeb { 655bfcc09ddSBjoern A. Zeeb int txq_id; 656bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 657bfcc09ddSBjoern A. Zeeb 658*a4128aadSBjoern A. Zeeb memset(trans_pcie->txqs.queue_used, 0, 659*a4128aadSBjoern A. Zeeb sizeof(trans_pcie->txqs.queue_used)); 660bfcc09ddSBjoern A. Zeeb 661bfcc09ddSBjoern A. Zeeb /* Tx queues */ 662bfcc09ddSBjoern A. Zeeb if (trans_pcie->txq_memory) { 663bfcc09ddSBjoern A. Zeeb for (txq_id = 0; 664bfcc09ddSBjoern A. Zeeb txq_id < trans->trans_cfg->base_params->num_of_queues; 665bfcc09ddSBjoern A. Zeeb txq_id++) { 666bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_free(trans, txq_id); 667*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id] = NULL; 668bfcc09ddSBjoern A. Zeeb } 669bfcc09ddSBjoern A. Zeeb } 670bfcc09ddSBjoern A. Zeeb 671bfcc09ddSBjoern A. Zeeb kfree(trans_pcie->txq_memory); 672bfcc09ddSBjoern A. Zeeb trans_pcie->txq_memory = NULL; 673bfcc09ddSBjoern A. Zeeb 674bfcc09ddSBjoern A. Zeeb iwl_pcie_free_dma_ptr(trans, &trans_pcie->kw); 675bfcc09ddSBjoern A. Zeeb 676*a4128aadSBjoern A. Zeeb iwl_pcie_free_dma_ptr(trans, &trans_pcie->txqs.scd_bc_tbls); 677*a4128aadSBjoern A. Zeeb } 678*a4128aadSBjoern A. Zeeb 679*a4128aadSBjoern A. Zeeb void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq) 680*a4128aadSBjoern A. Zeeb { 681*a4128aadSBjoern A. Zeeb u32 txq_id = txq->id; 682*a4128aadSBjoern A. Zeeb u32 status; 683*a4128aadSBjoern A. Zeeb bool active; 684*a4128aadSBjoern A. Zeeb u8 fifo; 685*a4128aadSBjoern A. Zeeb 686*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->gen2) { 687*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id, 688*a4128aadSBjoern A. Zeeb txq->read_ptr, txq->write_ptr); 689*a4128aadSBjoern A. Zeeb /* TODO: access new SCD registers and dump them */ 690*a4128aadSBjoern A. Zeeb return; 691*a4128aadSBjoern A. Zeeb } 692*a4128aadSBjoern A. Zeeb 693*a4128aadSBjoern A. Zeeb status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id)); 694*a4128aadSBjoern A. Zeeb fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; 695*a4128aadSBjoern A. Zeeb active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); 696*a4128aadSBjoern A. Zeeb 697*a4128aadSBjoern A. Zeeb IWL_ERR(trans, 698*a4128aadSBjoern A. Zeeb "Queue %d is %sactive on fifo %d and stuck for %u ms. SW [%d, %d] HW [%d, %d] FH TRB=0x0%x\n", 699*a4128aadSBjoern A. Zeeb txq_id, active ? "" : "in", fifo, 700*a4128aadSBjoern A. Zeeb jiffies_to_msecs(txq->wd_timeout), 701*a4128aadSBjoern A. Zeeb txq->read_ptr, txq->write_ptr, 702*a4128aadSBjoern A. Zeeb iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & 703*a4128aadSBjoern A. Zeeb (trans->trans_cfg->base_params->max_tfd_queue_size - 1), 704*a4128aadSBjoern A. Zeeb iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) & 705*a4128aadSBjoern A. Zeeb (trans->trans_cfg->base_params->max_tfd_queue_size - 1), 706*a4128aadSBjoern A. Zeeb iwl_read_direct32(trans, FH_TX_TRB_REG(fifo))); 707*a4128aadSBjoern A. Zeeb } 708*a4128aadSBjoern A. Zeeb 709*a4128aadSBjoern A. Zeeb static void iwl_txq_stuck_timer(struct timer_list *t) 710*a4128aadSBjoern A. Zeeb { 711*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = from_timer(txq, t, stuck_timer); 712*a4128aadSBjoern A. Zeeb struct iwl_trans *trans = txq->trans; 713*a4128aadSBjoern A. Zeeb 714*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 715*a4128aadSBjoern A. Zeeb /* check if triggered erroneously */ 716*a4128aadSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr) { 717*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 718*a4128aadSBjoern A. Zeeb return; 719*a4128aadSBjoern A. Zeeb } 720*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 721*a4128aadSBjoern A. Zeeb 722*a4128aadSBjoern A. Zeeb iwl_txq_log_scd_error(trans, txq); 723*a4128aadSBjoern A. Zeeb 724*a4128aadSBjoern A. Zeeb iwl_force_nmi(trans); 725*a4128aadSBjoern A. Zeeb } 726*a4128aadSBjoern A. Zeeb 727*a4128aadSBjoern A. Zeeb int iwl_pcie_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, 728*a4128aadSBjoern A. Zeeb int slots_num, bool cmd_queue) 729*a4128aadSBjoern A. Zeeb { 730*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 731*a4128aadSBjoern A. Zeeb size_t num_entries = trans->trans_cfg->gen2 ? 732*a4128aadSBjoern A. Zeeb slots_num : trans->trans_cfg->base_params->max_tfd_queue_size; 733*a4128aadSBjoern A. Zeeb size_t tfd_sz; 734*a4128aadSBjoern A. Zeeb size_t tb0_buf_sz; 735*a4128aadSBjoern A. Zeeb int i; 736*a4128aadSBjoern A. Zeeb 737*a4128aadSBjoern A. Zeeb if (WARN_ONCE(slots_num <= 0, "Invalid slots num:%d\n", slots_num)) 738*a4128aadSBjoern A. Zeeb return -EINVAL; 739*a4128aadSBjoern A. Zeeb 740*a4128aadSBjoern A. Zeeb if (WARN_ON(txq->entries || txq->tfds)) 741*a4128aadSBjoern A. Zeeb return -EINVAL; 742*a4128aadSBjoern A. Zeeb 743*a4128aadSBjoern A. Zeeb tfd_sz = trans_pcie->txqs.tfd.size * num_entries; 744*a4128aadSBjoern A. Zeeb 745*a4128aadSBjoern A. Zeeb timer_setup(&txq->stuck_timer, iwl_txq_stuck_timer, 0); 746*a4128aadSBjoern A. Zeeb txq->trans = trans; 747*a4128aadSBjoern A. Zeeb 748*a4128aadSBjoern A. Zeeb txq->n_window = slots_num; 749*a4128aadSBjoern A. Zeeb 750*a4128aadSBjoern A. Zeeb txq->entries = kcalloc(slots_num, 751*a4128aadSBjoern A. Zeeb sizeof(struct iwl_pcie_txq_entry), 752*a4128aadSBjoern A. Zeeb GFP_KERNEL); 753*a4128aadSBjoern A. Zeeb 754*a4128aadSBjoern A. Zeeb if (!txq->entries) 755*a4128aadSBjoern A. Zeeb goto error; 756*a4128aadSBjoern A. Zeeb 757*a4128aadSBjoern A. Zeeb if (cmd_queue) 758*a4128aadSBjoern A. Zeeb for (i = 0; i < slots_num; i++) { 759*a4128aadSBjoern A. Zeeb txq->entries[i].cmd = 760*a4128aadSBjoern A. Zeeb kmalloc(sizeof(struct iwl_device_cmd), 761*a4128aadSBjoern A. Zeeb GFP_KERNEL); 762*a4128aadSBjoern A. Zeeb if (!txq->entries[i].cmd) 763*a4128aadSBjoern A. Zeeb goto error; 764*a4128aadSBjoern A. Zeeb } 765*a4128aadSBjoern A. Zeeb 766*a4128aadSBjoern A. Zeeb /* Circular buffer of transmit frame descriptors (TFDs), 767*a4128aadSBjoern A. Zeeb * shared with device 768*a4128aadSBjoern A. Zeeb */ 769*a4128aadSBjoern A. Zeeb txq->tfds = dma_alloc_coherent(trans->dev, tfd_sz, 770*a4128aadSBjoern A. Zeeb &txq->dma_addr, GFP_KERNEL); 771*a4128aadSBjoern A. Zeeb if (!txq->tfds) 772*a4128aadSBjoern A. Zeeb goto error; 773*a4128aadSBjoern A. Zeeb 774*a4128aadSBjoern A. Zeeb BUILD_BUG_ON(sizeof(*txq->first_tb_bufs) != IWL_FIRST_TB_SIZE_ALIGN); 775*a4128aadSBjoern A. Zeeb 776*a4128aadSBjoern A. Zeeb tb0_buf_sz = sizeof(*txq->first_tb_bufs) * slots_num; 777*a4128aadSBjoern A. Zeeb 778*a4128aadSBjoern A. Zeeb txq->first_tb_bufs = dma_alloc_coherent(trans->dev, tb0_buf_sz, 779*a4128aadSBjoern A. Zeeb &txq->first_tb_dma, 780*a4128aadSBjoern A. Zeeb GFP_KERNEL); 781*a4128aadSBjoern A. Zeeb if (!txq->first_tb_bufs) 782*a4128aadSBjoern A. Zeeb goto err_free_tfds; 783*a4128aadSBjoern A. Zeeb 784*a4128aadSBjoern A. Zeeb for (i = 0; i < num_entries; i++) { 785*a4128aadSBjoern A. Zeeb void *tfd = iwl_txq_get_tfd(trans, txq, i); 786*a4128aadSBjoern A. Zeeb 787*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->gen2) 788*a4128aadSBjoern A. Zeeb iwl_txq_set_tfd_invalid_gen2(trans, tfd); 789*a4128aadSBjoern A. Zeeb else 790*a4128aadSBjoern A. Zeeb iwl_txq_set_tfd_invalid_gen1(trans, tfd); 791*a4128aadSBjoern A. Zeeb } 792*a4128aadSBjoern A. Zeeb 793*a4128aadSBjoern A. Zeeb return 0; 794*a4128aadSBjoern A. Zeeb err_free_tfds: 795*a4128aadSBjoern A. Zeeb dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr); 796*a4128aadSBjoern A. Zeeb txq->tfds = NULL; 797*a4128aadSBjoern A. Zeeb error: 798*a4128aadSBjoern A. Zeeb if (txq->entries && cmd_queue) 799*a4128aadSBjoern A. Zeeb for (i = 0; i < slots_num; i++) 800*a4128aadSBjoern A. Zeeb kfree(txq->entries[i].cmd); 801*a4128aadSBjoern A. Zeeb kfree(txq->entries); 802*a4128aadSBjoern A. Zeeb txq->entries = NULL; 803*a4128aadSBjoern A. Zeeb 804*a4128aadSBjoern A. Zeeb return -ENOMEM; 805bfcc09ddSBjoern A. Zeeb } 806bfcc09ddSBjoern A. Zeeb 807bfcc09ddSBjoern A. Zeeb /* 808bfcc09ddSBjoern A. Zeeb * iwl_pcie_tx_alloc - allocate TX context 809bfcc09ddSBjoern A. Zeeb * Allocate all Tx DMA structures and initialize them 810bfcc09ddSBjoern A. Zeeb */ 811bfcc09ddSBjoern A. Zeeb static int iwl_pcie_tx_alloc(struct iwl_trans *trans) 812bfcc09ddSBjoern A. Zeeb { 813bfcc09ddSBjoern A. Zeeb int ret; 814bfcc09ddSBjoern A. Zeeb int txq_id, slots_num; 815bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 816bfcc09ddSBjoern A. Zeeb u16 bc_tbls_size = trans->trans_cfg->base_params->num_of_queues; 817bfcc09ddSBjoern A. Zeeb 818bfcc09ddSBjoern A. Zeeb if (WARN_ON(trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)) 819bfcc09ddSBjoern A. Zeeb return -EINVAL; 820bfcc09ddSBjoern A. Zeeb 821bfcc09ddSBjoern A. Zeeb bc_tbls_size *= sizeof(struct iwlagn_scd_bc_tbl); 822bfcc09ddSBjoern A. Zeeb 823bfcc09ddSBjoern A. Zeeb /*It is not allowed to alloc twice, so warn when this happens. 824bfcc09ddSBjoern A. Zeeb * We cannot rely on the previous allocation, so free and fail */ 825bfcc09ddSBjoern A. Zeeb if (WARN_ON(trans_pcie->txq_memory)) { 826bfcc09ddSBjoern A. Zeeb ret = -EINVAL; 827bfcc09ddSBjoern A. Zeeb goto error; 828bfcc09ddSBjoern A. Zeeb } 829bfcc09ddSBjoern A. Zeeb 830*a4128aadSBjoern A. Zeeb ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->txqs.scd_bc_tbls, 831bfcc09ddSBjoern A. Zeeb bc_tbls_size); 832bfcc09ddSBjoern A. Zeeb if (ret) { 833bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); 834bfcc09ddSBjoern A. Zeeb goto error; 835bfcc09ddSBjoern A. Zeeb } 836bfcc09ddSBjoern A. Zeeb 837bfcc09ddSBjoern A. Zeeb /* Alloc keep-warm buffer */ 838bfcc09ddSBjoern A. Zeeb ret = iwl_pcie_alloc_dma_ptr(trans, &trans_pcie->kw, IWL_KW_SIZE); 839bfcc09ddSBjoern A. Zeeb if (ret) { 840bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Keep Warm allocation failed\n"); 841bfcc09ddSBjoern A. Zeeb goto error; 842bfcc09ddSBjoern A. Zeeb } 843bfcc09ddSBjoern A. Zeeb 844bfcc09ddSBjoern A. Zeeb trans_pcie->txq_memory = 845bfcc09ddSBjoern A. Zeeb kcalloc(trans->trans_cfg->base_params->num_of_queues, 846bfcc09ddSBjoern A. Zeeb sizeof(struct iwl_txq), GFP_KERNEL); 847bfcc09ddSBjoern A. Zeeb if (!trans_pcie->txq_memory) { 848bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Not enough memory for txq\n"); 849bfcc09ddSBjoern A. Zeeb ret = -ENOMEM; 850bfcc09ddSBjoern A. Zeeb goto error; 851bfcc09ddSBjoern A. Zeeb } 852bfcc09ddSBjoern A. Zeeb 853bfcc09ddSBjoern A. Zeeb /* Alloc and init all Tx queues, including the command queue (#4/#9) */ 854bfcc09ddSBjoern A. Zeeb for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues; 855bfcc09ddSBjoern A. Zeeb txq_id++) { 856*a4128aadSBjoern A. Zeeb bool cmd_queue = (txq_id == trans_pcie->txqs.cmd.q_id); 857bfcc09ddSBjoern A. Zeeb 858bfcc09ddSBjoern A. Zeeb if (cmd_queue) 859bfcc09ddSBjoern A. Zeeb slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE, 860bfcc09ddSBjoern A. Zeeb trans->cfg->min_txq_size); 861bfcc09ddSBjoern A. Zeeb else 862bfcc09ddSBjoern A. Zeeb slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE, 863d9836fb4SBjoern A. Zeeb trans->cfg->min_ba_txq_size); 864*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id] = &trans_pcie->txq_memory[txq_id]; 865*a4128aadSBjoern A. Zeeb ret = iwl_pcie_txq_alloc(trans, trans_pcie->txqs.txq[txq_id], 866*a4128aadSBjoern A. Zeeb slots_num, cmd_queue); 867bfcc09ddSBjoern A. Zeeb if (ret) { 868bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); 869bfcc09ddSBjoern A. Zeeb goto error; 870bfcc09ddSBjoern A. Zeeb } 871*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id]->id = txq_id; 872bfcc09ddSBjoern A. Zeeb } 873bfcc09ddSBjoern A. Zeeb 874bfcc09ddSBjoern A. Zeeb return 0; 875bfcc09ddSBjoern A. Zeeb 876bfcc09ddSBjoern A. Zeeb error: 877bfcc09ddSBjoern A. Zeeb iwl_pcie_tx_free(trans); 878bfcc09ddSBjoern A. Zeeb 879bfcc09ddSBjoern A. Zeeb return ret; 880bfcc09ddSBjoern A. Zeeb } 881bfcc09ddSBjoern A. Zeeb 882*a4128aadSBjoern A. Zeeb /* 883*a4128aadSBjoern A. Zeeb * iwl_queue_init - Initialize queue's high/low-water and read/write indexes 884*a4128aadSBjoern A. Zeeb */ 885*a4128aadSBjoern A. Zeeb static int iwl_queue_init(struct iwl_txq *q, int slots_num) 886*a4128aadSBjoern A. Zeeb { 887*a4128aadSBjoern A. Zeeb q->n_window = slots_num; 888*a4128aadSBjoern A. Zeeb 889*a4128aadSBjoern A. Zeeb /* slots_num must be power-of-two size, otherwise 890*a4128aadSBjoern A. Zeeb * iwl_txq_get_cmd_index is broken. 891*a4128aadSBjoern A. Zeeb */ 892*a4128aadSBjoern A. Zeeb if (WARN_ON(!is_power_of_2(slots_num))) 893*a4128aadSBjoern A. Zeeb return -EINVAL; 894*a4128aadSBjoern A. Zeeb 895*a4128aadSBjoern A. Zeeb q->low_mark = q->n_window / 4; 896*a4128aadSBjoern A. Zeeb if (q->low_mark < 4) 897*a4128aadSBjoern A. Zeeb q->low_mark = 4; 898*a4128aadSBjoern A. Zeeb 899*a4128aadSBjoern A. Zeeb q->high_mark = q->n_window / 8; 900*a4128aadSBjoern A. Zeeb if (q->high_mark < 2) 901*a4128aadSBjoern A. Zeeb q->high_mark = 2; 902*a4128aadSBjoern A. Zeeb 903*a4128aadSBjoern A. Zeeb q->write_ptr = 0; 904*a4128aadSBjoern A. Zeeb q->read_ptr = 0; 905*a4128aadSBjoern A. Zeeb 906*a4128aadSBjoern A. Zeeb return 0; 907*a4128aadSBjoern A. Zeeb } 908*a4128aadSBjoern A. Zeeb 909*a4128aadSBjoern A. Zeeb int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, 910*a4128aadSBjoern A. Zeeb int slots_num, bool cmd_queue) 911*a4128aadSBjoern A. Zeeb { 912*a4128aadSBjoern A. Zeeb u32 tfd_queue_max_size = 913*a4128aadSBjoern A. Zeeb trans->trans_cfg->base_params->max_tfd_queue_size; 914*a4128aadSBjoern A. Zeeb int ret; 915*a4128aadSBjoern A. Zeeb 916*a4128aadSBjoern A. Zeeb txq->need_update = false; 917*a4128aadSBjoern A. Zeeb 918*a4128aadSBjoern A. Zeeb /* max_tfd_queue_size must be power-of-two size, otherwise 919*a4128aadSBjoern A. Zeeb * iwl_txq_inc_wrap and iwl_txq_dec_wrap are broken. 920*a4128aadSBjoern A. Zeeb */ 921*a4128aadSBjoern A. Zeeb if (WARN_ONCE(tfd_queue_max_size & (tfd_queue_max_size - 1), 922*a4128aadSBjoern A. Zeeb "Max tfd queue size must be a power of two, but is %d", 923*a4128aadSBjoern A. Zeeb tfd_queue_max_size)) 924*a4128aadSBjoern A. Zeeb return -EINVAL; 925*a4128aadSBjoern A. Zeeb 926*a4128aadSBjoern A. Zeeb /* Initialize queue's high/low-water marks, and head/tail indexes */ 927*a4128aadSBjoern A. Zeeb ret = iwl_queue_init(txq, slots_num); 928*a4128aadSBjoern A. Zeeb if (ret) 929*a4128aadSBjoern A. Zeeb return ret; 930*a4128aadSBjoern A. Zeeb 931*a4128aadSBjoern A. Zeeb spin_lock_init(&txq->lock); 932*a4128aadSBjoern A. Zeeb spin_lock_init(&txq->reclaim_lock); 933*a4128aadSBjoern A. Zeeb 934*a4128aadSBjoern A. Zeeb if (cmd_queue) { 935*a4128aadSBjoern A. Zeeb #if defined(__linux__) 936*a4128aadSBjoern A. Zeeb static struct lock_class_key iwl_txq_cmd_queue_lock_class; 937*a4128aadSBjoern A. Zeeb 938*a4128aadSBjoern A. Zeeb lockdep_set_class(&txq->lock, &iwl_txq_cmd_queue_lock_class); 939*a4128aadSBjoern A. Zeeb #endif 940*a4128aadSBjoern A. Zeeb } 941*a4128aadSBjoern A. Zeeb 942*a4128aadSBjoern A. Zeeb __skb_queue_head_init(&txq->overflow_q); 943*a4128aadSBjoern A. Zeeb 944*a4128aadSBjoern A. Zeeb return 0; 945*a4128aadSBjoern A. Zeeb } 946*a4128aadSBjoern A. Zeeb 947bfcc09ddSBjoern A. Zeeb int iwl_pcie_tx_init(struct iwl_trans *trans) 948bfcc09ddSBjoern A. Zeeb { 949bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 950bfcc09ddSBjoern A. Zeeb int ret; 951bfcc09ddSBjoern A. Zeeb int txq_id, slots_num; 952bfcc09ddSBjoern A. Zeeb bool alloc = false; 953bfcc09ddSBjoern A. Zeeb 954bfcc09ddSBjoern A. Zeeb if (!trans_pcie->txq_memory) { 955bfcc09ddSBjoern A. Zeeb ret = iwl_pcie_tx_alloc(trans); 956bfcc09ddSBjoern A. Zeeb if (ret) 957bfcc09ddSBjoern A. Zeeb goto error; 958bfcc09ddSBjoern A. Zeeb alloc = true; 959bfcc09ddSBjoern A. Zeeb } 960bfcc09ddSBjoern A. Zeeb 961bfcc09ddSBjoern A. Zeeb spin_lock_bh(&trans_pcie->irq_lock); 962bfcc09ddSBjoern A. Zeeb 963bfcc09ddSBjoern A. Zeeb /* Turn off all Tx DMA fifos */ 964bfcc09ddSBjoern A. Zeeb iwl_scd_deactivate_fifos(trans); 965bfcc09ddSBjoern A. Zeeb 966bfcc09ddSBjoern A. Zeeb /* Tell NIC where to find the "keep warm" buffer */ 967bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG, 968bfcc09ddSBjoern A. Zeeb trans_pcie->kw.dma >> 4); 969bfcc09ddSBjoern A. Zeeb 970bfcc09ddSBjoern A. Zeeb spin_unlock_bh(&trans_pcie->irq_lock); 971bfcc09ddSBjoern A. Zeeb 972bfcc09ddSBjoern A. Zeeb /* Alloc and init all Tx queues, including the command queue (#4/#9) */ 973bfcc09ddSBjoern A. Zeeb for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues; 974bfcc09ddSBjoern A. Zeeb txq_id++) { 975*a4128aadSBjoern A. Zeeb bool cmd_queue = (txq_id == trans_pcie->txqs.cmd.q_id); 976bfcc09ddSBjoern A. Zeeb 977bfcc09ddSBjoern A. Zeeb if (cmd_queue) 978bfcc09ddSBjoern A. Zeeb slots_num = max_t(u32, IWL_CMD_QUEUE_SIZE, 979bfcc09ddSBjoern A. Zeeb trans->cfg->min_txq_size); 980bfcc09ddSBjoern A. Zeeb else 981bfcc09ddSBjoern A. Zeeb slots_num = max_t(u32, IWL_DEFAULT_QUEUE_SIZE, 982d9836fb4SBjoern A. Zeeb trans->cfg->min_ba_txq_size); 983*a4128aadSBjoern A. Zeeb ret = iwl_txq_init(trans, trans_pcie->txqs.txq[txq_id], slots_num, 984bfcc09ddSBjoern A. Zeeb cmd_queue); 985bfcc09ddSBjoern A. Zeeb if (ret) { 986bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); 987bfcc09ddSBjoern A. Zeeb goto error; 988bfcc09ddSBjoern A. Zeeb } 989bfcc09ddSBjoern A. Zeeb 990bfcc09ddSBjoern A. Zeeb /* 991bfcc09ddSBjoern A. Zeeb * Tell nic where to find circular buffer of TFDs for a 992bfcc09ddSBjoern A. Zeeb * given Tx queue, and enable the DMA channel used for that 993bfcc09ddSBjoern A. Zeeb * queue. 994bfcc09ddSBjoern A. Zeeb * Circular buffer (TFD queue in DRAM) physical base address 995bfcc09ddSBjoern A. Zeeb */ 996bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id), 997*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id]->dma_addr >> 8); 998bfcc09ddSBjoern A. Zeeb } 999bfcc09ddSBjoern A. Zeeb 1000bfcc09ddSBjoern A. Zeeb iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE); 1001bfcc09ddSBjoern A. Zeeb if (trans->trans_cfg->base_params->num_of_queues > 20) 1002bfcc09ddSBjoern A. Zeeb iwl_set_bits_prph(trans, SCD_GP_CTRL, 1003bfcc09ddSBjoern A. Zeeb SCD_GP_CTRL_ENABLE_31_QUEUES); 1004bfcc09ddSBjoern A. Zeeb 1005bfcc09ddSBjoern A. Zeeb return 0; 1006bfcc09ddSBjoern A. Zeeb error: 1007bfcc09ddSBjoern A. Zeeb /*Upon error, free only if we allocated something */ 1008bfcc09ddSBjoern A. Zeeb if (alloc) 1009bfcc09ddSBjoern A. Zeeb iwl_pcie_tx_free(trans); 1010bfcc09ddSBjoern A. Zeeb return ret; 1011bfcc09ddSBjoern A. Zeeb } 1012bfcc09ddSBjoern A. Zeeb 1013bfcc09ddSBjoern A. Zeeb static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, 1014bfcc09ddSBjoern A. Zeeb const struct iwl_host_cmd *cmd) 1015bfcc09ddSBjoern A. Zeeb { 1016bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1017bfcc09ddSBjoern A. Zeeb 1018bfcc09ddSBjoern A. Zeeb /* Make sure the NIC is still alive in the bus */ 1019bfcc09ddSBjoern A. Zeeb if (test_bit(STATUS_TRANS_DEAD, &trans->status)) 1020bfcc09ddSBjoern A. Zeeb return -ENODEV; 1021bfcc09ddSBjoern A. Zeeb 1022bfcc09ddSBjoern A. Zeeb if (!trans->trans_cfg->base_params->apmg_wake_up_wa) 1023bfcc09ddSBjoern A. Zeeb return 0; 1024bfcc09ddSBjoern A. Zeeb 1025bfcc09ddSBjoern A. Zeeb /* 1026bfcc09ddSBjoern A. Zeeb * wake up the NIC to make sure that the firmware will see the host 1027bfcc09ddSBjoern A. Zeeb * command - we will let the NIC sleep once all the host commands 1028bfcc09ddSBjoern A. Zeeb * returned. This needs to be done only on NICs that have 1029bfcc09ddSBjoern A. Zeeb * apmg_wake_up_wa set (see above.) 1030bfcc09ddSBjoern A. Zeeb */ 1031bfcc09ddSBjoern A. Zeeb if (!_iwl_trans_pcie_grab_nic_access(trans)) 1032bfcc09ddSBjoern A. Zeeb return -EIO; 1033bfcc09ddSBjoern A. Zeeb 1034bfcc09ddSBjoern A. Zeeb /* 1035bfcc09ddSBjoern A. Zeeb * In iwl_trans_grab_nic_access(), we've acquired the reg_lock. 1036bfcc09ddSBjoern A. Zeeb * There, we also returned immediately if cmd_hold_nic_awake is 1037bfcc09ddSBjoern A. Zeeb * already true, so it's OK to unconditionally set it to true. 1038bfcc09ddSBjoern A. Zeeb */ 1039bfcc09ddSBjoern A. Zeeb trans_pcie->cmd_hold_nic_awake = true; 1040bfcc09ddSBjoern A. Zeeb spin_unlock(&trans_pcie->reg_lock); 1041bfcc09ddSBjoern A. Zeeb 1042bfcc09ddSBjoern A. Zeeb return 0; 1043bfcc09ddSBjoern A. Zeeb } 1044bfcc09ddSBjoern A. Zeeb 1045*a4128aadSBjoern A. Zeeb static void iwl_txq_progress(struct iwl_txq *txq) 1046*a4128aadSBjoern A. Zeeb { 1047*a4128aadSBjoern A. Zeeb lockdep_assert_held(&txq->lock); 1048*a4128aadSBjoern A. Zeeb 1049*a4128aadSBjoern A. Zeeb if (!txq->wd_timeout) 1050*a4128aadSBjoern A. Zeeb return; 1051*a4128aadSBjoern A. Zeeb 1052*a4128aadSBjoern A. Zeeb /* 1053*a4128aadSBjoern A. Zeeb * station is asleep and we send data - that must 1054*a4128aadSBjoern A. Zeeb * be uAPSD or PS-Poll. Don't rearm the timer. 1055*a4128aadSBjoern A. Zeeb */ 1056*a4128aadSBjoern A. Zeeb if (txq->frozen) 1057*a4128aadSBjoern A. Zeeb return; 1058*a4128aadSBjoern A. Zeeb 1059*a4128aadSBjoern A. Zeeb /* 1060*a4128aadSBjoern A. Zeeb * if empty delete timer, otherwise move timer forward 1061*a4128aadSBjoern A. Zeeb * since we're making progress on this queue 1062*a4128aadSBjoern A. Zeeb */ 1063*a4128aadSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr) 1064*a4128aadSBjoern A. Zeeb del_timer(&txq->stuck_timer); 1065*a4128aadSBjoern A. Zeeb else 1066*a4128aadSBjoern A. Zeeb mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); 1067*a4128aadSBjoern A. Zeeb } 1068*a4128aadSBjoern A. Zeeb 1069*a4128aadSBjoern A. Zeeb static inline bool iwl_txq_used(const struct iwl_txq *q, int i, 1070*a4128aadSBjoern A. Zeeb int read_ptr, int write_ptr) 1071*a4128aadSBjoern A. Zeeb { 1072*a4128aadSBjoern A. Zeeb int index = iwl_txq_get_cmd_index(q, i); 1073*a4128aadSBjoern A. Zeeb int r = iwl_txq_get_cmd_index(q, read_ptr); 1074*a4128aadSBjoern A. Zeeb int w = iwl_txq_get_cmd_index(q, write_ptr); 1075*a4128aadSBjoern A. Zeeb 1076*a4128aadSBjoern A. Zeeb return w >= r ? 1077*a4128aadSBjoern A. Zeeb (index >= r && index < w) : 1078*a4128aadSBjoern A. Zeeb !(index < r && index >= w); 1079*a4128aadSBjoern A. Zeeb } 1080*a4128aadSBjoern A. Zeeb 1081bfcc09ddSBjoern A. Zeeb /* 1082bfcc09ddSBjoern A. Zeeb * iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd 1083bfcc09ddSBjoern A. Zeeb * 1084bfcc09ddSBjoern A. Zeeb * When FW advances 'R' index, all entries between old and new 'R' index 1085bfcc09ddSBjoern A. Zeeb * need to be reclaimed. As result, some free space forms. If there is 1086bfcc09ddSBjoern A. Zeeb * enough free space (> low mark), wake the stack that feeds us. 1087bfcc09ddSBjoern A. Zeeb */ 1088bfcc09ddSBjoern A. Zeeb static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) 1089bfcc09ddSBjoern A. Zeeb { 1090*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1091*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 1092bfcc09ddSBjoern A. Zeeb int nfreed = 0; 1093bfcc09ddSBjoern A. Zeeb u16 r; 1094bfcc09ddSBjoern A. Zeeb 1095bfcc09ddSBjoern A. Zeeb lockdep_assert_held(&txq->lock); 1096bfcc09ddSBjoern A. Zeeb 1097bfcc09ddSBjoern A. Zeeb idx = iwl_txq_get_cmd_index(txq, idx); 1098bfcc09ddSBjoern A. Zeeb r = iwl_txq_get_cmd_index(txq, txq->read_ptr); 1099bfcc09ddSBjoern A. Zeeb 1100bfcc09ddSBjoern A. Zeeb if (idx >= trans->trans_cfg->base_params->max_tfd_queue_size || 1101*a4128aadSBjoern A. Zeeb (!iwl_txq_used(txq, idx, txq->read_ptr, txq->write_ptr))) { 1102*a4128aadSBjoern A. Zeeb WARN_ONCE(test_bit(txq_id, trans_pcie->txqs.queue_used), 1103bfcc09ddSBjoern A. Zeeb "%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n", 1104bfcc09ddSBjoern A. Zeeb __func__, txq_id, idx, 1105bfcc09ddSBjoern A. Zeeb trans->trans_cfg->base_params->max_tfd_queue_size, 1106bfcc09ddSBjoern A. Zeeb txq->write_ptr, txq->read_ptr); 1107bfcc09ddSBjoern A. Zeeb return; 1108bfcc09ddSBjoern A. Zeeb } 1109bfcc09ddSBjoern A. Zeeb 1110bfcc09ddSBjoern A. Zeeb for (idx = iwl_txq_inc_wrap(trans, idx); r != idx; 1111bfcc09ddSBjoern A. Zeeb r = iwl_txq_inc_wrap(trans, r)) { 1112bfcc09ddSBjoern A. Zeeb txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr); 1113bfcc09ddSBjoern A. Zeeb 1114bfcc09ddSBjoern A. Zeeb if (nfreed++ > 0) { 1115bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", 1116bfcc09ddSBjoern A. Zeeb idx, txq->write_ptr, r); 1117bfcc09ddSBjoern A. Zeeb iwl_force_nmi(trans); 1118bfcc09ddSBjoern A. Zeeb } 1119bfcc09ddSBjoern A. Zeeb } 1120bfcc09ddSBjoern A. Zeeb 1121bfcc09ddSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr) 1122bfcc09ddSBjoern A. Zeeb iwl_pcie_clear_cmd_in_flight(trans); 1123bfcc09ddSBjoern A. Zeeb 1124bfcc09ddSBjoern A. Zeeb iwl_txq_progress(txq); 1125bfcc09ddSBjoern A. Zeeb } 1126bfcc09ddSBjoern A. Zeeb 1127bfcc09ddSBjoern A. Zeeb static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid, 1128bfcc09ddSBjoern A. Zeeb u16 txq_id) 1129bfcc09ddSBjoern A. Zeeb { 1130bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1131bfcc09ddSBjoern A. Zeeb u32 tbl_dw_addr; 1132bfcc09ddSBjoern A. Zeeb u32 tbl_dw; 1133bfcc09ddSBjoern A. Zeeb u16 scd_q2ratid; 1134bfcc09ddSBjoern A. Zeeb 1135bfcc09ddSBjoern A. Zeeb scd_q2ratid = ra_tid & SCD_QUEUE_RA_TID_MAP_RATID_MSK; 1136bfcc09ddSBjoern A. Zeeb 1137bfcc09ddSBjoern A. Zeeb tbl_dw_addr = trans_pcie->scd_base_addr + 1138bfcc09ddSBjoern A. Zeeb SCD_TRANS_TBL_OFFSET_QUEUE(txq_id); 1139bfcc09ddSBjoern A. Zeeb 1140bfcc09ddSBjoern A. Zeeb tbl_dw = iwl_trans_read_mem32(trans, tbl_dw_addr); 1141bfcc09ddSBjoern A. Zeeb 1142bfcc09ddSBjoern A. Zeeb if (txq_id & 0x1) 1143bfcc09ddSBjoern A. Zeeb tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); 1144bfcc09ddSBjoern A. Zeeb else 1145bfcc09ddSBjoern A. Zeeb tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); 1146bfcc09ddSBjoern A. Zeeb 1147bfcc09ddSBjoern A. Zeeb iwl_trans_write_mem32(trans, tbl_dw_addr, tbl_dw); 1148bfcc09ddSBjoern A. Zeeb 1149bfcc09ddSBjoern A. Zeeb return 0; 1150bfcc09ddSBjoern A. Zeeb } 1151bfcc09ddSBjoern A. Zeeb 1152bfcc09ddSBjoern A. Zeeb /* Receiver address (actually, Rx station's index into station table), 1153bfcc09ddSBjoern A. Zeeb * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ 1154bfcc09ddSBjoern A. Zeeb #define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) 1155bfcc09ddSBjoern A. Zeeb 1156bfcc09ddSBjoern A. Zeeb bool iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn, 1157bfcc09ddSBjoern A. Zeeb const struct iwl_trans_txq_scd_cfg *cfg, 1158bfcc09ddSBjoern A. Zeeb unsigned int wdg_timeout) 1159bfcc09ddSBjoern A. Zeeb { 1160bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1161*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 1162bfcc09ddSBjoern A. Zeeb int fifo = -1; 1163bfcc09ddSBjoern A. Zeeb bool scd_bug = false; 1164bfcc09ddSBjoern A. Zeeb 1165*a4128aadSBjoern A. Zeeb if (test_and_set_bit(txq_id, trans_pcie->txqs.queue_used)) 1166bfcc09ddSBjoern A. Zeeb WARN_ONCE(1, "queue %d already used - expect issues", txq_id); 1167bfcc09ddSBjoern A. Zeeb 1168bfcc09ddSBjoern A. Zeeb txq->wd_timeout = msecs_to_jiffies(wdg_timeout); 1169bfcc09ddSBjoern A. Zeeb 1170bfcc09ddSBjoern A. Zeeb if (cfg) { 1171bfcc09ddSBjoern A. Zeeb fifo = cfg->fifo; 1172bfcc09ddSBjoern A. Zeeb 1173bfcc09ddSBjoern A. Zeeb /* Disable the scheduler prior configuring the cmd queue */ 1174*a4128aadSBjoern A. Zeeb if (txq_id == trans_pcie->txqs.cmd.q_id && 1175bfcc09ddSBjoern A. Zeeb trans_pcie->scd_set_active) 1176bfcc09ddSBjoern A. Zeeb iwl_scd_enable_set_active(trans, 0); 1177bfcc09ddSBjoern A. Zeeb 1178bfcc09ddSBjoern A. Zeeb /* Stop this Tx queue before configuring it */ 1179bfcc09ddSBjoern A. Zeeb iwl_scd_txq_set_inactive(trans, txq_id); 1180bfcc09ddSBjoern A. Zeeb 1181bfcc09ddSBjoern A. Zeeb /* Set this queue as a chain-building queue unless it is CMD */ 1182*a4128aadSBjoern A. Zeeb if (txq_id != trans_pcie->txqs.cmd.q_id) 1183bfcc09ddSBjoern A. Zeeb iwl_scd_txq_set_chain(trans, txq_id); 1184bfcc09ddSBjoern A. Zeeb 1185bfcc09ddSBjoern A. Zeeb if (cfg->aggregate) { 1186bfcc09ddSBjoern A. Zeeb u16 ra_tid = BUILD_RAxTID(cfg->sta_id, cfg->tid); 1187bfcc09ddSBjoern A. Zeeb 1188bfcc09ddSBjoern A. Zeeb /* Map receiver-address / traffic-ID to this queue */ 1189bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_set_ratid_map(trans, ra_tid, txq_id); 1190bfcc09ddSBjoern A. Zeeb 1191bfcc09ddSBjoern A. Zeeb /* enable aggregations for the queue */ 1192bfcc09ddSBjoern A. Zeeb iwl_scd_txq_enable_agg(trans, txq_id); 1193bfcc09ddSBjoern A. Zeeb txq->ampdu = true; 1194bfcc09ddSBjoern A. Zeeb } else { 1195bfcc09ddSBjoern A. Zeeb /* 1196bfcc09ddSBjoern A. Zeeb * disable aggregations for the queue, this will also 1197bfcc09ddSBjoern A. Zeeb * make the ra_tid mapping configuration irrelevant 1198bfcc09ddSBjoern A. Zeeb * since it is now a non-AGG queue. 1199bfcc09ddSBjoern A. Zeeb */ 1200bfcc09ddSBjoern A. Zeeb iwl_scd_txq_disable_agg(trans, txq_id); 1201bfcc09ddSBjoern A. Zeeb 1202bfcc09ddSBjoern A. Zeeb ssn = txq->read_ptr; 1203bfcc09ddSBjoern A. Zeeb } 1204bfcc09ddSBjoern A. Zeeb } else { 1205bfcc09ddSBjoern A. Zeeb /* 1206bfcc09ddSBjoern A. Zeeb * If we need to move the SCD write pointer by steps of 1207bfcc09ddSBjoern A. Zeeb * 0x40, 0x80 or 0xc0, it gets stuck. Avoids this and let 1208bfcc09ddSBjoern A. Zeeb * the op_mode know by returning true later. 1209bfcc09ddSBjoern A. Zeeb * Do this only in case cfg is NULL since this trick can 1210bfcc09ddSBjoern A. Zeeb * be done only if we have DQA enabled which is true for mvm 1211bfcc09ddSBjoern A. Zeeb * only. And mvm never sets a cfg pointer. 1212bfcc09ddSBjoern A. Zeeb * This is really ugly, but this is the easiest way out for 1213bfcc09ddSBjoern A. Zeeb * this sad hardware issue. 1214bfcc09ddSBjoern A. Zeeb * This bug has been fixed on devices 9000 and up. 1215bfcc09ddSBjoern A. Zeeb */ 1216bfcc09ddSBjoern A. Zeeb scd_bug = !trans->trans_cfg->mq_rx_supported && 1217bfcc09ddSBjoern A. Zeeb !((ssn - txq->write_ptr) & 0x3f) && 1218bfcc09ddSBjoern A. Zeeb (ssn != txq->write_ptr); 1219bfcc09ddSBjoern A. Zeeb if (scd_bug) 1220bfcc09ddSBjoern A. Zeeb ssn++; 1221bfcc09ddSBjoern A. Zeeb } 1222bfcc09ddSBjoern A. Zeeb 1223bfcc09ddSBjoern A. Zeeb /* Place first TFD at index corresponding to start sequence number. 1224bfcc09ddSBjoern A. Zeeb * Assumes that ssn_idx is valid (!= 0xFFF) */ 1225bfcc09ddSBjoern A. Zeeb txq->read_ptr = (ssn & 0xff); 1226bfcc09ddSBjoern A. Zeeb txq->write_ptr = (ssn & 0xff); 1227bfcc09ddSBjoern A. Zeeb iwl_write_direct32(trans, HBUS_TARG_WRPTR, 1228bfcc09ddSBjoern A. Zeeb (ssn & 0xff) | (txq_id << 8)); 1229bfcc09ddSBjoern A. Zeeb 1230bfcc09ddSBjoern A. Zeeb if (cfg) { 1231bfcc09ddSBjoern A. Zeeb u8 frame_limit = cfg->frame_limit; 1232bfcc09ddSBjoern A. Zeeb 1233bfcc09ddSBjoern A. Zeeb iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn); 1234bfcc09ddSBjoern A. Zeeb 1235bfcc09ddSBjoern A. Zeeb /* Set up Tx window size and frame limit for this queue */ 1236bfcc09ddSBjoern A. Zeeb iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr + 1237bfcc09ddSBjoern A. Zeeb SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); 1238bfcc09ddSBjoern A. Zeeb iwl_trans_write_mem32(trans, 1239bfcc09ddSBjoern A. Zeeb trans_pcie->scd_base_addr + 1240bfcc09ddSBjoern A. Zeeb SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), 1241bfcc09ddSBjoern A. Zeeb SCD_QUEUE_CTX_REG2_VAL(WIN_SIZE, frame_limit) | 1242bfcc09ddSBjoern A. Zeeb SCD_QUEUE_CTX_REG2_VAL(FRAME_LIMIT, frame_limit)); 1243bfcc09ddSBjoern A. Zeeb 1244bfcc09ddSBjoern A. Zeeb /* Set up status area in SRAM, map to Tx DMA/FIFO, activate */ 1245bfcc09ddSBjoern A. Zeeb iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), 1246bfcc09ddSBjoern A. Zeeb (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE) | 1247bfcc09ddSBjoern A. Zeeb (cfg->fifo << SCD_QUEUE_STTS_REG_POS_TXF) | 1248bfcc09ddSBjoern A. Zeeb (1 << SCD_QUEUE_STTS_REG_POS_WSL) | 1249bfcc09ddSBjoern A. Zeeb SCD_QUEUE_STTS_REG_MSK); 1250bfcc09ddSBjoern A. Zeeb 1251bfcc09ddSBjoern A. Zeeb /* enable the scheduler for this queue (only) */ 1252*a4128aadSBjoern A. Zeeb if (txq_id == trans_pcie->txqs.cmd.q_id && 1253bfcc09ddSBjoern A. Zeeb trans_pcie->scd_set_active) 1254bfcc09ddSBjoern A. Zeeb iwl_scd_enable_set_active(trans, BIT(txq_id)); 1255bfcc09ddSBjoern A. Zeeb 1256bfcc09ddSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, 1257bfcc09ddSBjoern A. Zeeb "Activate queue %d on FIFO %d WrPtr: %d\n", 1258bfcc09ddSBjoern A. Zeeb txq_id, fifo, ssn & 0xff); 1259bfcc09ddSBjoern A. Zeeb } else { 1260bfcc09ddSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, 1261bfcc09ddSBjoern A. Zeeb "Activate queue %d WrPtr: %d\n", 1262bfcc09ddSBjoern A. Zeeb txq_id, ssn & 0xff); 1263bfcc09ddSBjoern A. Zeeb } 1264bfcc09ddSBjoern A. Zeeb 1265bfcc09ddSBjoern A. Zeeb return scd_bug; 1266bfcc09ddSBjoern A. Zeeb } 1267bfcc09ddSBjoern A. Zeeb 1268bfcc09ddSBjoern A. Zeeb void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id, 1269bfcc09ddSBjoern A. Zeeb bool shared_mode) 1270bfcc09ddSBjoern A. Zeeb { 1271*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1272*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 1273bfcc09ddSBjoern A. Zeeb 1274bfcc09ddSBjoern A. Zeeb txq->ampdu = !shared_mode; 1275bfcc09ddSBjoern A. Zeeb } 1276bfcc09ddSBjoern A. Zeeb 1277bfcc09ddSBjoern A. Zeeb void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, 1278bfcc09ddSBjoern A. Zeeb bool configure_scd) 1279bfcc09ddSBjoern A. Zeeb { 1280bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1281bfcc09ddSBjoern A. Zeeb u32 stts_addr = trans_pcie->scd_base_addr + 1282bfcc09ddSBjoern A. Zeeb SCD_TX_STTS_QUEUE_OFFSET(txq_id); 1283bfcc09ddSBjoern A. Zeeb static const u32 zero_val[4] = {}; 1284bfcc09ddSBjoern A. Zeeb 1285*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id]->frozen_expiry_remainder = 0; 1286*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id]->frozen = false; 1287bfcc09ddSBjoern A. Zeeb 1288bfcc09ddSBjoern A. Zeeb /* 1289bfcc09ddSBjoern A. Zeeb * Upon HW Rfkill - we stop the device, and then stop the queues 1290bfcc09ddSBjoern A. Zeeb * in the op_mode. Just for the sake of the simplicity of the op_mode, 1291bfcc09ddSBjoern A. Zeeb * allow the op_mode to call txq_disable after it already called 1292bfcc09ddSBjoern A. Zeeb * stop_device. 1293bfcc09ddSBjoern A. Zeeb */ 1294*a4128aadSBjoern A. Zeeb if (!test_and_clear_bit(txq_id, trans_pcie->txqs.queue_used)) { 1295bfcc09ddSBjoern A. Zeeb WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status), 1296bfcc09ddSBjoern A. Zeeb "queue %d not used", txq_id); 1297bfcc09ddSBjoern A. Zeeb return; 1298bfcc09ddSBjoern A. Zeeb } 1299bfcc09ddSBjoern A. Zeeb 1300bfcc09ddSBjoern A. Zeeb if (configure_scd) { 1301bfcc09ddSBjoern A. Zeeb iwl_scd_txq_set_inactive(trans, txq_id); 1302bfcc09ddSBjoern A. Zeeb 1303d9836fb4SBjoern A. Zeeb iwl_trans_write_mem(trans, stts_addr, (const void *)zero_val, 1304bfcc09ddSBjoern A. Zeeb ARRAY_SIZE(zero_val)); 1305bfcc09ddSBjoern A. Zeeb } 1306bfcc09ddSBjoern A. Zeeb 1307bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_unmap(trans, txq_id); 1308*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id]->ampdu = false; 1309bfcc09ddSBjoern A. Zeeb 1310bfcc09ddSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); 1311bfcc09ddSBjoern A. Zeeb } 1312bfcc09ddSBjoern A. Zeeb 1313bfcc09ddSBjoern A. Zeeb /*************** HOST COMMAND QUEUE FUNCTIONS *****/ 1314bfcc09ddSBjoern A. Zeeb 1315*a4128aadSBjoern A. Zeeb static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block) 1316*a4128aadSBjoern A. Zeeb { 1317*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1318*a4128aadSBjoern A. Zeeb int i; 1319*a4128aadSBjoern A. Zeeb 1320*a4128aadSBjoern A. Zeeb for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) { 1321*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[i]; 1322*a4128aadSBjoern A. Zeeb 1323*a4128aadSBjoern A. Zeeb if (i == trans_pcie->txqs.cmd.q_id) 1324*a4128aadSBjoern A. Zeeb continue; 1325*a4128aadSBjoern A. Zeeb 1326*a4128aadSBjoern A. Zeeb /* we skip the command queue (obviously) so it's OK to nest */ 1327*a4128aadSBjoern A. Zeeb spin_lock_nested(&txq->lock, 1); 1328*a4128aadSBjoern A. Zeeb 1329*a4128aadSBjoern A. Zeeb if (!block && !(WARN_ON_ONCE(!txq->block))) { 1330*a4128aadSBjoern A. Zeeb txq->block--; 1331*a4128aadSBjoern A. Zeeb if (!txq->block) { 1332*a4128aadSBjoern A. Zeeb iwl_write32(trans, HBUS_TARG_WRPTR, 1333*a4128aadSBjoern A. Zeeb txq->write_ptr | (i << 8)); 1334*a4128aadSBjoern A. Zeeb } 1335*a4128aadSBjoern A. Zeeb } else if (block) { 1336*a4128aadSBjoern A. Zeeb txq->block++; 1337*a4128aadSBjoern A. Zeeb } 1338*a4128aadSBjoern A. Zeeb 1339*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 1340*a4128aadSBjoern A. Zeeb } 1341*a4128aadSBjoern A. Zeeb } 1342*a4128aadSBjoern A. Zeeb 1343bfcc09ddSBjoern A. Zeeb /* 1344bfcc09ddSBjoern A. Zeeb * iwl_pcie_enqueue_hcmd - enqueue a uCode command 1345bfcc09ddSBjoern A. Zeeb * @priv: device private data point 1346bfcc09ddSBjoern A. Zeeb * @cmd: a pointer to the ucode command structure 1347bfcc09ddSBjoern A. Zeeb * 1348bfcc09ddSBjoern A. Zeeb * The function returns < 0 values to indicate the operation 1349bfcc09ddSBjoern A. Zeeb * failed. On success, it returns the index (>= 0) of command in the 1350bfcc09ddSBjoern A. Zeeb * command queue. 1351bfcc09ddSBjoern A. Zeeb */ 1352bfcc09ddSBjoern A. Zeeb int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, 1353bfcc09ddSBjoern A. Zeeb struct iwl_host_cmd *cmd) 1354bfcc09ddSBjoern A. Zeeb { 1355*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1356*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id]; 1357bfcc09ddSBjoern A. Zeeb struct iwl_device_cmd *out_cmd; 1358bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *out_meta; 1359bfcc09ddSBjoern A. Zeeb void *dup_buf = NULL; 1360bfcc09ddSBjoern A. Zeeb dma_addr_t phys_addr; 1361bfcc09ddSBjoern A. Zeeb int idx; 1362bfcc09ddSBjoern A. Zeeb u16 copy_size, cmd_size, tb0_size; 1363bfcc09ddSBjoern A. Zeeb bool had_nocopy = false; 1364bfcc09ddSBjoern A. Zeeb u8 group_id = iwl_cmd_groupid(cmd->id); 1365bfcc09ddSBjoern A. Zeeb int i, ret; 1366bfcc09ddSBjoern A. Zeeb u32 cmd_pos; 1367bfcc09ddSBjoern A. Zeeb const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; 1368bfcc09ddSBjoern A. Zeeb u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; 1369bfcc09ddSBjoern A. Zeeb unsigned long flags; 1370bfcc09ddSBjoern A. Zeeb 1371bfcc09ddSBjoern A. Zeeb if (WARN(!trans->wide_cmd_header && 1372bfcc09ddSBjoern A. Zeeb group_id > IWL_ALWAYS_LONG_GROUP, 1373bfcc09ddSBjoern A. Zeeb "unsupported wide command %#x\n", cmd->id)) 1374bfcc09ddSBjoern A. Zeeb return -EINVAL; 1375bfcc09ddSBjoern A. Zeeb 1376bfcc09ddSBjoern A. Zeeb if (group_id != 0) { 1377bfcc09ddSBjoern A. Zeeb copy_size = sizeof(struct iwl_cmd_header_wide); 1378bfcc09ddSBjoern A. Zeeb cmd_size = sizeof(struct iwl_cmd_header_wide); 1379bfcc09ddSBjoern A. Zeeb } else { 1380bfcc09ddSBjoern A. Zeeb copy_size = sizeof(struct iwl_cmd_header); 1381bfcc09ddSBjoern A. Zeeb cmd_size = sizeof(struct iwl_cmd_header); 1382bfcc09ddSBjoern A. Zeeb } 1383bfcc09ddSBjoern A. Zeeb 1384bfcc09ddSBjoern A. Zeeb /* need one for the header if the first is NOCOPY */ 1385bfcc09ddSBjoern A. Zeeb BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1); 1386bfcc09ddSBjoern A. Zeeb 1387bfcc09ddSBjoern A. Zeeb for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { 1388bfcc09ddSBjoern A. Zeeb cmddata[i] = cmd->data[i]; 1389bfcc09ddSBjoern A. Zeeb cmdlen[i] = cmd->len[i]; 1390bfcc09ddSBjoern A. Zeeb 1391bfcc09ddSBjoern A. Zeeb if (!cmd->len[i]) 1392bfcc09ddSBjoern A. Zeeb continue; 1393bfcc09ddSBjoern A. Zeeb 1394bfcc09ddSBjoern A. Zeeb /* need at least IWL_FIRST_TB_SIZE copied */ 1395bfcc09ddSBjoern A. Zeeb if (copy_size < IWL_FIRST_TB_SIZE) { 1396bfcc09ddSBjoern A. Zeeb int copy = IWL_FIRST_TB_SIZE - copy_size; 1397bfcc09ddSBjoern A. Zeeb 1398bfcc09ddSBjoern A. Zeeb if (copy > cmdlen[i]) 1399bfcc09ddSBjoern A. Zeeb copy = cmdlen[i]; 1400bfcc09ddSBjoern A. Zeeb cmdlen[i] -= copy; 1401bfcc09ddSBjoern A. Zeeb cmddata[i] += copy; 1402bfcc09ddSBjoern A. Zeeb copy_size += copy; 1403bfcc09ddSBjoern A. Zeeb } 1404bfcc09ddSBjoern A. Zeeb 1405bfcc09ddSBjoern A. Zeeb if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { 1406bfcc09ddSBjoern A. Zeeb had_nocopy = true; 1407bfcc09ddSBjoern A. Zeeb if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { 1408bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1409bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1410bfcc09ddSBjoern A. Zeeb } 1411bfcc09ddSBjoern A. Zeeb } else if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) { 1412bfcc09ddSBjoern A. Zeeb /* 1413bfcc09ddSBjoern A. Zeeb * This is also a chunk that isn't copied 1414bfcc09ddSBjoern A. Zeeb * to the static buffer so set had_nocopy. 1415bfcc09ddSBjoern A. Zeeb */ 1416bfcc09ddSBjoern A. Zeeb had_nocopy = true; 1417bfcc09ddSBjoern A. Zeeb 1418bfcc09ddSBjoern A. Zeeb /* only allowed once */ 1419bfcc09ddSBjoern A. Zeeb if (WARN_ON(dup_buf)) { 1420bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1421bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1422bfcc09ddSBjoern A. Zeeb } 1423bfcc09ddSBjoern A. Zeeb 1424bfcc09ddSBjoern A. Zeeb dup_buf = kmemdup(cmddata[i], cmdlen[i], 1425bfcc09ddSBjoern A. Zeeb GFP_ATOMIC); 1426bfcc09ddSBjoern A. Zeeb if (!dup_buf) 1427bfcc09ddSBjoern A. Zeeb return -ENOMEM; 1428bfcc09ddSBjoern A. Zeeb } else { 1429bfcc09ddSBjoern A. Zeeb /* NOCOPY must not be followed by normal! */ 1430bfcc09ddSBjoern A. Zeeb if (WARN_ON(had_nocopy)) { 1431bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1432bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1433bfcc09ddSBjoern A. Zeeb } 1434bfcc09ddSBjoern A. Zeeb copy_size += cmdlen[i]; 1435bfcc09ddSBjoern A. Zeeb } 1436bfcc09ddSBjoern A. Zeeb cmd_size += cmd->len[i]; 1437bfcc09ddSBjoern A. Zeeb } 1438bfcc09ddSBjoern A. Zeeb 1439bfcc09ddSBjoern A. Zeeb /* 1440bfcc09ddSBjoern A. Zeeb * If any of the command structures end up being larger than 1441bfcc09ddSBjoern A. Zeeb * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically 1442bfcc09ddSBjoern A. Zeeb * allocated into separate TFDs, then we will need to 1443bfcc09ddSBjoern A. Zeeb * increase the size of the buffers. 1444bfcc09ddSBjoern A. Zeeb */ 1445bfcc09ddSBjoern A. Zeeb if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, 1446bfcc09ddSBjoern A. Zeeb "Command %s (%#x) is too large (%d bytes)\n", 1447bfcc09ddSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd->id), 1448bfcc09ddSBjoern A. Zeeb cmd->id, copy_size)) { 1449bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1450bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1451bfcc09ddSBjoern A. Zeeb } 1452bfcc09ddSBjoern A. Zeeb 1453bfcc09ddSBjoern A. Zeeb spin_lock_irqsave(&txq->lock, flags); 1454bfcc09ddSBjoern A. Zeeb 1455bfcc09ddSBjoern A. Zeeb if (iwl_txq_space(trans, txq) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 1456bfcc09ddSBjoern A. Zeeb spin_unlock_irqrestore(&txq->lock, flags); 1457bfcc09ddSBjoern A. Zeeb 1458bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "No space in command queue\n"); 1459bfcc09ddSBjoern A. Zeeb iwl_op_mode_cmd_queue_full(trans->op_mode); 1460bfcc09ddSBjoern A. Zeeb idx = -ENOSPC; 1461bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1462bfcc09ddSBjoern A. Zeeb } 1463bfcc09ddSBjoern A. Zeeb 1464bfcc09ddSBjoern A. Zeeb idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 1465bfcc09ddSBjoern A. Zeeb out_cmd = txq->entries[idx].cmd; 1466bfcc09ddSBjoern A. Zeeb out_meta = &txq->entries[idx].meta; 1467bfcc09ddSBjoern A. Zeeb 1468*a4128aadSBjoern A. Zeeb /* re-initialize, this also marks the SG list as unused */ 1469*a4128aadSBjoern A. Zeeb memset(out_meta, 0, sizeof(*out_meta)); 1470bfcc09ddSBjoern A. Zeeb if (cmd->flags & CMD_WANT_SKB) 1471bfcc09ddSBjoern A. Zeeb out_meta->source = cmd; 1472bfcc09ddSBjoern A. Zeeb 1473bfcc09ddSBjoern A. Zeeb /* set up the header */ 1474bfcc09ddSBjoern A. Zeeb if (group_id != 0) { 1475bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.cmd = iwl_cmd_opcode(cmd->id); 1476bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.group_id = group_id; 1477bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.version = iwl_cmd_version(cmd->id); 1478bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.length = 1479bfcc09ddSBjoern A. Zeeb cpu_to_le16(cmd_size - 1480bfcc09ddSBjoern A. Zeeb sizeof(struct iwl_cmd_header_wide)); 1481bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.reserved = 0; 1482bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.sequence = 1483*a4128aadSBjoern A. Zeeb cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->txqs.cmd.q_id) | 1484bfcc09ddSBjoern A. Zeeb INDEX_TO_SEQ(txq->write_ptr)); 1485bfcc09ddSBjoern A. Zeeb 1486bfcc09ddSBjoern A. Zeeb cmd_pos = sizeof(struct iwl_cmd_header_wide); 1487bfcc09ddSBjoern A. Zeeb copy_size = sizeof(struct iwl_cmd_header_wide); 1488bfcc09ddSBjoern A. Zeeb } else { 1489bfcc09ddSBjoern A. Zeeb out_cmd->hdr.cmd = iwl_cmd_opcode(cmd->id); 1490bfcc09ddSBjoern A. Zeeb out_cmd->hdr.sequence = 1491*a4128aadSBjoern A. Zeeb cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->txqs.cmd.q_id) | 1492bfcc09ddSBjoern A. Zeeb INDEX_TO_SEQ(txq->write_ptr)); 1493bfcc09ddSBjoern A. Zeeb out_cmd->hdr.group_id = 0; 1494bfcc09ddSBjoern A. Zeeb 1495bfcc09ddSBjoern A. Zeeb cmd_pos = sizeof(struct iwl_cmd_header); 1496bfcc09ddSBjoern A. Zeeb copy_size = sizeof(struct iwl_cmd_header); 1497bfcc09ddSBjoern A. Zeeb } 1498bfcc09ddSBjoern A. Zeeb 1499bfcc09ddSBjoern A. Zeeb /* and copy the data that needs to be copied */ 1500bfcc09ddSBjoern A. Zeeb for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { 1501bfcc09ddSBjoern A. Zeeb int copy; 1502bfcc09ddSBjoern A. Zeeb 1503bfcc09ddSBjoern A. Zeeb if (!cmd->len[i]) 1504bfcc09ddSBjoern A. Zeeb continue; 1505bfcc09ddSBjoern A. Zeeb 1506bfcc09ddSBjoern A. Zeeb /* copy everything if not nocopy/dup */ 1507bfcc09ddSBjoern A. Zeeb if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | 1508bfcc09ddSBjoern A. Zeeb IWL_HCMD_DFL_DUP))) { 1509bfcc09ddSBjoern A. Zeeb copy = cmd->len[i]; 1510bfcc09ddSBjoern A. Zeeb 1511bfcc09ddSBjoern A. Zeeb memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); 1512bfcc09ddSBjoern A. Zeeb cmd_pos += copy; 1513bfcc09ddSBjoern A. Zeeb copy_size += copy; 1514bfcc09ddSBjoern A. Zeeb continue; 1515bfcc09ddSBjoern A. Zeeb } 1516bfcc09ddSBjoern A. Zeeb 1517bfcc09ddSBjoern A. Zeeb /* 1518bfcc09ddSBjoern A. Zeeb * Otherwise we need at least IWL_FIRST_TB_SIZE copied 1519bfcc09ddSBjoern A. Zeeb * in total (for bi-directional DMA), but copy up to what 1520bfcc09ddSBjoern A. Zeeb * we can fit into the payload for debug dump purposes. 1521bfcc09ddSBjoern A. Zeeb */ 1522bfcc09ddSBjoern A. Zeeb copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]); 1523bfcc09ddSBjoern A. Zeeb 1524bfcc09ddSBjoern A. Zeeb memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); 1525bfcc09ddSBjoern A. Zeeb cmd_pos += copy; 1526bfcc09ddSBjoern A. Zeeb 1527bfcc09ddSBjoern A. Zeeb /* However, treat copy_size the proper way, we need it below */ 1528bfcc09ddSBjoern A. Zeeb if (copy_size < IWL_FIRST_TB_SIZE) { 1529bfcc09ddSBjoern A. Zeeb copy = IWL_FIRST_TB_SIZE - copy_size; 1530bfcc09ddSBjoern A. Zeeb 1531bfcc09ddSBjoern A. Zeeb if (copy > cmd->len[i]) 1532bfcc09ddSBjoern A. Zeeb copy = cmd->len[i]; 1533bfcc09ddSBjoern A. Zeeb copy_size += copy; 1534bfcc09ddSBjoern A. Zeeb } 1535bfcc09ddSBjoern A. Zeeb } 1536bfcc09ddSBjoern A. Zeeb 1537bfcc09ddSBjoern A. Zeeb IWL_DEBUG_HC(trans, 1538bfcc09ddSBjoern A. Zeeb "Sending command %s (%.2x.%.2x), seq: 0x%04X, %d bytes at %d[%d]:%d\n", 1539bfcc09ddSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd->id), 1540bfcc09ddSBjoern A. Zeeb group_id, out_cmd->hdr.cmd, 1541bfcc09ddSBjoern A. Zeeb le16_to_cpu(out_cmd->hdr.sequence), 1542*a4128aadSBjoern A. Zeeb cmd_size, txq->write_ptr, idx, trans_pcie->txqs.cmd.q_id); 1543bfcc09ddSBjoern A. Zeeb 1544bfcc09ddSBjoern A. Zeeb /* start the TFD with the minimum copy bytes */ 1545bfcc09ddSBjoern A. Zeeb tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE); 1546bfcc09ddSBjoern A. Zeeb memcpy(&txq->first_tb_bufs[idx], &out_cmd->hdr, tb0_size); 1547bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, 1548bfcc09ddSBjoern A. Zeeb iwl_txq_get_first_tb_dma(txq, idx), 1549bfcc09ddSBjoern A. Zeeb tb0_size, true); 1550bfcc09ddSBjoern A. Zeeb 1551bfcc09ddSBjoern A. Zeeb /* map first command fragment, if any remains */ 1552bfcc09ddSBjoern A. Zeeb if (copy_size > tb0_size) { 1553bfcc09ddSBjoern A. Zeeb phys_addr = dma_map_single(trans->dev, 1554bfcc09ddSBjoern A. Zeeb ((u8 *)&out_cmd->hdr) + tb0_size, 1555bfcc09ddSBjoern A. Zeeb copy_size - tb0_size, 1556bfcc09ddSBjoern A. Zeeb DMA_TO_DEVICE); 1557bfcc09ddSBjoern A. Zeeb if (dma_mapping_error(trans->dev, phys_addr)) { 1558bfcc09ddSBjoern A. Zeeb iwl_txq_gen1_tfd_unmap(trans, out_meta, txq, 1559bfcc09ddSBjoern A. Zeeb txq->write_ptr); 1560bfcc09ddSBjoern A. Zeeb idx = -ENOMEM; 1561bfcc09ddSBjoern A. Zeeb goto out; 1562bfcc09ddSBjoern A. Zeeb } 1563bfcc09ddSBjoern A. Zeeb 1564bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, phys_addr, 1565bfcc09ddSBjoern A. Zeeb copy_size - tb0_size, false); 1566bfcc09ddSBjoern A. Zeeb } 1567bfcc09ddSBjoern A. Zeeb 1568bfcc09ddSBjoern A. Zeeb /* map the remaining (adjusted) nocopy/dup fragments */ 1569bfcc09ddSBjoern A. Zeeb for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { 1570bfcc09ddSBjoern A. Zeeb void *data = (void *)(uintptr_t)cmddata[i]; 1571bfcc09ddSBjoern A. Zeeb 1572bfcc09ddSBjoern A. Zeeb if (!cmdlen[i]) 1573bfcc09ddSBjoern A. Zeeb continue; 1574bfcc09ddSBjoern A. Zeeb if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | 1575bfcc09ddSBjoern A. Zeeb IWL_HCMD_DFL_DUP))) 1576bfcc09ddSBjoern A. Zeeb continue; 1577bfcc09ddSBjoern A. Zeeb if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) 1578bfcc09ddSBjoern A. Zeeb data = dup_buf; 1579bfcc09ddSBjoern A. Zeeb phys_addr = dma_map_single(trans->dev, data, 1580bfcc09ddSBjoern A. Zeeb cmdlen[i], DMA_TO_DEVICE); 1581bfcc09ddSBjoern A. Zeeb if (dma_mapping_error(trans->dev, phys_addr)) { 1582bfcc09ddSBjoern A. Zeeb iwl_txq_gen1_tfd_unmap(trans, out_meta, txq, 1583bfcc09ddSBjoern A. Zeeb txq->write_ptr); 1584bfcc09ddSBjoern A. Zeeb idx = -ENOMEM; 1585bfcc09ddSBjoern A. Zeeb goto out; 1586bfcc09ddSBjoern A. Zeeb } 1587bfcc09ddSBjoern A. Zeeb 1588bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], false); 1589bfcc09ddSBjoern A. Zeeb } 1590bfcc09ddSBjoern A. Zeeb 1591bfcc09ddSBjoern A. Zeeb BUILD_BUG_ON(IWL_TFH_NUM_TBS > sizeof(out_meta->tbs) * BITS_PER_BYTE); 1592bfcc09ddSBjoern A. Zeeb out_meta->flags = cmd->flags; 1593bfcc09ddSBjoern A. Zeeb if (WARN_ON_ONCE(txq->entries[idx].free_buf)) 1594bfcc09ddSBjoern A. Zeeb kfree_sensitive(txq->entries[idx].free_buf); 1595bfcc09ddSBjoern A. Zeeb txq->entries[idx].free_buf = dup_buf; 1596bfcc09ddSBjoern A. Zeeb 1597bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr_wide); 1598bfcc09ddSBjoern A. Zeeb 1599bfcc09ddSBjoern A. Zeeb /* start timer if queue currently empty */ 1600bfcc09ddSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr && txq->wd_timeout) 1601bfcc09ddSBjoern A. Zeeb mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); 1602bfcc09ddSBjoern A. Zeeb 1603bfcc09ddSBjoern A. Zeeb ret = iwl_pcie_set_cmd_in_flight(trans, cmd); 1604bfcc09ddSBjoern A. Zeeb if (ret < 0) { 1605bfcc09ddSBjoern A. Zeeb idx = ret; 1606bfcc09ddSBjoern A. Zeeb goto out; 1607bfcc09ddSBjoern A. Zeeb } 1608bfcc09ddSBjoern A. Zeeb 1609*a4128aadSBjoern A. Zeeb if (cmd->flags & CMD_BLOCK_TXQS) 1610*a4128aadSBjoern A. Zeeb iwl_trans_pcie_block_txq_ptrs(trans, true); 1611*a4128aadSBjoern A. Zeeb 1612bfcc09ddSBjoern A. Zeeb /* Increment and update queue's write index */ 1613bfcc09ddSBjoern A. Zeeb txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr); 1614bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_inc_wr_ptr(trans, txq); 1615bfcc09ddSBjoern A. Zeeb 1616bfcc09ddSBjoern A. Zeeb out: 1617bfcc09ddSBjoern A. Zeeb spin_unlock_irqrestore(&txq->lock, flags); 1618bfcc09ddSBjoern A. Zeeb free_dup_buf: 1619bfcc09ddSBjoern A. Zeeb if (idx < 0) 1620bfcc09ddSBjoern A. Zeeb kfree(dup_buf); 1621bfcc09ddSBjoern A. Zeeb return idx; 1622bfcc09ddSBjoern A. Zeeb } 1623bfcc09ddSBjoern A. Zeeb 1624bfcc09ddSBjoern A. Zeeb /* 1625bfcc09ddSBjoern A. Zeeb * iwl_pcie_hcmd_complete - Pull unused buffers off the queue and reclaim them 1626bfcc09ddSBjoern A. Zeeb * @rxb: Rx buffer to reclaim 1627bfcc09ddSBjoern A. Zeeb */ 1628bfcc09ddSBjoern A. Zeeb void iwl_pcie_hcmd_complete(struct iwl_trans *trans, 1629bfcc09ddSBjoern A. Zeeb struct iwl_rx_cmd_buffer *rxb) 1630bfcc09ddSBjoern A. Zeeb { 1631bfcc09ddSBjoern A. Zeeb struct iwl_rx_packet *pkt = rxb_addr(rxb); 1632bfcc09ddSBjoern A. Zeeb u16 sequence = le16_to_cpu(pkt->hdr.sequence); 1633bfcc09ddSBjoern A. Zeeb u8 group_id; 1634bfcc09ddSBjoern A. Zeeb u32 cmd_id; 1635bfcc09ddSBjoern A. Zeeb int txq_id = SEQ_TO_QUEUE(sequence); 1636bfcc09ddSBjoern A. Zeeb int index = SEQ_TO_INDEX(sequence); 1637bfcc09ddSBjoern A. Zeeb int cmd_index; 1638bfcc09ddSBjoern A. Zeeb struct iwl_device_cmd *cmd; 1639bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *meta; 1640bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1641*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id]; 1642bfcc09ddSBjoern A. Zeeb 1643bfcc09ddSBjoern A. Zeeb /* If a Tx command is being handled and it isn't in the actual 1644bfcc09ddSBjoern A. Zeeb * command queue then there a command routing bug has been introduced 1645bfcc09ddSBjoern A. Zeeb * in the queue management code. */ 1646*a4128aadSBjoern A. Zeeb if (WARN(txq_id != trans_pcie->txqs.cmd.q_id, 1647bfcc09ddSBjoern A. Zeeb "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", 1648*a4128aadSBjoern A. Zeeb txq_id, trans_pcie->txqs.cmd.q_id, sequence, txq->read_ptr, 1649bfcc09ddSBjoern A. Zeeb txq->write_ptr)) { 1650bfcc09ddSBjoern A. Zeeb iwl_print_hex_error(trans, pkt, 32); 1651bfcc09ddSBjoern A. Zeeb return; 1652bfcc09ddSBjoern A. Zeeb } 1653bfcc09ddSBjoern A. Zeeb 1654bfcc09ddSBjoern A. Zeeb spin_lock_bh(&txq->lock); 1655bfcc09ddSBjoern A. Zeeb 1656bfcc09ddSBjoern A. Zeeb cmd_index = iwl_txq_get_cmd_index(txq, index); 1657bfcc09ddSBjoern A. Zeeb cmd = txq->entries[cmd_index].cmd; 1658bfcc09ddSBjoern A. Zeeb meta = &txq->entries[cmd_index].meta; 1659bfcc09ddSBjoern A. Zeeb group_id = cmd->hdr.group_id; 1660d9836fb4SBjoern A. Zeeb cmd_id = WIDE_ID(group_id, cmd->hdr.cmd); 1661bfcc09ddSBjoern A. Zeeb 1662*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->gen2) 1663*a4128aadSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, meta, 1664*a4128aadSBjoern A. Zeeb iwl_txq_get_tfd(trans, txq, index)); 1665*a4128aadSBjoern A. Zeeb else 1666bfcc09ddSBjoern A. Zeeb iwl_txq_gen1_tfd_unmap(trans, meta, txq, index); 1667bfcc09ddSBjoern A. Zeeb 1668bfcc09ddSBjoern A. Zeeb /* Input error checking is done when commands are added to queue. */ 1669bfcc09ddSBjoern A. Zeeb if (meta->flags & CMD_WANT_SKB) { 1670bfcc09ddSBjoern A. Zeeb struct page *p = rxb_steal_page(rxb); 1671bfcc09ddSBjoern A. Zeeb 1672bfcc09ddSBjoern A. Zeeb meta->source->resp_pkt = pkt; 1673bfcc09ddSBjoern A. Zeeb #if defined(__linux__) 1674bfcc09ddSBjoern A. Zeeb meta->source->_rx_page_addr = (unsigned long)page_address(p); 1675bfcc09ddSBjoern A. Zeeb #elif defined(__FreeBSD__) 1676bfcc09ddSBjoern A. Zeeb meta->source->_page = p; 1677bfcc09ddSBjoern A. Zeeb #endif 1678bfcc09ddSBjoern A. Zeeb meta->source->_rx_page_order = trans_pcie->rx_page_order; 1679bfcc09ddSBjoern A. Zeeb } 1680bfcc09ddSBjoern A. Zeeb 1681*a4128aadSBjoern A. Zeeb if (meta->flags & CMD_BLOCK_TXQS) 1682*a4128aadSBjoern A. Zeeb iwl_trans_pcie_block_txq_ptrs(trans, false); 1683bfcc09ddSBjoern A. Zeeb 1684bfcc09ddSBjoern A. Zeeb iwl_pcie_cmdq_reclaim(trans, txq_id, index); 1685bfcc09ddSBjoern A. Zeeb 1686bfcc09ddSBjoern A. Zeeb if (!(meta->flags & CMD_ASYNC)) { 1687bfcc09ddSBjoern A. Zeeb if (!test_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status)) { 1688bfcc09ddSBjoern A. Zeeb IWL_WARN(trans, 1689bfcc09ddSBjoern A. Zeeb "HCMD_ACTIVE already clear for command %s\n", 1690bfcc09ddSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd_id)); 1691bfcc09ddSBjoern A. Zeeb } 1692bfcc09ddSBjoern A. Zeeb clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); 1693bfcc09ddSBjoern A. Zeeb IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", 1694bfcc09ddSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd_id)); 1695bfcc09ddSBjoern A. Zeeb wake_up(&trans->wait_command_queue); 1696bfcc09ddSBjoern A. Zeeb } 1697bfcc09ddSBjoern A. Zeeb 1698bfcc09ddSBjoern A. Zeeb meta->flags = 0; 1699bfcc09ddSBjoern A. Zeeb 1700bfcc09ddSBjoern A. Zeeb spin_unlock_bh(&txq->lock); 1701bfcc09ddSBjoern A. Zeeb } 1702bfcc09ddSBjoern A. Zeeb 1703bfcc09ddSBjoern A. Zeeb static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb, 1704bfcc09ddSBjoern A. Zeeb struct iwl_txq *txq, u8 hdr_len, 1705bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *out_meta) 1706bfcc09ddSBjoern A. Zeeb { 1707bfcc09ddSBjoern A. Zeeb u16 head_tb_len; 1708bfcc09ddSBjoern A. Zeeb int i; 1709bfcc09ddSBjoern A. Zeeb 1710bfcc09ddSBjoern A. Zeeb /* 1711bfcc09ddSBjoern A. Zeeb * Set up TFD's third entry to point directly to remainder 1712bfcc09ddSBjoern A. Zeeb * of skb's head, if any 1713bfcc09ddSBjoern A. Zeeb */ 1714bfcc09ddSBjoern A. Zeeb head_tb_len = skb_headlen(skb) - hdr_len; 1715bfcc09ddSBjoern A. Zeeb 1716bfcc09ddSBjoern A. Zeeb if (head_tb_len > 0) { 1717bfcc09ddSBjoern A. Zeeb dma_addr_t tb_phys = dma_map_single(trans->dev, 1718bfcc09ddSBjoern A. Zeeb skb->data + hdr_len, 1719bfcc09ddSBjoern A. Zeeb head_tb_len, DMA_TO_DEVICE); 1720bfcc09ddSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, tb_phys))) 1721bfcc09ddSBjoern A. Zeeb return -EINVAL; 1722bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_tx_tb(trans->dev, skb, skb->data + hdr_len, 1723bfcc09ddSBjoern A. Zeeb tb_phys, head_tb_len); 1724bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, tb_phys, head_tb_len, false); 1725bfcc09ddSBjoern A. Zeeb } 1726bfcc09ddSBjoern A. Zeeb 1727bfcc09ddSBjoern A. Zeeb /* set up the remaining entries to point to the data */ 1728bfcc09ddSBjoern A. Zeeb for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1729bfcc09ddSBjoern A. Zeeb const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 1730bfcc09ddSBjoern A. Zeeb dma_addr_t tb_phys; 1731bfcc09ddSBjoern A. Zeeb int tb_idx; 1732bfcc09ddSBjoern A. Zeeb 1733bfcc09ddSBjoern A. Zeeb if (!skb_frag_size(frag)) 1734bfcc09ddSBjoern A. Zeeb continue; 1735bfcc09ddSBjoern A. Zeeb 1736bfcc09ddSBjoern A. Zeeb tb_phys = skb_frag_dma_map(trans->dev, frag, 0, 1737bfcc09ddSBjoern A. Zeeb skb_frag_size(frag), DMA_TO_DEVICE); 1738bfcc09ddSBjoern A. Zeeb 1739bfcc09ddSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, tb_phys))) 1740bfcc09ddSBjoern A. Zeeb return -EINVAL; 1741bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_tx_tb(trans->dev, skb, skb_frag_address(frag), 1742bfcc09ddSBjoern A. Zeeb tb_phys, skb_frag_size(frag)); 1743bfcc09ddSBjoern A. Zeeb tb_idx = iwl_pcie_txq_build_tfd(trans, txq, tb_phys, 1744bfcc09ddSBjoern A. Zeeb skb_frag_size(frag), false); 1745bfcc09ddSBjoern A. Zeeb if (tb_idx < 0) 1746bfcc09ddSBjoern A. Zeeb return tb_idx; 1747bfcc09ddSBjoern A. Zeeb 1748bfcc09ddSBjoern A. Zeeb out_meta->tbs |= BIT(tb_idx); 1749bfcc09ddSBjoern A. Zeeb } 1750bfcc09ddSBjoern A. Zeeb 1751bfcc09ddSBjoern A. Zeeb return 0; 1752bfcc09ddSBjoern A. Zeeb } 1753bfcc09ddSBjoern A. Zeeb 1754bfcc09ddSBjoern A. Zeeb #ifdef CONFIG_INET 1755*a4128aadSBjoern A. Zeeb static void *iwl_pcie_get_page_hdr(struct iwl_trans *trans, 1756*a4128aadSBjoern A. Zeeb size_t len, struct sk_buff *skb) 1757*a4128aadSBjoern A. Zeeb { 1758*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1759*a4128aadSBjoern A. Zeeb struct iwl_tso_hdr_page *p = this_cpu_ptr(trans_pcie->txqs.tso_hdr_page); 1760*a4128aadSBjoern A. Zeeb struct iwl_tso_page_info *info; 1761*a4128aadSBjoern A. Zeeb struct page **page_ptr; 1762*a4128aadSBjoern A. Zeeb dma_addr_t phys; 1763*a4128aadSBjoern A. Zeeb void *ret; 1764*a4128aadSBjoern A. Zeeb 1765*a4128aadSBjoern A. Zeeb page_ptr = (void *)((u8 *)skb->cb + trans_pcie->txqs.page_offs); 1766*a4128aadSBjoern A. Zeeb 1767*a4128aadSBjoern A. Zeeb if (WARN_ON(*page_ptr)) 1768*a4128aadSBjoern A. Zeeb return NULL; 1769*a4128aadSBjoern A. Zeeb 1770*a4128aadSBjoern A. Zeeb if (!p->page) 1771*a4128aadSBjoern A. Zeeb goto alloc; 1772*a4128aadSBjoern A. Zeeb 1773*a4128aadSBjoern A. Zeeb /* 1774*a4128aadSBjoern A. Zeeb * Check if there's enough room on this page 1775*a4128aadSBjoern A. Zeeb * 1776*a4128aadSBjoern A. Zeeb * Note that we put a page chaining pointer *last* in the 1777*a4128aadSBjoern A. Zeeb * page - we need it somewhere, and if it's there then we 1778*a4128aadSBjoern A. Zeeb * avoid DMA mapping the last bits of the page which may 1779*a4128aadSBjoern A. Zeeb * trigger the 32-bit boundary hardware bug. 1780*a4128aadSBjoern A. Zeeb * 1781*a4128aadSBjoern A. Zeeb * (see also get_workaround_page() in tx-gen2.c) 1782*a4128aadSBjoern A. Zeeb */ 1783*a4128aadSBjoern A. Zeeb if (((unsigned long)p->pos & ~PAGE_MASK) + len < IWL_TSO_PAGE_DATA_SIZE) { 1784*a4128aadSBjoern A. Zeeb info = IWL_TSO_PAGE_INFO(page_address(p->page)); 1785*a4128aadSBjoern A. Zeeb goto out; 1786*a4128aadSBjoern A. Zeeb } 1787*a4128aadSBjoern A. Zeeb 1788*a4128aadSBjoern A. Zeeb /* We don't have enough room on this page, get a new one. */ 1789*a4128aadSBjoern A. Zeeb iwl_pcie_free_and_unmap_tso_page(trans, p->page); 1790*a4128aadSBjoern A. Zeeb 1791*a4128aadSBjoern A. Zeeb alloc: 1792*a4128aadSBjoern A. Zeeb p->page = alloc_page(GFP_ATOMIC); 1793*a4128aadSBjoern A. Zeeb if (!p->page) 1794*a4128aadSBjoern A. Zeeb return NULL; 1795*a4128aadSBjoern A. Zeeb p->pos = page_address(p->page); 1796*a4128aadSBjoern A. Zeeb 1797*a4128aadSBjoern A. Zeeb info = IWL_TSO_PAGE_INFO(page_address(p->page)); 1798*a4128aadSBjoern A. Zeeb 1799*a4128aadSBjoern A. Zeeb /* set the chaining pointer to NULL */ 1800*a4128aadSBjoern A. Zeeb info->next = NULL; 1801*a4128aadSBjoern A. Zeeb 1802*a4128aadSBjoern A. Zeeb /* Create a DMA mapping for the page */ 1803*a4128aadSBjoern A. Zeeb phys = dma_map_page_attrs(trans->dev, p->page, 0, PAGE_SIZE, 1804*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); 1805*a4128aadSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, phys))) { 1806*a4128aadSBjoern A. Zeeb __free_page(p->page); 1807*a4128aadSBjoern A. Zeeb p->page = NULL; 1808*a4128aadSBjoern A. Zeeb 1809*a4128aadSBjoern A. Zeeb return NULL; 1810*a4128aadSBjoern A. Zeeb } 1811*a4128aadSBjoern A. Zeeb 1812*a4128aadSBjoern A. Zeeb /* Store physical address and set use count */ 1813*a4128aadSBjoern A. Zeeb info->dma_addr = phys; 1814*a4128aadSBjoern A. Zeeb refcount_set(&info->use_count, 1); 1815*a4128aadSBjoern A. Zeeb out: 1816*a4128aadSBjoern A. Zeeb *page_ptr = p->page; 1817*a4128aadSBjoern A. Zeeb /* Return an internal reference for the caller */ 1818*a4128aadSBjoern A. Zeeb refcount_inc(&info->use_count); 1819*a4128aadSBjoern A. Zeeb ret = p->pos; 1820*a4128aadSBjoern A. Zeeb p->pos += len; 1821*a4128aadSBjoern A. Zeeb 1822*a4128aadSBjoern A. Zeeb return ret; 1823*a4128aadSBjoern A. Zeeb } 1824*a4128aadSBjoern A. Zeeb 1825*a4128aadSBjoern A. Zeeb /** 1826*a4128aadSBjoern A. Zeeb * iwl_pcie_get_sgt_tb_phys - Find TB address in mapped SG list 1827*a4128aadSBjoern A. Zeeb * @sgt: scatter gather table 1828*a4128aadSBjoern A. Zeeb * @offset: Offset into the mapped memory (i.e. SKB payload data) 1829*a4128aadSBjoern A. Zeeb * @len: Length of the area 1830*a4128aadSBjoern A. Zeeb * 1831*a4128aadSBjoern A. Zeeb * Find the DMA address that corresponds to the SKB payload data at the 1832*a4128aadSBjoern A. Zeeb * position given by @offset. 1833*a4128aadSBjoern A. Zeeb * 1834*a4128aadSBjoern A. Zeeb * Returns: Address for TB entry 1835*a4128aadSBjoern A. Zeeb */ 1836*a4128aadSBjoern A. Zeeb dma_addr_t iwl_pcie_get_sgt_tb_phys(struct sg_table *sgt, unsigned int offset, 1837*a4128aadSBjoern A. Zeeb unsigned int len) 1838*a4128aadSBjoern A. Zeeb { 1839*a4128aadSBjoern A. Zeeb struct scatterlist *sg; 1840*a4128aadSBjoern A. Zeeb unsigned int sg_offset = 0; 1841*a4128aadSBjoern A. Zeeb int i; 1842*a4128aadSBjoern A. Zeeb 1843*a4128aadSBjoern A. Zeeb /* 1844*a4128aadSBjoern A. Zeeb * Search the mapped DMA areas in the SG for the area that contains the 1845*a4128aadSBjoern A. Zeeb * data at offset with the given length. 1846*a4128aadSBjoern A. Zeeb */ 1847*a4128aadSBjoern A. Zeeb for_each_sgtable_dma_sg(sgt, sg, i) { 1848*a4128aadSBjoern A. Zeeb if (offset >= sg_offset && 1849*a4128aadSBjoern A. Zeeb offset + len <= sg_offset + sg_dma_len(sg)) 1850*a4128aadSBjoern A. Zeeb return sg_dma_address(sg) + offset - sg_offset; 1851*a4128aadSBjoern A. Zeeb 1852*a4128aadSBjoern A. Zeeb sg_offset += sg_dma_len(sg); 1853*a4128aadSBjoern A. Zeeb } 1854*a4128aadSBjoern A. Zeeb 1855*a4128aadSBjoern A. Zeeb WARN_ON_ONCE(1); 1856*a4128aadSBjoern A. Zeeb 1857*a4128aadSBjoern A. Zeeb return DMA_MAPPING_ERROR; 1858*a4128aadSBjoern A. Zeeb } 1859*a4128aadSBjoern A. Zeeb 1860*a4128aadSBjoern A. Zeeb /** 1861*a4128aadSBjoern A. Zeeb * iwl_pcie_prep_tso - Prepare TSO page and SKB for sending 1862*a4128aadSBjoern A. Zeeb * @trans: transport private data 1863*a4128aadSBjoern A. Zeeb * @skb: the SKB to map 1864*a4128aadSBjoern A. Zeeb * @cmd_meta: command meta to store the scatter list information for unmapping 1865*a4128aadSBjoern A. Zeeb * @hdr: output argument for TSO headers 1866*a4128aadSBjoern A. Zeeb * @hdr_room: requested length for TSO headers 1867*a4128aadSBjoern A. Zeeb * 1868*a4128aadSBjoern A. Zeeb * Allocate space for a scatter gather list and TSO headers and map the SKB 1869*a4128aadSBjoern A. Zeeb * using the scatter gather list. The SKB is unmapped again when the page is 1870*a4128aadSBjoern A. Zeeb * free'ed again at the end of the operation. 1871*a4128aadSBjoern A. Zeeb * 1872*a4128aadSBjoern A. Zeeb * Returns: newly allocated and mapped scatter gather table with list 1873*a4128aadSBjoern A. Zeeb */ 1874*a4128aadSBjoern A. Zeeb struct sg_table *iwl_pcie_prep_tso(struct iwl_trans *trans, struct sk_buff *skb, 1875*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *cmd_meta, 1876*a4128aadSBjoern A. Zeeb u8 **hdr, unsigned int hdr_room) 1877*a4128aadSBjoern A. Zeeb { 1878*a4128aadSBjoern A. Zeeb struct sg_table *sgt; 1879*a4128aadSBjoern A. Zeeb 1880*a4128aadSBjoern A. Zeeb if (WARN_ON_ONCE(skb_has_frag_list(skb))) 1881*a4128aadSBjoern A. Zeeb return NULL; 1882*a4128aadSBjoern A. Zeeb 1883*a4128aadSBjoern A. Zeeb *hdr = iwl_pcie_get_page_hdr(trans, 1884*a4128aadSBjoern A. Zeeb hdr_room + __alignof__(struct sg_table) + 1885*a4128aadSBjoern A. Zeeb sizeof(struct sg_table) + 1886*a4128aadSBjoern A. Zeeb (skb_shinfo(skb)->nr_frags + 1) * 1887*a4128aadSBjoern A. Zeeb sizeof(struct scatterlist), 1888*a4128aadSBjoern A. Zeeb skb); 1889*a4128aadSBjoern A. Zeeb if (!*hdr) 1890*a4128aadSBjoern A. Zeeb return NULL; 1891*a4128aadSBjoern A. Zeeb 1892*a4128aadSBjoern A. Zeeb sgt = (void *)PTR_ALIGN(*hdr + hdr_room, __alignof__(struct sg_table)); 1893*a4128aadSBjoern A. Zeeb sgt->sgl = (void *)(sgt + 1); 1894*a4128aadSBjoern A. Zeeb 1895*a4128aadSBjoern A. Zeeb sg_init_table(sgt->sgl, skb_shinfo(skb)->nr_frags + 1); 1896*a4128aadSBjoern A. Zeeb 1897*a4128aadSBjoern A. Zeeb /* Only map the data, not the header (it is copied to the TSO page) */ 1898*a4128aadSBjoern A. Zeeb sgt->orig_nents = skb_to_sgvec(skb, sgt->sgl, skb_headlen(skb), 1899*a4128aadSBjoern A. Zeeb skb->data_len); 1900*a4128aadSBjoern A. Zeeb if (WARN_ON_ONCE(sgt->orig_nents <= 0)) 1901*a4128aadSBjoern A. Zeeb return NULL; 1902*a4128aadSBjoern A. Zeeb 1903*a4128aadSBjoern A. Zeeb /* And map the entire SKB */ 1904*a4128aadSBjoern A. Zeeb if (dma_map_sgtable(trans->dev, sgt, DMA_TO_DEVICE, 0) < 0) 1905*a4128aadSBjoern A. Zeeb return NULL; 1906*a4128aadSBjoern A. Zeeb 1907*a4128aadSBjoern A. Zeeb /* Store non-zero (i.e. valid) offset for unmapping */ 1908*a4128aadSBjoern A. Zeeb cmd_meta->sg_offset = (unsigned long) sgt & ~PAGE_MASK; 1909*a4128aadSBjoern A. Zeeb 1910*a4128aadSBjoern A. Zeeb return sgt; 1911*a4128aadSBjoern A. Zeeb } 1912*a4128aadSBjoern A. Zeeb 1913bfcc09ddSBjoern A. Zeeb static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, 1914bfcc09ddSBjoern A. Zeeb struct iwl_txq *txq, u8 hdr_len, 1915bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *out_meta, 1916bfcc09ddSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, 1917bfcc09ddSBjoern A. Zeeb u16 tb1_len) 1918bfcc09ddSBjoern A. Zeeb { 1919*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1920bfcc09ddSBjoern A. Zeeb struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; 1921bfcc09ddSBjoern A. Zeeb struct ieee80211_hdr *hdr = (void *)skb->data; 1922bfcc09ddSBjoern A. Zeeb unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; 1923bfcc09ddSBjoern A. Zeeb unsigned int mss = skb_shinfo(skb)->gso_size; 1924*a4128aadSBjoern A. Zeeb unsigned int data_offset = 0; 1925bfcc09ddSBjoern A. Zeeb u16 length, iv_len, amsdu_pad; 1926*a4128aadSBjoern A. Zeeb dma_addr_t start_hdr_phys; 1927*a4128aadSBjoern A. Zeeb u8 *start_hdr, *pos_hdr; 1928*a4128aadSBjoern A. Zeeb struct sg_table *sgt; 1929bfcc09ddSBjoern A. Zeeb struct tso_t tso; 1930bfcc09ddSBjoern A. Zeeb 1931bfcc09ddSBjoern A. Zeeb /* if the packet is protected, then it must be CCMP or GCMP */ 1932bfcc09ddSBjoern A. Zeeb BUILD_BUG_ON(IEEE80211_CCMP_HDR_LEN != IEEE80211_GCMP_HDR_LEN); 1933bfcc09ddSBjoern A. Zeeb iv_len = ieee80211_has_protected(hdr->frame_control) ? 1934bfcc09ddSBjoern A. Zeeb IEEE80211_CCMP_HDR_LEN : 0; 1935bfcc09ddSBjoern A. Zeeb 1936bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_tx(trans->dev, skb, 1937bfcc09ddSBjoern A. Zeeb iwl_txq_get_tfd(trans, txq, txq->write_ptr), 1938*a4128aadSBjoern A. Zeeb trans_pcie->txqs.tfd.size, 1939bfcc09ddSBjoern A. Zeeb &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len, 0); 1940bfcc09ddSBjoern A. Zeeb 1941*a4128aadSBjoern A. Zeeb ip_hdrlen = skb_network_header_len(skb); 1942bfcc09ddSBjoern A. Zeeb snap_ip_tcp_hdrlen = 8 + ip_hdrlen + tcp_hdrlen(skb); 1943bfcc09ddSBjoern A. Zeeb total_len = skb->len - snap_ip_tcp_hdrlen - hdr_len - iv_len; 1944bfcc09ddSBjoern A. Zeeb amsdu_pad = 0; 1945bfcc09ddSBjoern A. Zeeb 1946bfcc09ddSBjoern A. Zeeb /* total amount of header we may need for this A-MSDU */ 1947bfcc09ddSBjoern A. Zeeb hdr_room = DIV_ROUND_UP(total_len, mss) * 1948bfcc09ddSBjoern A. Zeeb (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len; 1949bfcc09ddSBjoern A. Zeeb 1950bfcc09ddSBjoern A. Zeeb /* Our device supports 9 segments at most, it will fit in 1 page */ 1951*a4128aadSBjoern A. Zeeb sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room); 1952*a4128aadSBjoern A. Zeeb if (!sgt) 1953bfcc09ddSBjoern A. Zeeb return -ENOMEM; 1954bfcc09ddSBjoern A. Zeeb 1955*a4128aadSBjoern A. Zeeb start_hdr_phys = iwl_pcie_get_tso_page_phys(start_hdr); 1956*a4128aadSBjoern A. Zeeb pos_hdr = start_hdr; 1957*a4128aadSBjoern A. Zeeb memcpy(pos_hdr, skb->data + hdr_len, iv_len); 1958*a4128aadSBjoern A. Zeeb pos_hdr += iv_len; 1959bfcc09ddSBjoern A. Zeeb 1960bfcc09ddSBjoern A. Zeeb /* 1961bfcc09ddSBjoern A. Zeeb * Pull the ieee80211 header + IV to be able to use TSO core, 1962bfcc09ddSBjoern A. Zeeb * we will restore it for the tx_status flow. 1963bfcc09ddSBjoern A. Zeeb */ 1964bfcc09ddSBjoern A. Zeeb skb_pull(skb, hdr_len + iv_len); 1965bfcc09ddSBjoern A. Zeeb 1966bfcc09ddSBjoern A. Zeeb /* 1967bfcc09ddSBjoern A. Zeeb * Remove the length of all the headers that we don't actually 1968bfcc09ddSBjoern A. Zeeb * have in the MPDU by themselves, but that we duplicate into 1969bfcc09ddSBjoern A. Zeeb * all the different MSDUs inside the A-MSDU. 1970bfcc09ddSBjoern A. Zeeb */ 1971bfcc09ddSBjoern A. Zeeb le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen); 1972bfcc09ddSBjoern A. Zeeb 1973bfcc09ddSBjoern A. Zeeb tso_start(skb, &tso); 1974bfcc09ddSBjoern A. Zeeb 1975bfcc09ddSBjoern A. Zeeb while (total_len) { 1976bfcc09ddSBjoern A. Zeeb /* this is the data left for this subframe */ 1977bfcc09ddSBjoern A. Zeeb unsigned int data_left = 1978bfcc09ddSBjoern A. Zeeb min_t(unsigned int, mss, total_len); 1979bfcc09ddSBjoern A. Zeeb unsigned int hdr_tb_len; 1980bfcc09ddSBjoern A. Zeeb dma_addr_t hdr_tb_phys; 1981*a4128aadSBjoern A. Zeeb u8 *subf_hdrs_start = pos_hdr; 1982bfcc09ddSBjoern A. Zeeb 1983bfcc09ddSBjoern A. Zeeb total_len -= data_left; 1984bfcc09ddSBjoern A. Zeeb 1985*a4128aadSBjoern A. Zeeb memset(pos_hdr, 0, amsdu_pad); 1986*a4128aadSBjoern A. Zeeb pos_hdr += amsdu_pad; 1987bfcc09ddSBjoern A. Zeeb amsdu_pad = (4 - (sizeof(struct ethhdr) + snap_ip_tcp_hdrlen + 1988bfcc09ddSBjoern A. Zeeb data_left)) & 0x3; 1989*a4128aadSBjoern A. Zeeb ether_addr_copy(pos_hdr, ieee80211_get_DA(hdr)); 1990*a4128aadSBjoern A. Zeeb pos_hdr += ETH_ALEN; 1991*a4128aadSBjoern A. Zeeb ether_addr_copy(pos_hdr, ieee80211_get_SA(hdr)); 1992*a4128aadSBjoern A. Zeeb pos_hdr += ETH_ALEN; 1993bfcc09ddSBjoern A. Zeeb 1994bfcc09ddSBjoern A. Zeeb length = snap_ip_tcp_hdrlen + data_left; 1995*a4128aadSBjoern A. Zeeb *((__be16 *)pos_hdr) = cpu_to_be16(length); 1996*a4128aadSBjoern A. Zeeb pos_hdr += sizeof(length); 1997bfcc09ddSBjoern A. Zeeb 1998bfcc09ddSBjoern A. Zeeb /* 1999bfcc09ddSBjoern A. Zeeb * This will copy the SNAP as well which will be considered 2000bfcc09ddSBjoern A. Zeeb * as MAC header. 2001bfcc09ddSBjoern A. Zeeb */ 2002*a4128aadSBjoern A. Zeeb tso_build_hdr(skb, pos_hdr, &tso, data_left, !total_len); 2003bfcc09ddSBjoern A. Zeeb 2004*a4128aadSBjoern A. Zeeb pos_hdr += snap_ip_tcp_hdrlen; 2005bfcc09ddSBjoern A. Zeeb 2006*a4128aadSBjoern A. Zeeb hdr_tb_len = pos_hdr - start_hdr; 2007*a4128aadSBjoern A. Zeeb hdr_tb_phys = iwl_pcie_get_tso_page_phys(start_hdr); 2008*a4128aadSBjoern A. Zeeb 2009bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, hdr_tb_phys, 2010bfcc09ddSBjoern A. Zeeb hdr_tb_len, false); 2011bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, 2012bfcc09ddSBjoern A. Zeeb hdr_tb_phys, hdr_tb_len); 2013bfcc09ddSBjoern A. Zeeb /* add this subframe's headers' length to the tx_cmd */ 2014*a4128aadSBjoern A. Zeeb le16_add_cpu(&tx_cmd->len, pos_hdr - subf_hdrs_start); 2015bfcc09ddSBjoern A. Zeeb 2016bfcc09ddSBjoern A. Zeeb /* prepare the start_hdr for the next subframe */ 2017*a4128aadSBjoern A. Zeeb start_hdr = pos_hdr; 2018bfcc09ddSBjoern A. Zeeb 2019bfcc09ddSBjoern A. Zeeb /* put the payload */ 2020bfcc09ddSBjoern A. Zeeb while (data_left) { 2021bfcc09ddSBjoern A. Zeeb unsigned int size = min_t(unsigned int, tso.size, 2022bfcc09ddSBjoern A. Zeeb data_left); 2023bfcc09ddSBjoern A. Zeeb dma_addr_t tb_phys; 2024bfcc09ddSBjoern A. Zeeb 2025*a4128aadSBjoern A. Zeeb tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, data_offset, size); 2026*a4128aadSBjoern A. Zeeb /* Not a real mapping error, use direct comparison */ 2027*a4128aadSBjoern A. Zeeb if (unlikely(tb_phys == DMA_MAPPING_ERROR)) 2028bfcc09ddSBjoern A. Zeeb return -EINVAL; 2029bfcc09ddSBjoern A. Zeeb 2030bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, tb_phys, 2031bfcc09ddSBjoern A. Zeeb size, false); 2032bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_tx_tb(trans->dev, skb, tso.data, 2033bfcc09ddSBjoern A. Zeeb tb_phys, size); 2034bfcc09ddSBjoern A. Zeeb 2035bfcc09ddSBjoern A. Zeeb data_left -= size; 2036*a4128aadSBjoern A. Zeeb data_offset += size; 2037bfcc09ddSBjoern A. Zeeb tso_build_data(skb, &tso, size); 2038bfcc09ddSBjoern A. Zeeb } 2039bfcc09ddSBjoern A. Zeeb } 2040bfcc09ddSBjoern A. Zeeb 2041*a4128aadSBjoern A. Zeeb dma_sync_single_for_device(trans->dev, start_hdr_phys, hdr_room, 2042*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 2043*a4128aadSBjoern A. Zeeb 2044bfcc09ddSBjoern A. Zeeb /* re -add the WiFi header and IV */ 2045bfcc09ddSBjoern A. Zeeb skb_push(skb, hdr_len + iv_len); 2046bfcc09ddSBjoern A. Zeeb 2047bfcc09ddSBjoern A. Zeeb return 0; 2048bfcc09ddSBjoern A. Zeeb } 2049bfcc09ddSBjoern A. Zeeb #else /* CONFIG_INET */ 2050bfcc09ddSBjoern A. Zeeb static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb, 2051bfcc09ddSBjoern A. Zeeb struct iwl_txq *txq, u8 hdr_len, 2052bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *out_meta, 2053bfcc09ddSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, 2054bfcc09ddSBjoern A. Zeeb u16 tb1_len) 2055bfcc09ddSBjoern A. Zeeb { 2056bfcc09ddSBjoern A. Zeeb /* No A-MSDU without CONFIG_INET */ 2057bfcc09ddSBjoern A. Zeeb WARN_ON(1); 2058bfcc09ddSBjoern A. Zeeb 2059bfcc09ddSBjoern A. Zeeb return -1; 2060bfcc09ddSBjoern A. Zeeb } 2061bfcc09ddSBjoern A. Zeeb #endif /* CONFIG_INET */ 2062bfcc09ddSBjoern A. Zeeb 2063*a4128aadSBjoern A. Zeeb #define IWL_TX_CRC_SIZE 4 2064*a4128aadSBjoern A. Zeeb #define IWL_TX_DELIMITER_SIZE 4 2065*a4128aadSBjoern A. Zeeb 2066*a4128aadSBjoern A. Zeeb /* 2067*a4128aadSBjoern A. Zeeb * iwl_txq_gen1_update_byte_cnt_tbl - Set up entry in Tx byte-count array 2068*a4128aadSBjoern A. Zeeb */ 2069*a4128aadSBjoern A. Zeeb static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans, 2070*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, u16 byte_cnt, 2071*a4128aadSBjoern A. Zeeb int num_tbs) 2072*a4128aadSBjoern A. Zeeb { 2073*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2074*a4128aadSBjoern A. Zeeb struct iwlagn_scd_bc_tbl *scd_bc_tbl; 2075*a4128aadSBjoern A. Zeeb int write_ptr = txq->write_ptr; 2076*a4128aadSBjoern A. Zeeb int txq_id = txq->id; 2077*a4128aadSBjoern A. Zeeb u8 sec_ctl = 0; 2078*a4128aadSBjoern A. Zeeb u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; 2079*a4128aadSBjoern A. Zeeb __le16 bc_ent; 2080*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd = txq->entries[txq->write_ptr].cmd; 2081*a4128aadSBjoern A. Zeeb struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; 2082*a4128aadSBjoern A. Zeeb u8 sta_id = tx_cmd->sta_id; 2083*a4128aadSBjoern A. Zeeb 2084*a4128aadSBjoern A. Zeeb scd_bc_tbl = trans_pcie->txqs.scd_bc_tbls.addr; 2085*a4128aadSBjoern A. Zeeb 2086*a4128aadSBjoern A. Zeeb sec_ctl = tx_cmd->sec_ctl; 2087*a4128aadSBjoern A. Zeeb 2088*a4128aadSBjoern A. Zeeb switch (sec_ctl & TX_CMD_SEC_MSK) { 2089*a4128aadSBjoern A. Zeeb case TX_CMD_SEC_CCM: 2090*a4128aadSBjoern A. Zeeb len += IEEE80211_CCMP_MIC_LEN; 2091*a4128aadSBjoern A. Zeeb break; 2092*a4128aadSBjoern A. Zeeb case TX_CMD_SEC_TKIP: 2093*a4128aadSBjoern A. Zeeb len += IEEE80211_TKIP_ICV_LEN; 2094*a4128aadSBjoern A. Zeeb break; 2095*a4128aadSBjoern A. Zeeb case TX_CMD_SEC_WEP: 2096*a4128aadSBjoern A. Zeeb len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN; 2097*a4128aadSBjoern A. Zeeb break; 2098*a4128aadSBjoern A. Zeeb } 2099*a4128aadSBjoern A. Zeeb if (trans_pcie->txqs.bc_table_dword) 2100*a4128aadSBjoern A. Zeeb len = DIV_ROUND_UP(len, 4); 2101*a4128aadSBjoern A. Zeeb 2102*a4128aadSBjoern A. Zeeb if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX)) 2103*a4128aadSBjoern A. Zeeb return; 2104*a4128aadSBjoern A. Zeeb 2105*a4128aadSBjoern A. Zeeb bc_ent = cpu_to_le16(len | (sta_id << 12)); 2106*a4128aadSBjoern A. Zeeb 2107*a4128aadSBjoern A. Zeeb scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; 2108*a4128aadSBjoern A. Zeeb 2109*a4128aadSBjoern A. Zeeb if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) 2110*a4128aadSBjoern A. Zeeb scd_bc_tbl[txq_id].tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = 2111*a4128aadSBjoern A. Zeeb bc_ent; 2112*a4128aadSBjoern A. Zeeb } 2113*a4128aadSBjoern A. Zeeb 2114bfcc09ddSBjoern A. Zeeb int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, 2115bfcc09ddSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, int txq_id) 2116bfcc09ddSBjoern A. Zeeb { 2117*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2118bfcc09ddSBjoern A. Zeeb struct ieee80211_hdr *hdr; 2119bfcc09ddSBjoern A. Zeeb struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; 2120bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *out_meta; 2121bfcc09ddSBjoern A. Zeeb struct iwl_txq *txq; 2122bfcc09ddSBjoern A. Zeeb dma_addr_t tb0_phys, tb1_phys, scratch_phys; 2123bfcc09ddSBjoern A. Zeeb void *tb1_addr; 2124bfcc09ddSBjoern A. Zeeb void *tfd; 2125bfcc09ddSBjoern A. Zeeb u16 len, tb1_len; 2126bfcc09ddSBjoern A. Zeeb bool wait_write_ptr; 2127bfcc09ddSBjoern A. Zeeb __le16 fc; 2128bfcc09ddSBjoern A. Zeeb u8 hdr_len; 2129bfcc09ddSBjoern A. Zeeb u16 wifi_seq; 2130bfcc09ddSBjoern A. Zeeb bool amsdu; 2131bfcc09ddSBjoern A. Zeeb 2132*a4128aadSBjoern A. Zeeb txq = trans_pcie->txqs.txq[txq_id]; 2133bfcc09ddSBjoern A. Zeeb 2134*a4128aadSBjoern A. Zeeb if (WARN_ONCE(!test_bit(txq_id, trans_pcie->txqs.queue_used), 2135bfcc09ddSBjoern A. Zeeb "TX on unused queue %d\n", txq_id)) 2136bfcc09ddSBjoern A. Zeeb return -EINVAL; 2137bfcc09ddSBjoern A. Zeeb 2138bfcc09ddSBjoern A. Zeeb if (skb_is_nonlinear(skb) && 2139*a4128aadSBjoern A. Zeeb skb_shinfo(skb)->nr_frags > IWL_TRANS_PCIE_MAX_FRAGS(trans_pcie) && 2140bfcc09ddSBjoern A. Zeeb __skb_linearize(skb)) 2141bfcc09ddSBjoern A. Zeeb return -ENOMEM; 2142bfcc09ddSBjoern A. Zeeb 2143bfcc09ddSBjoern A. Zeeb /* mac80211 always puts the full header into the SKB's head, 2144bfcc09ddSBjoern A. Zeeb * so there's no need to check if it's readable there 2145bfcc09ddSBjoern A. Zeeb */ 2146bfcc09ddSBjoern A. Zeeb hdr = (struct ieee80211_hdr *)skb->data; 2147bfcc09ddSBjoern A. Zeeb fc = hdr->frame_control; 2148bfcc09ddSBjoern A. Zeeb hdr_len = ieee80211_hdrlen(fc); 2149bfcc09ddSBjoern A. Zeeb 2150bfcc09ddSBjoern A. Zeeb spin_lock(&txq->lock); 2151bfcc09ddSBjoern A. Zeeb 2152bfcc09ddSBjoern A. Zeeb if (iwl_txq_space(trans, txq) < txq->high_mark) { 2153bfcc09ddSBjoern A. Zeeb iwl_txq_stop(trans, txq); 2154bfcc09ddSBjoern A. Zeeb 2155bfcc09ddSBjoern A. Zeeb /* don't put the packet on the ring, if there is no room */ 2156bfcc09ddSBjoern A. Zeeb if (unlikely(iwl_txq_space(trans, txq) < 3)) { 2157bfcc09ddSBjoern A. Zeeb struct iwl_device_tx_cmd **dev_cmd_ptr; 2158bfcc09ddSBjoern A. Zeeb 2159bfcc09ddSBjoern A. Zeeb dev_cmd_ptr = (void *)((u8 *)skb->cb + 2160*a4128aadSBjoern A. Zeeb trans_pcie->txqs.dev_cmd_offs); 2161bfcc09ddSBjoern A. Zeeb 2162bfcc09ddSBjoern A. Zeeb *dev_cmd_ptr = dev_cmd; 2163bfcc09ddSBjoern A. Zeeb __skb_queue_tail(&txq->overflow_q, skb); 2164bfcc09ddSBjoern A. Zeeb 2165bfcc09ddSBjoern A. Zeeb spin_unlock(&txq->lock); 2166bfcc09ddSBjoern A. Zeeb return 0; 2167bfcc09ddSBjoern A. Zeeb } 2168bfcc09ddSBjoern A. Zeeb } 2169bfcc09ddSBjoern A. Zeeb 2170bfcc09ddSBjoern A. Zeeb /* In AGG mode, the index in the ring must correspond to the WiFi 2171bfcc09ddSBjoern A. Zeeb * sequence number. This is a HW requirements to help the SCD to parse 2172bfcc09ddSBjoern A. Zeeb * the BA. 2173bfcc09ddSBjoern A. Zeeb * Check here that the packets are in the right place on the ring. 2174bfcc09ddSBjoern A. Zeeb */ 2175bfcc09ddSBjoern A. Zeeb wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); 2176bfcc09ddSBjoern A. Zeeb WARN_ONCE(txq->ampdu && 2177bfcc09ddSBjoern A. Zeeb (wifi_seq & 0xff) != txq->write_ptr, 2178bfcc09ddSBjoern A. Zeeb "Q: %d WiFi Seq %d tfdNum %d", 2179bfcc09ddSBjoern A. Zeeb txq_id, wifi_seq, txq->write_ptr); 2180bfcc09ddSBjoern A. Zeeb 2181bfcc09ddSBjoern A. Zeeb /* Set up driver data for this TFD */ 2182bfcc09ddSBjoern A. Zeeb txq->entries[txq->write_ptr].skb = skb; 2183bfcc09ddSBjoern A. Zeeb txq->entries[txq->write_ptr].cmd = dev_cmd; 2184bfcc09ddSBjoern A. Zeeb 2185bfcc09ddSBjoern A. Zeeb dev_cmd->hdr.sequence = 2186bfcc09ddSBjoern A. Zeeb cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | 2187bfcc09ddSBjoern A. Zeeb INDEX_TO_SEQ(txq->write_ptr))); 2188bfcc09ddSBjoern A. Zeeb 2189bfcc09ddSBjoern A. Zeeb tb0_phys = iwl_txq_get_first_tb_dma(txq, txq->write_ptr); 2190bfcc09ddSBjoern A. Zeeb scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) + 2191bfcc09ddSBjoern A. Zeeb offsetof(struct iwl_tx_cmd, scratch); 2192bfcc09ddSBjoern A. Zeeb 2193bfcc09ddSBjoern A. Zeeb tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); 2194bfcc09ddSBjoern A. Zeeb tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); 2195bfcc09ddSBjoern A. Zeeb 2196bfcc09ddSBjoern A. Zeeb /* Set up first empty entry in queue's array of Tx/cmd buffers */ 2197bfcc09ddSBjoern A. Zeeb out_meta = &txq->entries[txq->write_ptr].meta; 2198*a4128aadSBjoern A. Zeeb memset(out_meta, 0, sizeof(*out_meta)); 2199bfcc09ddSBjoern A. Zeeb 2200bfcc09ddSBjoern A. Zeeb /* 2201bfcc09ddSBjoern A. Zeeb * The second TB (tb1) points to the remainder of the TX command 2202bfcc09ddSBjoern A. Zeeb * and the 802.11 header - dword aligned size 2203bfcc09ddSBjoern A. Zeeb * (This calculation modifies the TX command, so do it before the 2204bfcc09ddSBjoern A. Zeeb * setup of the first TB) 2205bfcc09ddSBjoern A. Zeeb */ 2206bfcc09ddSBjoern A. Zeeb len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + 2207bfcc09ddSBjoern A. Zeeb hdr_len - IWL_FIRST_TB_SIZE; 2208bfcc09ddSBjoern A. Zeeb /* do not align A-MSDU to dword as the subframe header aligns it */ 2209bfcc09ddSBjoern A. Zeeb amsdu = ieee80211_is_data_qos(fc) && 2210bfcc09ddSBjoern A. Zeeb (*ieee80211_get_qos_ctl(hdr) & 2211bfcc09ddSBjoern A. Zeeb IEEE80211_QOS_CTL_A_MSDU_PRESENT); 2212bfcc09ddSBjoern A. Zeeb if (!amsdu) { 2213bfcc09ddSBjoern A. Zeeb tb1_len = ALIGN(len, 4); 2214bfcc09ddSBjoern A. Zeeb /* Tell NIC about any 2-byte padding after MAC header */ 2215bfcc09ddSBjoern A. Zeeb if (tb1_len != len) 2216bfcc09ddSBjoern A. Zeeb tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_MH_PAD); 2217bfcc09ddSBjoern A. Zeeb } else { 2218bfcc09ddSBjoern A. Zeeb tb1_len = len; 2219bfcc09ddSBjoern A. Zeeb } 2220bfcc09ddSBjoern A. Zeeb 2221bfcc09ddSBjoern A. Zeeb /* 2222bfcc09ddSBjoern A. Zeeb * The first TB points to bi-directional DMA data, we'll 2223bfcc09ddSBjoern A. Zeeb * memcpy the data into it later. 2224bfcc09ddSBjoern A. Zeeb */ 2225bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, 2226bfcc09ddSBjoern A. Zeeb IWL_FIRST_TB_SIZE, true); 2227bfcc09ddSBjoern A. Zeeb 2228bfcc09ddSBjoern A. Zeeb /* there must be data left over for TB1 or this code must be changed */ 2229bfcc09ddSBjoern A. Zeeb BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_FIRST_TB_SIZE); 22309af1bba4SBjoern A. Zeeb BUILD_BUG_ON(sizeof(struct iwl_cmd_header) + 22319af1bba4SBjoern A. Zeeb offsetofend(struct iwl_tx_cmd, scratch) > 22329af1bba4SBjoern A. Zeeb IWL_FIRST_TB_SIZE); 2233bfcc09ddSBjoern A. Zeeb 2234bfcc09ddSBjoern A. Zeeb /* map the data for TB1 */ 2235bfcc09ddSBjoern A. Zeeb tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE; 2236bfcc09ddSBjoern A. Zeeb tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); 2237bfcc09ddSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, tb1_phys))) 2238bfcc09ddSBjoern A. Zeeb goto out_err; 2239bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false); 2240bfcc09ddSBjoern A. Zeeb 2241bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_tx(trans->dev, skb, 2242bfcc09ddSBjoern A. Zeeb iwl_txq_get_tfd(trans, txq, txq->write_ptr), 2243*a4128aadSBjoern A. Zeeb trans_pcie->txqs.tfd.size, 2244bfcc09ddSBjoern A. Zeeb &dev_cmd->hdr, IWL_FIRST_TB_SIZE + tb1_len, 2245bfcc09ddSBjoern A. Zeeb hdr_len); 2246bfcc09ddSBjoern A. Zeeb 2247bfcc09ddSBjoern A. Zeeb /* 2248bfcc09ddSBjoern A. Zeeb * If gso_size wasn't set, don't give the frame "amsdu treatment" 2249bfcc09ddSBjoern A. Zeeb * (adding subframes, etc.). 2250bfcc09ddSBjoern A. Zeeb * This can happen in some testing flows when the amsdu was already 2251bfcc09ddSBjoern A. Zeeb * pre-built, and we just need to send the resulting skb. 2252bfcc09ddSBjoern A. Zeeb */ 2253bfcc09ddSBjoern A. Zeeb if (amsdu && skb_shinfo(skb)->gso_size) { 2254bfcc09ddSBjoern A. Zeeb if (unlikely(iwl_fill_data_tbs_amsdu(trans, skb, txq, hdr_len, 2255bfcc09ddSBjoern A. Zeeb out_meta, dev_cmd, 2256bfcc09ddSBjoern A. Zeeb tb1_len))) 2257bfcc09ddSBjoern A. Zeeb goto out_err; 2258bfcc09ddSBjoern A. Zeeb } else { 2259bfcc09ddSBjoern A. Zeeb struct sk_buff *frag; 2260bfcc09ddSBjoern A. Zeeb 2261bfcc09ddSBjoern A. Zeeb if (unlikely(iwl_fill_data_tbs(trans, skb, txq, hdr_len, 2262bfcc09ddSBjoern A. Zeeb out_meta))) 2263bfcc09ddSBjoern A. Zeeb goto out_err; 2264bfcc09ddSBjoern A. Zeeb 2265bfcc09ddSBjoern A. Zeeb skb_walk_frags(skb, frag) { 2266bfcc09ddSBjoern A. Zeeb if (unlikely(iwl_fill_data_tbs(trans, frag, txq, 0, 2267bfcc09ddSBjoern A. Zeeb out_meta))) 2268bfcc09ddSBjoern A. Zeeb goto out_err; 2269bfcc09ddSBjoern A. Zeeb } 2270bfcc09ddSBjoern A. Zeeb } 2271bfcc09ddSBjoern A. Zeeb 2272bfcc09ddSBjoern A. Zeeb /* building the A-MSDU might have changed this data, so memcpy it now */ 2273bfcc09ddSBjoern A. Zeeb memcpy(&txq->first_tb_bufs[txq->write_ptr], dev_cmd, IWL_FIRST_TB_SIZE); 2274bfcc09ddSBjoern A. Zeeb 2275bfcc09ddSBjoern A. Zeeb tfd = iwl_txq_get_tfd(trans, txq, txq->write_ptr); 2276bfcc09ddSBjoern A. Zeeb /* Set up entry for this TFD in Tx byte-count array */ 2277bfcc09ddSBjoern A. Zeeb iwl_txq_gen1_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len), 2278*a4128aadSBjoern A. Zeeb iwl_txq_gen1_tfd_get_num_tbs(tfd)); 2279bfcc09ddSBjoern A. Zeeb 2280bfcc09ddSBjoern A. Zeeb wait_write_ptr = ieee80211_has_morefrags(fc); 2281bfcc09ddSBjoern A. Zeeb 2282bfcc09ddSBjoern A. Zeeb /* start timer if queue currently empty */ 2283bfcc09ddSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr && txq->wd_timeout) { 2284bfcc09ddSBjoern A. Zeeb /* 2285bfcc09ddSBjoern A. Zeeb * If the TXQ is active, then set the timer, if not, 2286bfcc09ddSBjoern A. Zeeb * set the timer in remainder so that the timer will 2287bfcc09ddSBjoern A. Zeeb * be armed with the right value when the station will 2288bfcc09ddSBjoern A. Zeeb * wake up. 2289bfcc09ddSBjoern A. Zeeb */ 2290bfcc09ddSBjoern A. Zeeb if (!txq->frozen) 2291bfcc09ddSBjoern A. Zeeb mod_timer(&txq->stuck_timer, 2292bfcc09ddSBjoern A. Zeeb jiffies + txq->wd_timeout); 2293bfcc09ddSBjoern A. Zeeb else 2294bfcc09ddSBjoern A. Zeeb txq->frozen_expiry_remainder = txq->wd_timeout; 2295bfcc09ddSBjoern A. Zeeb } 2296bfcc09ddSBjoern A. Zeeb 2297bfcc09ddSBjoern A. Zeeb /* Tell device the write index *just past* this latest filled TFD */ 2298bfcc09ddSBjoern A. Zeeb txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr); 2299bfcc09ddSBjoern A. Zeeb if (!wait_write_ptr) 2300bfcc09ddSBjoern A. Zeeb iwl_pcie_txq_inc_wr_ptr(trans, txq); 2301bfcc09ddSBjoern A. Zeeb 2302bfcc09ddSBjoern A. Zeeb /* 2303bfcc09ddSBjoern A. Zeeb * At this point the frame is "transmitted" successfully 2304bfcc09ddSBjoern A. Zeeb * and we will get a TX status notification eventually. 2305bfcc09ddSBjoern A. Zeeb */ 2306bfcc09ddSBjoern A. Zeeb spin_unlock(&txq->lock); 2307bfcc09ddSBjoern A. Zeeb return 0; 2308bfcc09ddSBjoern A. Zeeb out_err: 2309bfcc09ddSBjoern A. Zeeb iwl_txq_gen1_tfd_unmap(trans, out_meta, txq, txq->write_ptr); 2310bfcc09ddSBjoern A. Zeeb spin_unlock(&txq->lock); 2311bfcc09ddSBjoern A. Zeeb return -1; 2312bfcc09ddSBjoern A. Zeeb } 2313*a4128aadSBjoern A. Zeeb 2314*a4128aadSBjoern A. Zeeb static void iwl_txq_gen1_inval_byte_cnt_tbl(struct iwl_trans *trans, 2315*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, 2316*a4128aadSBjoern A. Zeeb int read_ptr) 2317*a4128aadSBjoern A. Zeeb { 2318*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2319*a4128aadSBjoern A. Zeeb struct iwlagn_scd_bc_tbl *scd_bc_tbl = trans_pcie->txqs.scd_bc_tbls.addr; 2320*a4128aadSBjoern A. Zeeb int txq_id = txq->id; 2321*a4128aadSBjoern A. Zeeb u8 sta_id = 0; 2322*a4128aadSBjoern A. Zeeb __le16 bc_ent; 2323*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd = txq->entries[read_ptr].cmd; 2324*a4128aadSBjoern A. Zeeb struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload; 2325*a4128aadSBjoern A. Zeeb 2326*a4128aadSBjoern A. Zeeb WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); 2327*a4128aadSBjoern A. Zeeb 2328*a4128aadSBjoern A. Zeeb if (txq_id != trans_pcie->txqs.cmd.q_id) 2329*a4128aadSBjoern A. Zeeb sta_id = tx_cmd->sta_id; 2330*a4128aadSBjoern A. Zeeb 2331*a4128aadSBjoern A. Zeeb bc_ent = cpu_to_le16(1 | (sta_id << 12)); 2332*a4128aadSBjoern A. Zeeb 2333*a4128aadSBjoern A. Zeeb scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; 2334*a4128aadSBjoern A. Zeeb 2335*a4128aadSBjoern A. Zeeb if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) 2336*a4128aadSBjoern A. Zeeb scd_bc_tbl[txq_id].tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = 2337*a4128aadSBjoern A. Zeeb bc_ent; 2338*a4128aadSBjoern A. Zeeb } 2339*a4128aadSBjoern A. Zeeb 2340*a4128aadSBjoern A. Zeeb /* Frees buffers until index _not_ inclusive */ 2341*a4128aadSBjoern A. Zeeb void iwl_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, 2342*a4128aadSBjoern A. Zeeb struct sk_buff_head *skbs, bool is_flush) 2343*a4128aadSBjoern A. Zeeb { 2344*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2345*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 2346*a4128aadSBjoern A. Zeeb int tfd_num, read_ptr, last_to_free; 2347*a4128aadSBjoern A. Zeeb int txq_read_ptr, txq_write_ptr; 2348*a4128aadSBjoern A. Zeeb 2349*a4128aadSBjoern A. Zeeb /* This function is not meant to release cmd queue*/ 2350*a4128aadSBjoern A. Zeeb if (WARN_ON(txq_id == trans_pcie->txqs.cmd.q_id)) 2351*a4128aadSBjoern A. Zeeb return; 2352*a4128aadSBjoern A. Zeeb 2353*a4128aadSBjoern A. Zeeb if (WARN_ON(!txq)) 2354*a4128aadSBjoern A. Zeeb return; 2355*a4128aadSBjoern A. Zeeb 2356*a4128aadSBjoern A. Zeeb tfd_num = iwl_txq_get_cmd_index(txq, ssn); 2357*a4128aadSBjoern A. Zeeb 2358*a4128aadSBjoern A. Zeeb spin_lock_bh(&txq->reclaim_lock); 2359*a4128aadSBjoern A. Zeeb 2360*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 2361*a4128aadSBjoern A. Zeeb txq_read_ptr = txq->read_ptr; 2362*a4128aadSBjoern A. Zeeb txq_write_ptr = txq->write_ptr; 2363*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 2364*a4128aadSBjoern A. Zeeb 2365*a4128aadSBjoern A. Zeeb read_ptr = iwl_txq_get_cmd_index(txq, txq_read_ptr); 2366*a4128aadSBjoern A. Zeeb 2367*a4128aadSBjoern A. Zeeb if (!test_bit(txq_id, trans_pcie->txqs.queue_used)) { 2368*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n", 2369*a4128aadSBjoern A. Zeeb txq_id, ssn); 2370*a4128aadSBjoern A. Zeeb goto out; 2371*a4128aadSBjoern A. Zeeb } 2372*a4128aadSBjoern A. Zeeb 2373*a4128aadSBjoern A. Zeeb if (read_ptr == tfd_num) 2374*a4128aadSBjoern A. Zeeb goto out; 2375*a4128aadSBjoern A. Zeeb 2376*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d (%d) -> %d (%d)\n", 2377*a4128aadSBjoern A. Zeeb txq_id, read_ptr, txq_read_ptr, tfd_num, ssn); 2378*a4128aadSBjoern A. Zeeb 2379*a4128aadSBjoern A. Zeeb /* Since we free until index _not_ inclusive, the one before index is 2380*a4128aadSBjoern A. Zeeb * the last we will free. This one must be used 2381*a4128aadSBjoern A. Zeeb */ 2382*a4128aadSBjoern A. Zeeb last_to_free = iwl_txq_dec_wrap(trans, tfd_num); 2383*a4128aadSBjoern A. Zeeb 2384*a4128aadSBjoern A. Zeeb if (!iwl_txq_used(txq, last_to_free, txq_read_ptr, txq_write_ptr)) { 2385*a4128aadSBjoern A. Zeeb IWL_ERR(trans, 2386*a4128aadSBjoern A. Zeeb "%s: Read index for txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n", 2387*a4128aadSBjoern A. Zeeb __func__, txq_id, last_to_free, 2388*a4128aadSBjoern A. Zeeb trans->trans_cfg->base_params->max_tfd_queue_size, 2389*a4128aadSBjoern A. Zeeb txq_write_ptr, txq_read_ptr); 2390*a4128aadSBjoern A. Zeeb 2391*a4128aadSBjoern A. Zeeb iwl_op_mode_time_point(trans->op_mode, 2392*a4128aadSBjoern A. Zeeb IWL_FW_INI_TIME_POINT_FAKE_TX, 2393*a4128aadSBjoern A. Zeeb NULL); 2394*a4128aadSBjoern A. Zeeb goto out; 2395*a4128aadSBjoern A. Zeeb } 2396*a4128aadSBjoern A. Zeeb 2397*a4128aadSBjoern A. Zeeb if (WARN_ON(!skb_queue_empty(skbs))) 2398*a4128aadSBjoern A. Zeeb goto out; 2399*a4128aadSBjoern A. Zeeb 2400*a4128aadSBjoern A. Zeeb for (; 2401*a4128aadSBjoern A. Zeeb read_ptr != tfd_num; 2402*a4128aadSBjoern A. Zeeb txq_read_ptr = iwl_txq_inc_wrap(trans, txq_read_ptr), 2403*a4128aadSBjoern A. Zeeb read_ptr = iwl_txq_get_cmd_index(txq, txq_read_ptr)) { 2404*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *cmd_meta = &txq->entries[read_ptr].meta; 2405*a4128aadSBjoern A. Zeeb struct sk_buff *skb = txq->entries[read_ptr].skb; 2406*a4128aadSBjoern A. Zeeb 2407*a4128aadSBjoern A. Zeeb if (WARN_ONCE(!skb, "no SKB at %d (%d) on queue %d\n", 2408*a4128aadSBjoern A. Zeeb read_ptr, txq_read_ptr, txq_id)) 2409*a4128aadSBjoern A. Zeeb continue; 2410*a4128aadSBjoern A. Zeeb 2411*a4128aadSBjoern A. Zeeb iwl_pcie_free_tso_pages(trans, skb, cmd_meta); 2412*a4128aadSBjoern A. Zeeb 2413*a4128aadSBjoern A. Zeeb __skb_queue_tail(skbs, skb); 2414*a4128aadSBjoern A. Zeeb 2415*a4128aadSBjoern A. Zeeb txq->entries[read_ptr].skb = NULL; 2416*a4128aadSBjoern A. Zeeb 2417*a4128aadSBjoern A. Zeeb if (!trans->trans_cfg->gen2) 2418*a4128aadSBjoern A. Zeeb iwl_txq_gen1_inval_byte_cnt_tbl(trans, txq, 2419*a4128aadSBjoern A. Zeeb txq_read_ptr); 2420*a4128aadSBjoern A. Zeeb 2421*a4128aadSBjoern A. Zeeb iwl_txq_free_tfd(trans, txq, txq_read_ptr); 2422*a4128aadSBjoern A. Zeeb } 2423*a4128aadSBjoern A. Zeeb 2424*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 2425*a4128aadSBjoern A. Zeeb txq->read_ptr = txq_read_ptr; 2426*a4128aadSBjoern A. Zeeb 2427*a4128aadSBjoern A. Zeeb iwl_txq_progress(txq); 2428*a4128aadSBjoern A. Zeeb 2429*a4128aadSBjoern A. Zeeb if (iwl_txq_space(trans, txq) > txq->low_mark && 2430*a4128aadSBjoern A. Zeeb test_bit(txq_id, trans_pcie->txqs.queue_stopped)) { 2431*a4128aadSBjoern A. Zeeb struct sk_buff_head overflow_skbs; 2432*a4128aadSBjoern A. Zeeb struct sk_buff *skb; 2433*a4128aadSBjoern A. Zeeb 2434*a4128aadSBjoern A. Zeeb __skb_queue_head_init(&overflow_skbs); 2435*a4128aadSBjoern A. Zeeb skb_queue_splice_init(&txq->overflow_q, 2436*a4128aadSBjoern A. Zeeb is_flush ? skbs : &overflow_skbs); 2437*a4128aadSBjoern A. Zeeb 2438*a4128aadSBjoern A. Zeeb /* 2439*a4128aadSBjoern A. Zeeb * We are going to transmit from the overflow queue. 2440*a4128aadSBjoern A. Zeeb * Remember this state so that wait_for_txq_empty will know we 2441*a4128aadSBjoern A. Zeeb * are adding more packets to the TFD queue. It cannot rely on 2442*a4128aadSBjoern A. Zeeb * the state of &txq->overflow_q, as we just emptied it, but 2443*a4128aadSBjoern A. Zeeb * haven't TXed the content yet. 2444*a4128aadSBjoern A. Zeeb */ 2445*a4128aadSBjoern A. Zeeb txq->overflow_tx = true; 2446*a4128aadSBjoern A. Zeeb 2447*a4128aadSBjoern A. Zeeb /* 2448*a4128aadSBjoern A. Zeeb * This is tricky: we are in reclaim path and are holding 2449*a4128aadSBjoern A. Zeeb * reclaim_lock, so noone will try to access the txq data 2450*a4128aadSBjoern A. Zeeb * from that path. We stopped tx, so we can't have tx as well. 2451*a4128aadSBjoern A. Zeeb * Bottom line, we can unlock and re-lock later. 2452*a4128aadSBjoern A. Zeeb */ 2453*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 2454*a4128aadSBjoern A. Zeeb 2455*a4128aadSBjoern A. Zeeb while ((skb = __skb_dequeue(&overflow_skbs))) { 2456*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd_ptr; 2457*a4128aadSBjoern A. Zeeb 2458*a4128aadSBjoern A. Zeeb dev_cmd_ptr = *(void **)((u8 *)skb->cb + 2459*a4128aadSBjoern A. Zeeb trans_pcie->txqs.dev_cmd_offs); 2460*a4128aadSBjoern A. Zeeb 2461*a4128aadSBjoern A. Zeeb /* 2462*a4128aadSBjoern A. Zeeb * Note that we can very well be overflowing again. 2463*a4128aadSBjoern A. Zeeb * In that case, iwl_txq_space will be small again 2464*a4128aadSBjoern A. Zeeb * and we won't wake mac80211's queue. 2465*a4128aadSBjoern A. Zeeb */ 2466*a4128aadSBjoern A. Zeeb iwl_trans_tx(trans, skb, dev_cmd_ptr, txq_id); 2467*a4128aadSBjoern A. Zeeb } 2468*a4128aadSBjoern A. Zeeb 2469*a4128aadSBjoern A. Zeeb if (iwl_txq_space(trans, txq) > txq->low_mark) 2470*a4128aadSBjoern A. Zeeb iwl_trans_pcie_wake_queue(trans, txq); 2471*a4128aadSBjoern A. Zeeb 2472*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 2473*a4128aadSBjoern A. Zeeb txq->overflow_tx = false; 2474*a4128aadSBjoern A. Zeeb } 2475*a4128aadSBjoern A. Zeeb 2476*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 2477*a4128aadSBjoern A. Zeeb out: 2478*a4128aadSBjoern A. Zeeb spin_unlock_bh(&txq->reclaim_lock); 2479*a4128aadSBjoern A. Zeeb } 2480*a4128aadSBjoern A. Zeeb 2481*a4128aadSBjoern A. Zeeb /* Set wr_ptr of specific device and txq */ 2482*a4128aadSBjoern A. Zeeb void iwl_pcie_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr) 2483*a4128aadSBjoern A. Zeeb { 2484*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2485*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 2486*a4128aadSBjoern A. Zeeb 2487*a4128aadSBjoern A. Zeeb spin_lock_bh(&txq->lock); 2488*a4128aadSBjoern A. Zeeb 2489*a4128aadSBjoern A. Zeeb txq->write_ptr = ptr; 2490*a4128aadSBjoern A. Zeeb txq->read_ptr = txq->write_ptr; 2491*a4128aadSBjoern A. Zeeb 2492*a4128aadSBjoern A. Zeeb spin_unlock_bh(&txq->lock); 2493*a4128aadSBjoern A. Zeeb } 2494*a4128aadSBjoern A. Zeeb 2495*a4128aadSBjoern A. Zeeb void iwl_pcie_freeze_txq_timer(struct iwl_trans *trans, 2496*a4128aadSBjoern A. Zeeb unsigned long txqs, bool freeze) 2497*a4128aadSBjoern A. Zeeb { 2498*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2499*a4128aadSBjoern A. Zeeb int queue; 2500*a4128aadSBjoern A. Zeeb 2501*a4128aadSBjoern A. Zeeb for_each_set_bit(queue, &txqs, BITS_PER_LONG) { 2502*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[queue]; 2503*a4128aadSBjoern A. Zeeb unsigned long now; 2504*a4128aadSBjoern A. Zeeb 2505*a4128aadSBjoern A. Zeeb spin_lock_bh(&txq->lock); 2506*a4128aadSBjoern A. Zeeb 2507*a4128aadSBjoern A. Zeeb now = jiffies; 2508*a4128aadSBjoern A. Zeeb 2509*a4128aadSBjoern A. Zeeb if (txq->frozen == freeze) 2510*a4128aadSBjoern A. Zeeb goto next_queue; 2511*a4128aadSBjoern A. Zeeb 2512*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, "%s TXQ %d\n", 2513*a4128aadSBjoern A. Zeeb freeze ? "Freezing" : "Waking", queue); 2514*a4128aadSBjoern A. Zeeb 2515*a4128aadSBjoern A. Zeeb txq->frozen = freeze; 2516*a4128aadSBjoern A. Zeeb 2517*a4128aadSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr) 2518*a4128aadSBjoern A. Zeeb goto next_queue; 2519*a4128aadSBjoern A. Zeeb 2520*a4128aadSBjoern A. Zeeb if (freeze) { 2521*a4128aadSBjoern A. Zeeb if (unlikely(time_after(now, 2522*a4128aadSBjoern A. Zeeb txq->stuck_timer.expires))) { 2523*a4128aadSBjoern A. Zeeb /* 2524*a4128aadSBjoern A. Zeeb * The timer should have fired, maybe it is 2525*a4128aadSBjoern A. Zeeb * spinning right now on the lock. 2526*a4128aadSBjoern A. Zeeb */ 2527*a4128aadSBjoern A. Zeeb goto next_queue; 2528*a4128aadSBjoern A. Zeeb } 2529*a4128aadSBjoern A. Zeeb /* remember how long until the timer fires */ 2530*a4128aadSBjoern A. Zeeb txq->frozen_expiry_remainder = 2531*a4128aadSBjoern A. Zeeb txq->stuck_timer.expires - now; 2532*a4128aadSBjoern A. Zeeb del_timer(&txq->stuck_timer); 2533*a4128aadSBjoern A. Zeeb goto next_queue; 2534*a4128aadSBjoern A. Zeeb } 2535*a4128aadSBjoern A. Zeeb 2536*a4128aadSBjoern A. Zeeb /* 2537*a4128aadSBjoern A. Zeeb * Wake a non-empty queue -> arm timer with the 2538*a4128aadSBjoern A. Zeeb * remainder before it froze 2539*a4128aadSBjoern A. Zeeb */ 2540*a4128aadSBjoern A. Zeeb mod_timer(&txq->stuck_timer, 2541*a4128aadSBjoern A. Zeeb now + txq->frozen_expiry_remainder); 2542*a4128aadSBjoern A. Zeeb 2543*a4128aadSBjoern A. Zeeb next_queue: 2544*a4128aadSBjoern A. Zeeb spin_unlock_bh(&txq->lock); 2545*a4128aadSBjoern A. Zeeb } 2546*a4128aadSBjoern A. Zeeb } 2547*a4128aadSBjoern A. Zeeb 2548*a4128aadSBjoern A. Zeeb #define HOST_COMPLETE_TIMEOUT (2 * HZ) 2549*a4128aadSBjoern A. Zeeb 2550*a4128aadSBjoern A. Zeeb static int iwl_trans_pcie_send_hcmd_sync(struct iwl_trans *trans, 2551*a4128aadSBjoern A. Zeeb struct iwl_host_cmd *cmd) 2552*a4128aadSBjoern A. Zeeb { 2553*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 2554*a4128aadSBjoern A. Zeeb const char *cmd_str = iwl_get_cmd_string(trans, cmd->id); 2555*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id]; 2556*a4128aadSBjoern A. Zeeb int cmd_idx; 2557*a4128aadSBjoern A. Zeeb int ret; 2558*a4128aadSBjoern A. Zeeb 2559*a4128aadSBjoern A. Zeeb IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", cmd_str); 2560*a4128aadSBjoern A. Zeeb 2561*a4128aadSBjoern A. Zeeb if (WARN(test_and_set_bit(STATUS_SYNC_HCMD_ACTIVE, 2562*a4128aadSBjoern A. Zeeb &trans->status), 2563*a4128aadSBjoern A. Zeeb "Command %s: a command is already active!\n", cmd_str)) 2564*a4128aadSBjoern A. Zeeb return -EIO; 2565*a4128aadSBjoern A. Zeeb 2566*a4128aadSBjoern A. Zeeb IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n", cmd_str); 2567*a4128aadSBjoern A. Zeeb 2568*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->gen2) 2569*a4128aadSBjoern A. Zeeb cmd_idx = iwl_pcie_gen2_enqueue_hcmd(trans, cmd); 2570*a4128aadSBjoern A. Zeeb else 2571*a4128aadSBjoern A. Zeeb cmd_idx = iwl_pcie_enqueue_hcmd(trans, cmd); 2572*a4128aadSBjoern A. Zeeb 2573*a4128aadSBjoern A. Zeeb if (cmd_idx < 0) { 2574*a4128aadSBjoern A. Zeeb ret = cmd_idx; 2575*a4128aadSBjoern A. Zeeb clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); 2576*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Error sending %s: enqueue_hcmd failed: %d\n", 2577*a4128aadSBjoern A. Zeeb cmd_str, ret); 2578*a4128aadSBjoern A. Zeeb return ret; 2579*a4128aadSBjoern A. Zeeb } 2580*a4128aadSBjoern A. Zeeb 2581*a4128aadSBjoern A. Zeeb ret = wait_event_timeout(trans->wait_command_queue, 2582*a4128aadSBjoern A. Zeeb !test_bit(STATUS_SYNC_HCMD_ACTIVE, 2583*a4128aadSBjoern A. Zeeb &trans->status), 2584*a4128aadSBjoern A. Zeeb HOST_COMPLETE_TIMEOUT); 2585*a4128aadSBjoern A. Zeeb if (!ret) { 2586*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Error sending %s: time out after %dms.\n", 2587*a4128aadSBjoern A. Zeeb cmd_str, jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); 2588*a4128aadSBjoern A. Zeeb 2589*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Current CMD queue read_ptr %d write_ptr %d\n", 2590*a4128aadSBjoern A. Zeeb txq->read_ptr, txq->write_ptr); 2591*a4128aadSBjoern A. Zeeb 2592*a4128aadSBjoern A. Zeeb clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); 2593*a4128aadSBjoern A. Zeeb IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", 2594*a4128aadSBjoern A. Zeeb cmd_str); 2595*a4128aadSBjoern A. Zeeb ret = -ETIMEDOUT; 2596*a4128aadSBjoern A. Zeeb 2597*a4128aadSBjoern A. Zeeb iwl_trans_sync_nmi(trans); 2598*a4128aadSBjoern A. Zeeb goto cancel; 2599*a4128aadSBjoern A. Zeeb } 2600*a4128aadSBjoern A. Zeeb 2601*a4128aadSBjoern A. Zeeb if (test_bit(STATUS_FW_ERROR, &trans->status)) { 2602*a4128aadSBjoern A. Zeeb if (!test_and_clear_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, 2603*a4128aadSBjoern A. Zeeb &trans->status)) { 2604*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str); 2605*a4128aadSBjoern A. Zeeb dump_stack(); 2606*a4128aadSBjoern A. Zeeb } 2607*a4128aadSBjoern A. Zeeb ret = -EIO; 2608*a4128aadSBjoern A. Zeeb goto cancel; 2609*a4128aadSBjoern A. Zeeb } 2610*a4128aadSBjoern A. Zeeb 2611*a4128aadSBjoern A. Zeeb if (!(cmd->flags & CMD_SEND_IN_RFKILL) && 2612*a4128aadSBjoern A. Zeeb test_bit(STATUS_RFKILL_OPMODE, &trans->status)) { 2613*a4128aadSBjoern A. Zeeb IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n"); 2614*a4128aadSBjoern A. Zeeb ret = -ERFKILL; 2615*a4128aadSBjoern A. Zeeb goto cancel; 2616*a4128aadSBjoern A. Zeeb } 2617*a4128aadSBjoern A. Zeeb 2618*a4128aadSBjoern A. Zeeb if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) { 2619*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Error: Response NULL in '%s'\n", cmd_str); 2620*a4128aadSBjoern A. Zeeb ret = -EIO; 2621*a4128aadSBjoern A. Zeeb goto cancel; 2622*a4128aadSBjoern A. Zeeb } 2623*a4128aadSBjoern A. Zeeb 2624*a4128aadSBjoern A. Zeeb return 0; 2625*a4128aadSBjoern A. Zeeb 2626*a4128aadSBjoern A. Zeeb cancel: 2627*a4128aadSBjoern A. Zeeb if (cmd->flags & CMD_WANT_SKB) { 2628*a4128aadSBjoern A. Zeeb /* 2629*a4128aadSBjoern A. Zeeb * Cancel the CMD_WANT_SKB flag for the cmd in the 2630*a4128aadSBjoern A. Zeeb * TX cmd queue. Otherwise in case the cmd comes 2631*a4128aadSBjoern A. Zeeb * in later, it will possibly set an invalid 2632*a4128aadSBjoern A. Zeeb * address (cmd->meta.source). 2633*a4128aadSBjoern A. Zeeb */ 2634*a4128aadSBjoern A. Zeeb txq->entries[cmd_idx].meta.flags &= ~CMD_WANT_SKB; 2635*a4128aadSBjoern A. Zeeb } 2636*a4128aadSBjoern A. Zeeb 2637*a4128aadSBjoern A. Zeeb if (cmd->resp_pkt) { 2638*a4128aadSBjoern A. Zeeb iwl_free_resp(cmd); 2639*a4128aadSBjoern A. Zeeb cmd->resp_pkt = NULL; 2640*a4128aadSBjoern A. Zeeb } 2641*a4128aadSBjoern A. Zeeb 2642*a4128aadSBjoern A. Zeeb return ret; 2643*a4128aadSBjoern A. Zeeb } 2644*a4128aadSBjoern A. Zeeb 2645*a4128aadSBjoern A. Zeeb int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, 2646*a4128aadSBjoern A. Zeeb struct iwl_host_cmd *cmd) 2647*a4128aadSBjoern A. Zeeb { 2648*a4128aadSBjoern A. Zeeb /* Make sure the NIC is still alive in the bus */ 2649*a4128aadSBjoern A. Zeeb if (test_bit(STATUS_TRANS_DEAD, &trans->status)) 2650*a4128aadSBjoern A. Zeeb return -ENODEV; 2651*a4128aadSBjoern A. Zeeb 2652*a4128aadSBjoern A. Zeeb if (!(cmd->flags & CMD_SEND_IN_RFKILL) && 2653*a4128aadSBjoern A. Zeeb test_bit(STATUS_RFKILL_OPMODE, &trans->status)) { 2654*a4128aadSBjoern A. Zeeb IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", 2655*a4128aadSBjoern A. Zeeb cmd->id); 2656*a4128aadSBjoern A. Zeeb return -ERFKILL; 2657*a4128aadSBjoern A. Zeeb } 2658*a4128aadSBjoern A. Zeeb 2659*a4128aadSBjoern A. Zeeb if (unlikely(trans->system_pm_mode == IWL_PLAT_PM_MODE_D3 && 2660*a4128aadSBjoern A. Zeeb !(cmd->flags & CMD_SEND_IN_D3))) { 2661*a4128aadSBjoern A. Zeeb IWL_DEBUG_WOWLAN(trans, "Dropping CMD 0x%x: D3\n", cmd->id); 2662*a4128aadSBjoern A. Zeeb return -EHOSTDOWN; 2663*a4128aadSBjoern A. Zeeb } 2664*a4128aadSBjoern A. Zeeb 2665*a4128aadSBjoern A. Zeeb if (cmd->flags & CMD_ASYNC) { 2666*a4128aadSBjoern A. Zeeb int ret; 2667*a4128aadSBjoern A. Zeeb 2668*a4128aadSBjoern A. Zeeb /* An asynchronous command can not expect an SKB to be set. */ 2669*a4128aadSBjoern A. Zeeb if (WARN_ON(cmd->flags & CMD_WANT_SKB)) 2670*a4128aadSBjoern A. Zeeb return -EINVAL; 2671*a4128aadSBjoern A. Zeeb 2672*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->gen2) 2673*a4128aadSBjoern A. Zeeb ret = iwl_pcie_gen2_enqueue_hcmd(trans, cmd); 2674*a4128aadSBjoern A. Zeeb else 2675*a4128aadSBjoern A. Zeeb ret = iwl_pcie_enqueue_hcmd(trans, cmd); 2676*a4128aadSBjoern A. Zeeb 2677*a4128aadSBjoern A. Zeeb if (ret < 0) { 2678*a4128aadSBjoern A. Zeeb IWL_ERR(trans, 2679*a4128aadSBjoern A. Zeeb "Error sending %s: enqueue_hcmd failed: %d\n", 2680*a4128aadSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd->id), ret); 2681*a4128aadSBjoern A. Zeeb return ret; 2682*a4128aadSBjoern A. Zeeb } 2683*a4128aadSBjoern A. Zeeb return 0; 2684*a4128aadSBjoern A. Zeeb } 2685*a4128aadSBjoern A. Zeeb 2686*a4128aadSBjoern A. Zeeb return iwl_trans_pcie_send_hcmd_sync(trans, cmd); 2687*a4128aadSBjoern A. Zeeb } 2688*a4128aadSBjoern A. Zeeb IWL_EXPORT_SYMBOL(iwl_trans_pcie_send_hcmd); 2689