1bfcc09ddSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2bfcc09ddSBjoern A. Zeeb /* 3bfcc09ddSBjoern A. Zeeb * Copyright (C) 2017 Intel Deutschland GmbH 4*a4128aadSBjoern A. Zeeb * Copyright (C) 2018-2020, 2023-2024 Intel Corporation 5bfcc09ddSBjoern A. Zeeb */ 6bfcc09ddSBjoern A. Zeeb #ifdef CONFIG_INET 7bfcc09ddSBjoern A. Zeeb #include <net/tso.h> 8bfcc09ddSBjoern A. Zeeb #endif 9bfcc09ddSBjoern A. Zeeb #include <linux/tcp.h> 10bfcc09ddSBjoern A. Zeeb 11bfcc09ddSBjoern A. Zeeb #include "iwl-debug.h" 12bfcc09ddSBjoern A. Zeeb #include "iwl-csr.h" 13bfcc09ddSBjoern A. Zeeb #include "iwl-io.h" 14bfcc09ddSBjoern A. Zeeb #include "internal.h" 15bfcc09ddSBjoern A. Zeeb #include "fw/api/tx.h" 16*a4128aadSBjoern A. Zeeb #include "fw/api/commands.h" 17*a4128aadSBjoern A. Zeeb #include "fw/api/datapath.h" 18*a4128aadSBjoern A. Zeeb #include "iwl-scd.h" 19*a4128aadSBjoern A. Zeeb 20*a4128aadSBjoern A. Zeeb static struct page *get_workaround_page(struct iwl_trans *trans, 21*a4128aadSBjoern A. Zeeb struct sk_buff *skb) 22*a4128aadSBjoern A. Zeeb { 23*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 24*a4128aadSBjoern A. Zeeb struct iwl_tso_page_info *info; 25*a4128aadSBjoern A. Zeeb struct page **page_ptr; 26*a4128aadSBjoern A. Zeeb struct page *ret; 27*a4128aadSBjoern A. Zeeb dma_addr_t phys; 28*a4128aadSBjoern A. Zeeb 29*a4128aadSBjoern A. Zeeb page_ptr = (void *)((u8 *)skb->cb + trans_pcie->txqs.page_offs); 30*a4128aadSBjoern A. Zeeb 31*a4128aadSBjoern A. Zeeb ret = alloc_page(GFP_ATOMIC); 32*a4128aadSBjoern A. Zeeb if (!ret) 33*a4128aadSBjoern A. Zeeb return NULL; 34*a4128aadSBjoern A. Zeeb 35*a4128aadSBjoern A. Zeeb info = IWL_TSO_PAGE_INFO(page_address(ret)); 36*a4128aadSBjoern A. Zeeb 37*a4128aadSBjoern A. Zeeb /* Create a DMA mapping for the page */ 38*a4128aadSBjoern A. Zeeb phys = dma_map_page_attrs(trans->dev, ret, 0, PAGE_SIZE, 39*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); 40*a4128aadSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, phys))) { 41*a4128aadSBjoern A. Zeeb __free_page(ret); 42*a4128aadSBjoern A. Zeeb return NULL; 43*a4128aadSBjoern A. Zeeb } 44*a4128aadSBjoern A. Zeeb 45*a4128aadSBjoern A. Zeeb /* Store physical address and set use count */ 46*a4128aadSBjoern A. Zeeb info->dma_addr = phys; 47*a4128aadSBjoern A. Zeeb refcount_set(&info->use_count, 1); 48*a4128aadSBjoern A. Zeeb 49*a4128aadSBjoern A. Zeeb /* set the chaining pointer to the previous page if there */ 50*a4128aadSBjoern A. Zeeb info->next = *page_ptr; 51*a4128aadSBjoern A. Zeeb *page_ptr = ret; 52*a4128aadSBjoern A. Zeeb 53*a4128aadSBjoern A. Zeeb return ret; 54*a4128aadSBjoern A. Zeeb } 55*a4128aadSBjoern A. Zeeb 56*a4128aadSBjoern A. Zeeb /* 57*a4128aadSBjoern A. Zeeb * Add a TB and if needed apply the FH HW bug workaround; 58*a4128aadSBjoern A. Zeeb * meta != NULL indicates that it's a page mapping and we 59*a4128aadSBjoern A. Zeeb * need to dma_unmap_page() and set the meta->tbs bit in 60*a4128aadSBjoern A. Zeeb * this case. 61*a4128aadSBjoern A. Zeeb */ 62*a4128aadSBjoern A. Zeeb static int iwl_txq_gen2_set_tb_with_wa(struct iwl_trans *trans, 63*a4128aadSBjoern A. Zeeb struct sk_buff *skb, 64*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd, 65*a4128aadSBjoern A. Zeeb dma_addr_t phys, void *virt, 66*a4128aadSBjoern A. Zeeb u16 len, struct iwl_cmd_meta *meta, 67*a4128aadSBjoern A. Zeeb bool unmap) 68*a4128aadSBjoern A. Zeeb { 69*a4128aadSBjoern A. Zeeb dma_addr_t oldphys = phys; 70*a4128aadSBjoern A. Zeeb struct page *page; 71*a4128aadSBjoern A. Zeeb int ret; 72*a4128aadSBjoern A. Zeeb 73*a4128aadSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, phys))) 74*a4128aadSBjoern A. Zeeb return -ENOMEM; 75*a4128aadSBjoern A. Zeeb 76*a4128aadSBjoern A. Zeeb if (likely(!iwl_txq_crosses_4g_boundary(phys, len))) { 77*a4128aadSBjoern A. Zeeb ret = iwl_txq_gen2_set_tb(trans, tfd, phys, len); 78*a4128aadSBjoern A. Zeeb 79*a4128aadSBjoern A. Zeeb if (ret < 0) 80*a4128aadSBjoern A. Zeeb goto unmap; 81*a4128aadSBjoern A. Zeeb 82*a4128aadSBjoern A. Zeeb if (meta) 83*a4128aadSBjoern A. Zeeb meta->tbs |= BIT(ret); 84*a4128aadSBjoern A. Zeeb 85*a4128aadSBjoern A. Zeeb ret = 0; 86*a4128aadSBjoern A. Zeeb goto trace; 87*a4128aadSBjoern A. Zeeb } 88*a4128aadSBjoern A. Zeeb 89*a4128aadSBjoern A. Zeeb /* 90*a4128aadSBjoern A. Zeeb * Work around a hardware bug. If (as expressed in the 91*a4128aadSBjoern A. Zeeb * condition above) the TB ends on a 32-bit boundary, 92*a4128aadSBjoern A. Zeeb * then the next TB may be accessed with the wrong 93*a4128aadSBjoern A. Zeeb * address. 94*a4128aadSBjoern A. Zeeb * To work around it, copy the data elsewhere and make 95*a4128aadSBjoern A. Zeeb * a new mapping for it so the device will not fail. 96*a4128aadSBjoern A. Zeeb */ 97*a4128aadSBjoern A. Zeeb 98*a4128aadSBjoern A. Zeeb if (WARN_ON(len > IWL_TSO_PAGE_DATA_SIZE)) { 99*a4128aadSBjoern A. Zeeb ret = -ENOBUFS; 100*a4128aadSBjoern A. Zeeb goto unmap; 101*a4128aadSBjoern A. Zeeb } 102*a4128aadSBjoern A. Zeeb 103*a4128aadSBjoern A. Zeeb page = get_workaround_page(trans, skb); 104*a4128aadSBjoern A. Zeeb if (!page) { 105*a4128aadSBjoern A. Zeeb ret = -ENOMEM; 106*a4128aadSBjoern A. Zeeb goto unmap; 107*a4128aadSBjoern A. Zeeb } 108*a4128aadSBjoern A. Zeeb 109*a4128aadSBjoern A. Zeeb memcpy(page_address(page), virt, len); 110*a4128aadSBjoern A. Zeeb 111*a4128aadSBjoern A. Zeeb /* 112*a4128aadSBjoern A. Zeeb * This is a bit odd, but performance does not matter here, what 113*a4128aadSBjoern A. Zeeb * matters are the expectations of the calling code and TB cleanup 114*a4128aadSBjoern A. Zeeb * function. 115*a4128aadSBjoern A. Zeeb * 116*a4128aadSBjoern A. Zeeb * As such, if unmap is set, then create another mapping for the TB 117*a4128aadSBjoern A. Zeeb * entry as it will be unmapped later. On the other hand, if it is not 118*a4128aadSBjoern A. Zeeb * set, then the TB entry will not be unmapped and instead we simply 119*a4128aadSBjoern A. Zeeb * reference and sync the mapping that get_workaround_page() created. 120*a4128aadSBjoern A. Zeeb */ 121*a4128aadSBjoern A. Zeeb if (unmap) { 122*a4128aadSBjoern A. Zeeb phys = dma_map_single(trans->dev, page_address(page), len, 123*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 124*a4128aadSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, phys))) 125*a4128aadSBjoern A. Zeeb return -ENOMEM; 126*a4128aadSBjoern A. Zeeb } else { 127*a4128aadSBjoern A. Zeeb phys = iwl_pcie_get_tso_page_phys(page_address(page)); 128*a4128aadSBjoern A. Zeeb dma_sync_single_for_device(trans->dev, phys, len, 129*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 130*a4128aadSBjoern A. Zeeb } 131*a4128aadSBjoern A. Zeeb 132*a4128aadSBjoern A. Zeeb ret = iwl_txq_gen2_set_tb(trans, tfd, phys, len); 133*a4128aadSBjoern A. Zeeb if (ret < 0) { 134*a4128aadSBjoern A. Zeeb /* unmap the new allocation as single */ 135*a4128aadSBjoern A. Zeeb oldphys = phys; 136*a4128aadSBjoern A. Zeeb meta = NULL; 137*a4128aadSBjoern A. Zeeb goto unmap; 138*a4128aadSBjoern A. Zeeb } 139*a4128aadSBjoern A. Zeeb 140*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX(trans, 141*a4128aadSBjoern A. Zeeb "TB bug workaround: copied %d bytes from 0x%llx to 0x%llx\n", 142*a4128aadSBjoern A. Zeeb len, (unsigned long long)oldphys, 143*a4128aadSBjoern A. Zeeb (unsigned long long)phys); 144*a4128aadSBjoern A. Zeeb 145*a4128aadSBjoern A. Zeeb ret = 0; 146*a4128aadSBjoern A. Zeeb unmap: 147*a4128aadSBjoern A. Zeeb if (!unmap) 148*a4128aadSBjoern A. Zeeb goto trace; 149*a4128aadSBjoern A. Zeeb 150*a4128aadSBjoern A. Zeeb if (meta) 151*a4128aadSBjoern A. Zeeb dma_unmap_page(trans->dev, oldphys, len, DMA_TO_DEVICE); 152*a4128aadSBjoern A. Zeeb else 153*a4128aadSBjoern A. Zeeb dma_unmap_single(trans->dev, oldphys, len, DMA_TO_DEVICE); 154*a4128aadSBjoern A. Zeeb trace: 155*a4128aadSBjoern A. Zeeb trace_iwlwifi_dev_tx_tb(trans->dev, skb, virt, phys, len); 156*a4128aadSBjoern A. Zeeb 157*a4128aadSBjoern A. Zeeb return ret; 158*a4128aadSBjoern A. Zeeb } 159*a4128aadSBjoern A. Zeeb 160*a4128aadSBjoern A. Zeeb static int iwl_txq_gen2_build_amsdu(struct iwl_trans *trans, 161*a4128aadSBjoern A. Zeeb struct sk_buff *skb, 162*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd, 163*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *out_meta, 164*a4128aadSBjoern A. Zeeb int start_len, 165*a4128aadSBjoern A. Zeeb u8 hdr_len, 166*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd) 167*a4128aadSBjoern A. Zeeb { 168*a4128aadSBjoern A. Zeeb #ifdef CONFIG_INET 169*a4128aadSBjoern A. Zeeb struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload; 170*a4128aadSBjoern A. Zeeb struct ieee80211_hdr *hdr = (void *)skb->data; 171*a4128aadSBjoern A. Zeeb unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; 172*a4128aadSBjoern A. Zeeb unsigned int mss = skb_shinfo(skb)->gso_size; 173*a4128aadSBjoern A. Zeeb unsigned int data_offset = 0; 174*a4128aadSBjoern A. Zeeb dma_addr_t start_hdr_phys; 175*a4128aadSBjoern A. Zeeb u16 length, amsdu_pad; 176*a4128aadSBjoern A. Zeeb u8 *start_hdr; 177*a4128aadSBjoern A. Zeeb struct sg_table *sgt; 178*a4128aadSBjoern A. Zeeb struct tso_t tso; 179*a4128aadSBjoern A. Zeeb 180*a4128aadSBjoern A. Zeeb trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), 181*a4128aadSBjoern A. Zeeb &dev_cmd->hdr, start_len, 0); 182*a4128aadSBjoern A. Zeeb 183*a4128aadSBjoern A. Zeeb ip_hdrlen = skb_network_header_len(skb); 184*a4128aadSBjoern A. Zeeb snap_ip_tcp_hdrlen = 8 + ip_hdrlen + tcp_hdrlen(skb); 185*a4128aadSBjoern A. Zeeb total_len = skb->len - snap_ip_tcp_hdrlen - hdr_len; 186*a4128aadSBjoern A. Zeeb amsdu_pad = 0; 187*a4128aadSBjoern A. Zeeb 188*a4128aadSBjoern A. Zeeb /* total amount of header we may need for this A-MSDU */ 189*a4128aadSBjoern A. Zeeb hdr_room = DIV_ROUND_UP(total_len, mss) * 190*a4128aadSBjoern A. Zeeb (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)); 191*a4128aadSBjoern A. Zeeb 192*a4128aadSBjoern A. Zeeb /* Our device supports 9 segments at most, it will fit in 1 page */ 193*a4128aadSBjoern A. Zeeb sgt = iwl_pcie_prep_tso(trans, skb, out_meta, &start_hdr, hdr_room); 194*a4128aadSBjoern A. Zeeb if (!sgt) 195*a4128aadSBjoern A. Zeeb return -ENOMEM; 196*a4128aadSBjoern A. Zeeb 197*a4128aadSBjoern A. Zeeb start_hdr_phys = iwl_pcie_get_tso_page_phys(start_hdr); 198*a4128aadSBjoern A. Zeeb 199*a4128aadSBjoern A. Zeeb /* 200*a4128aadSBjoern A. Zeeb * Pull the ieee80211 header to be able to use TSO core, 201*a4128aadSBjoern A. Zeeb * we will restore it for the tx_status flow. 202*a4128aadSBjoern A. Zeeb */ 203*a4128aadSBjoern A. Zeeb skb_pull(skb, hdr_len); 204*a4128aadSBjoern A. Zeeb 205*a4128aadSBjoern A. Zeeb /* 206*a4128aadSBjoern A. Zeeb * Remove the length of all the headers that we don't actually 207*a4128aadSBjoern A. Zeeb * have in the MPDU by themselves, but that we duplicate into 208*a4128aadSBjoern A. Zeeb * all the different MSDUs inside the A-MSDU. 209*a4128aadSBjoern A. Zeeb */ 210*a4128aadSBjoern A. Zeeb le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen); 211*a4128aadSBjoern A. Zeeb 212*a4128aadSBjoern A. Zeeb tso_start(skb, &tso); 213*a4128aadSBjoern A. Zeeb 214*a4128aadSBjoern A. Zeeb while (total_len) { 215*a4128aadSBjoern A. Zeeb /* this is the data left for this subframe */ 216*a4128aadSBjoern A. Zeeb unsigned int data_left = min_t(unsigned int, mss, total_len); 217*a4128aadSBjoern A. Zeeb unsigned int tb_len; 218*a4128aadSBjoern A. Zeeb dma_addr_t tb_phys; 219*a4128aadSBjoern A. Zeeb u8 *pos_hdr = start_hdr; 220*a4128aadSBjoern A. Zeeb 221*a4128aadSBjoern A. Zeeb total_len -= data_left; 222*a4128aadSBjoern A. Zeeb 223*a4128aadSBjoern A. Zeeb memset(pos_hdr, 0, amsdu_pad); 224*a4128aadSBjoern A. Zeeb pos_hdr += amsdu_pad; 225*a4128aadSBjoern A. Zeeb amsdu_pad = (4 - (sizeof(struct ethhdr) + snap_ip_tcp_hdrlen + 226*a4128aadSBjoern A. Zeeb data_left)) & 0x3; 227*a4128aadSBjoern A. Zeeb ether_addr_copy(pos_hdr, ieee80211_get_DA(hdr)); 228*a4128aadSBjoern A. Zeeb pos_hdr += ETH_ALEN; 229*a4128aadSBjoern A. Zeeb ether_addr_copy(pos_hdr, ieee80211_get_SA(hdr)); 230*a4128aadSBjoern A. Zeeb pos_hdr += ETH_ALEN; 231*a4128aadSBjoern A. Zeeb 232*a4128aadSBjoern A. Zeeb length = snap_ip_tcp_hdrlen + data_left; 233*a4128aadSBjoern A. Zeeb *((__be16 *)pos_hdr) = cpu_to_be16(length); 234*a4128aadSBjoern A. Zeeb pos_hdr += sizeof(length); 235*a4128aadSBjoern A. Zeeb 236*a4128aadSBjoern A. Zeeb /* 237*a4128aadSBjoern A. Zeeb * This will copy the SNAP as well which will be considered 238*a4128aadSBjoern A. Zeeb * as MAC header. 239*a4128aadSBjoern A. Zeeb */ 240*a4128aadSBjoern A. Zeeb tso_build_hdr(skb, pos_hdr, &tso, data_left, !total_len); 241*a4128aadSBjoern A. Zeeb 242*a4128aadSBjoern A. Zeeb pos_hdr += snap_ip_tcp_hdrlen; 243*a4128aadSBjoern A. Zeeb 244*a4128aadSBjoern A. Zeeb tb_len = pos_hdr - start_hdr; 245*a4128aadSBjoern A. Zeeb tb_phys = iwl_pcie_get_tso_page_phys(start_hdr); 246*a4128aadSBjoern A. Zeeb 247*a4128aadSBjoern A. Zeeb /* 248*a4128aadSBjoern A. Zeeb * No need for _with_wa, this is from the TSO page and 249*a4128aadSBjoern A. Zeeb * we leave some space at the end of it so can't hit 250*a4128aadSBjoern A. Zeeb * the buggy scenario. 251*a4128aadSBjoern A. Zeeb */ 252*a4128aadSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, tb_phys, tb_len); 253*a4128aadSBjoern A. Zeeb trace_iwlwifi_dev_tx_tb(trans->dev, skb, start_hdr, 254*a4128aadSBjoern A. Zeeb tb_phys, tb_len); 255*a4128aadSBjoern A. Zeeb /* add this subframe's headers' length to the tx_cmd */ 256*a4128aadSBjoern A. Zeeb le16_add_cpu(&tx_cmd->len, tb_len); 257*a4128aadSBjoern A. Zeeb 258*a4128aadSBjoern A. Zeeb /* prepare the start_hdr for the next subframe */ 259*a4128aadSBjoern A. Zeeb start_hdr = pos_hdr; 260*a4128aadSBjoern A. Zeeb 261*a4128aadSBjoern A. Zeeb /* put the payload */ 262*a4128aadSBjoern A. Zeeb while (data_left) { 263*a4128aadSBjoern A. Zeeb int ret; 264*a4128aadSBjoern A. Zeeb 265*a4128aadSBjoern A. Zeeb tb_len = min_t(unsigned int, tso.size, data_left); 266*a4128aadSBjoern A. Zeeb tb_phys = iwl_pcie_get_sgt_tb_phys(sgt, data_offset, 267*a4128aadSBjoern A. Zeeb tb_len); 268*a4128aadSBjoern A. Zeeb /* Not a real mapping error, use direct comparison */ 269*a4128aadSBjoern A. Zeeb if (unlikely(tb_phys == DMA_MAPPING_ERROR)) 270*a4128aadSBjoern A. Zeeb goto out_err; 271*a4128aadSBjoern A. Zeeb 272*a4128aadSBjoern A. Zeeb ret = iwl_txq_gen2_set_tb_with_wa(trans, skb, tfd, 273*a4128aadSBjoern A. Zeeb tb_phys, tso.data, 274*a4128aadSBjoern A. Zeeb tb_len, NULL, false); 275*a4128aadSBjoern A. Zeeb if (ret) 276*a4128aadSBjoern A. Zeeb goto out_err; 277*a4128aadSBjoern A. Zeeb 278*a4128aadSBjoern A. Zeeb data_left -= tb_len; 279*a4128aadSBjoern A. Zeeb data_offset += tb_len; 280*a4128aadSBjoern A. Zeeb tso_build_data(skb, &tso, tb_len); 281*a4128aadSBjoern A. Zeeb } 282*a4128aadSBjoern A. Zeeb } 283*a4128aadSBjoern A. Zeeb 284*a4128aadSBjoern A. Zeeb dma_sync_single_for_device(trans->dev, start_hdr_phys, hdr_room, 285*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 286*a4128aadSBjoern A. Zeeb 287*a4128aadSBjoern A. Zeeb /* re -add the WiFi header */ 288*a4128aadSBjoern A. Zeeb skb_push(skb, hdr_len); 289*a4128aadSBjoern A. Zeeb 290*a4128aadSBjoern A. Zeeb return 0; 291*a4128aadSBjoern A. Zeeb 292*a4128aadSBjoern A. Zeeb out_err: 293*a4128aadSBjoern A. Zeeb #endif 294*a4128aadSBjoern A. Zeeb return -EINVAL; 295*a4128aadSBjoern A. Zeeb } 296*a4128aadSBjoern A. Zeeb 297*a4128aadSBjoern A. Zeeb static struct 298*a4128aadSBjoern A. Zeeb iwl_tfh_tfd *iwl_txq_gen2_build_tx_amsdu(struct iwl_trans *trans, 299*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, 300*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, 301*a4128aadSBjoern A. Zeeb struct sk_buff *skb, 302*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *out_meta, 303*a4128aadSBjoern A. Zeeb int hdr_len, 304*a4128aadSBjoern A. Zeeb int tx_cmd_len) 305*a4128aadSBjoern A. Zeeb { 306*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 307*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd = iwl_txq_get_tfd(trans, txq, idx); 308*a4128aadSBjoern A. Zeeb dma_addr_t tb_phys; 309*a4128aadSBjoern A. Zeeb int len; 310*a4128aadSBjoern A. Zeeb void *tb1_addr; 311*a4128aadSBjoern A. Zeeb 312*a4128aadSBjoern A. Zeeb tb_phys = iwl_txq_get_first_tb_dma(txq, idx); 313*a4128aadSBjoern A. Zeeb 314*a4128aadSBjoern A. Zeeb /* 315*a4128aadSBjoern A. Zeeb * No need for _with_wa, the first TB allocation is aligned up 316*a4128aadSBjoern A. Zeeb * to a 64-byte boundary and thus can't be at the end or cross 317*a4128aadSBjoern A. Zeeb * a page boundary (much less a 2^32 boundary). 318*a4128aadSBjoern A. Zeeb */ 319*a4128aadSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE); 320*a4128aadSBjoern A. Zeeb 321*a4128aadSBjoern A. Zeeb /* 322*a4128aadSBjoern A. Zeeb * The second TB (tb1) points to the remainder of the TX command 323*a4128aadSBjoern A. Zeeb * and the 802.11 header - dword aligned size 324*a4128aadSBjoern A. Zeeb * (This calculation modifies the TX command, so do it before the 325*a4128aadSBjoern A. Zeeb * setup of the first TB) 326*a4128aadSBjoern A. Zeeb */ 327*a4128aadSBjoern A. Zeeb len = tx_cmd_len + sizeof(struct iwl_cmd_header) + hdr_len - 328*a4128aadSBjoern A. Zeeb IWL_FIRST_TB_SIZE; 329*a4128aadSBjoern A. Zeeb 330*a4128aadSBjoern A. Zeeb /* do not align A-MSDU to dword as the subframe header aligns it */ 331*a4128aadSBjoern A. Zeeb 332*a4128aadSBjoern A. Zeeb /* map the data for TB1 */ 333*a4128aadSBjoern A. Zeeb tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE; 334*a4128aadSBjoern A. Zeeb tb_phys = dma_map_single(trans->dev, tb1_addr, len, DMA_TO_DEVICE); 335*a4128aadSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, tb_phys))) 336*a4128aadSBjoern A. Zeeb goto out_err; 337*a4128aadSBjoern A. Zeeb /* 338*a4128aadSBjoern A. Zeeb * No need for _with_wa(), we ensure (via alignment) that the data 339*a4128aadSBjoern A. Zeeb * here can never cross or end at a page boundary. 340*a4128aadSBjoern A. Zeeb */ 341*a4128aadSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, tb_phys, len); 342*a4128aadSBjoern A. Zeeb 343*a4128aadSBjoern A. Zeeb if (iwl_txq_gen2_build_amsdu(trans, skb, tfd, out_meta, 344*a4128aadSBjoern A. Zeeb len + IWL_FIRST_TB_SIZE, hdr_len, dev_cmd)) 345*a4128aadSBjoern A. Zeeb goto out_err; 346*a4128aadSBjoern A. Zeeb 347*a4128aadSBjoern A. Zeeb /* building the A-MSDU might have changed this data, memcpy it now */ 348*a4128aadSBjoern A. Zeeb memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE); 349*a4128aadSBjoern A. Zeeb return tfd; 350*a4128aadSBjoern A. Zeeb 351*a4128aadSBjoern A. Zeeb out_err: 352*a4128aadSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, out_meta, tfd); 353*a4128aadSBjoern A. Zeeb return NULL; 354*a4128aadSBjoern A. Zeeb } 355*a4128aadSBjoern A. Zeeb 356*a4128aadSBjoern A. Zeeb static int iwl_txq_gen2_tx_add_frags(struct iwl_trans *trans, 357*a4128aadSBjoern A. Zeeb struct sk_buff *skb, 358*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd, 359*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *out_meta) 360*a4128aadSBjoern A. Zeeb { 361*a4128aadSBjoern A. Zeeb int i; 362*a4128aadSBjoern A. Zeeb 363*a4128aadSBjoern A. Zeeb for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 364*a4128aadSBjoern A. Zeeb const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 365*a4128aadSBjoern A. Zeeb dma_addr_t tb_phys; 366*a4128aadSBjoern A. Zeeb unsigned int fragsz = skb_frag_size(frag); 367*a4128aadSBjoern A. Zeeb int ret; 368*a4128aadSBjoern A. Zeeb 369*a4128aadSBjoern A. Zeeb if (!fragsz) 370*a4128aadSBjoern A. Zeeb continue; 371*a4128aadSBjoern A. Zeeb 372*a4128aadSBjoern A. Zeeb tb_phys = skb_frag_dma_map(trans->dev, frag, 0, 373*a4128aadSBjoern A. Zeeb fragsz, DMA_TO_DEVICE); 374*a4128aadSBjoern A. Zeeb ret = iwl_txq_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, 375*a4128aadSBjoern A. Zeeb skb_frag_address(frag), 376*a4128aadSBjoern A. Zeeb fragsz, out_meta, true); 377*a4128aadSBjoern A. Zeeb if (ret) 378*a4128aadSBjoern A. Zeeb return ret; 379*a4128aadSBjoern A. Zeeb } 380*a4128aadSBjoern A. Zeeb 381*a4128aadSBjoern A. Zeeb return 0; 382*a4128aadSBjoern A. Zeeb } 383*a4128aadSBjoern A. Zeeb 384*a4128aadSBjoern A. Zeeb static struct 385*a4128aadSBjoern A. Zeeb iwl_tfh_tfd *iwl_txq_gen2_build_tx(struct iwl_trans *trans, 386*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, 387*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, 388*a4128aadSBjoern A. Zeeb struct sk_buff *skb, 389*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *out_meta, 390*a4128aadSBjoern A. Zeeb int hdr_len, 391*a4128aadSBjoern A. Zeeb int tx_cmd_len, 392*a4128aadSBjoern A. Zeeb bool pad) 393*a4128aadSBjoern A. Zeeb { 394*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 395*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd = iwl_txq_get_tfd(trans, txq, idx); 396*a4128aadSBjoern A. Zeeb dma_addr_t tb_phys; 397*a4128aadSBjoern A. Zeeb int len, tb1_len, tb2_len; 398*a4128aadSBjoern A. Zeeb void *tb1_addr; 399*a4128aadSBjoern A. Zeeb struct sk_buff *frag; 400*a4128aadSBjoern A. Zeeb 401*a4128aadSBjoern A. Zeeb tb_phys = iwl_txq_get_first_tb_dma(txq, idx); 402*a4128aadSBjoern A. Zeeb 403*a4128aadSBjoern A. Zeeb /* The first TB points to bi-directional DMA data */ 404*a4128aadSBjoern A. Zeeb memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE); 405*a4128aadSBjoern A. Zeeb 406*a4128aadSBjoern A. Zeeb /* 407*a4128aadSBjoern A. Zeeb * No need for _with_wa, the first TB allocation is aligned up 408*a4128aadSBjoern A. Zeeb * to a 64-byte boundary and thus can't be at the end or cross 409*a4128aadSBjoern A. Zeeb * a page boundary (much less a 2^32 boundary). 410*a4128aadSBjoern A. Zeeb */ 411*a4128aadSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE); 412*a4128aadSBjoern A. Zeeb 413*a4128aadSBjoern A. Zeeb /* 414*a4128aadSBjoern A. Zeeb * The second TB (tb1) points to the remainder of the TX command 415*a4128aadSBjoern A. Zeeb * and the 802.11 header - dword aligned size 416*a4128aadSBjoern A. Zeeb * (This calculation modifies the TX command, so do it before the 417*a4128aadSBjoern A. Zeeb * setup of the first TB) 418*a4128aadSBjoern A. Zeeb */ 419*a4128aadSBjoern A. Zeeb len = tx_cmd_len + sizeof(struct iwl_cmd_header) + hdr_len - 420*a4128aadSBjoern A. Zeeb IWL_FIRST_TB_SIZE; 421*a4128aadSBjoern A. Zeeb 422*a4128aadSBjoern A. Zeeb if (pad) 423*a4128aadSBjoern A. Zeeb tb1_len = ALIGN(len, 4); 424*a4128aadSBjoern A. Zeeb else 425*a4128aadSBjoern A. Zeeb tb1_len = len; 426*a4128aadSBjoern A. Zeeb 427*a4128aadSBjoern A. Zeeb /* map the data for TB1 */ 428*a4128aadSBjoern A. Zeeb tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_FIRST_TB_SIZE; 429*a4128aadSBjoern A. Zeeb tb_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); 430*a4128aadSBjoern A. Zeeb if (unlikely(dma_mapping_error(trans->dev, tb_phys))) 431*a4128aadSBjoern A. Zeeb goto out_err; 432*a4128aadSBjoern A. Zeeb /* 433*a4128aadSBjoern A. Zeeb * No need for _with_wa(), we ensure (via alignment) that the data 434*a4128aadSBjoern A. Zeeb * here can never cross or end at a page boundary. 435*a4128aadSBjoern A. Zeeb */ 436*a4128aadSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, tb_phys, tb1_len); 437*a4128aadSBjoern A. Zeeb trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), &dev_cmd->hdr, 438*a4128aadSBjoern A. Zeeb IWL_FIRST_TB_SIZE + tb1_len, hdr_len); 439*a4128aadSBjoern A. Zeeb 440*a4128aadSBjoern A. Zeeb /* set up TFD's third entry to point to remainder of skb's head */ 441*a4128aadSBjoern A. Zeeb tb2_len = skb_headlen(skb) - hdr_len; 442*a4128aadSBjoern A. Zeeb 443*a4128aadSBjoern A. Zeeb if (tb2_len > 0) { 444*a4128aadSBjoern A. Zeeb int ret; 445*a4128aadSBjoern A. Zeeb 446*a4128aadSBjoern A. Zeeb tb_phys = dma_map_single(trans->dev, skb->data + hdr_len, 447*a4128aadSBjoern A. Zeeb tb2_len, DMA_TO_DEVICE); 448*a4128aadSBjoern A. Zeeb ret = iwl_txq_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, 449*a4128aadSBjoern A. Zeeb skb->data + hdr_len, tb2_len, 450*a4128aadSBjoern A. Zeeb NULL, true); 451*a4128aadSBjoern A. Zeeb if (ret) 452*a4128aadSBjoern A. Zeeb goto out_err; 453*a4128aadSBjoern A. Zeeb } 454*a4128aadSBjoern A. Zeeb 455*a4128aadSBjoern A. Zeeb if (iwl_txq_gen2_tx_add_frags(trans, skb, tfd, out_meta)) 456*a4128aadSBjoern A. Zeeb goto out_err; 457*a4128aadSBjoern A. Zeeb 458*a4128aadSBjoern A. Zeeb skb_walk_frags(skb, frag) { 459*a4128aadSBjoern A. Zeeb int ret; 460*a4128aadSBjoern A. Zeeb 461*a4128aadSBjoern A. Zeeb tb_phys = dma_map_single(trans->dev, frag->data, 462*a4128aadSBjoern A. Zeeb skb_headlen(frag), DMA_TO_DEVICE); 463*a4128aadSBjoern A. Zeeb ret = iwl_txq_gen2_set_tb_with_wa(trans, skb, tfd, tb_phys, 464*a4128aadSBjoern A. Zeeb frag->data, 465*a4128aadSBjoern A. Zeeb skb_headlen(frag), NULL, 466*a4128aadSBjoern A. Zeeb true); 467*a4128aadSBjoern A. Zeeb if (ret) 468*a4128aadSBjoern A. Zeeb goto out_err; 469*a4128aadSBjoern A. Zeeb if (iwl_txq_gen2_tx_add_frags(trans, frag, tfd, out_meta)) 470*a4128aadSBjoern A. Zeeb goto out_err; 471*a4128aadSBjoern A. Zeeb } 472*a4128aadSBjoern A. Zeeb 473*a4128aadSBjoern A. Zeeb return tfd; 474*a4128aadSBjoern A. Zeeb 475*a4128aadSBjoern A. Zeeb out_err: 476*a4128aadSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, out_meta, tfd); 477*a4128aadSBjoern A. Zeeb return NULL; 478*a4128aadSBjoern A. Zeeb } 479*a4128aadSBjoern A. Zeeb 480*a4128aadSBjoern A. Zeeb static 481*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *iwl_txq_gen2_build_tfd(struct iwl_trans *trans, 482*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, 483*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, 484*a4128aadSBjoern A. Zeeb struct sk_buff *skb, 485*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *out_meta) 486*a4128aadSBjoern A. Zeeb { 487*a4128aadSBjoern A. Zeeb struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 488*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 489*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd = iwl_txq_get_tfd(trans, txq, idx); 490*a4128aadSBjoern A. Zeeb int len, hdr_len; 491*a4128aadSBjoern A. Zeeb bool amsdu; 492*a4128aadSBjoern A. Zeeb 493*a4128aadSBjoern A. Zeeb /* There must be data left over for TB1 or this code must be changed */ 494*a4128aadSBjoern A. Zeeb BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) < IWL_FIRST_TB_SIZE); 495*a4128aadSBjoern A. Zeeb BUILD_BUG_ON(sizeof(struct iwl_cmd_header) + 496*a4128aadSBjoern A. Zeeb offsetofend(struct iwl_tx_cmd_gen2, dram_info) > 497*a4128aadSBjoern A. Zeeb IWL_FIRST_TB_SIZE); 498*a4128aadSBjoern A. Zeeb BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) < IWL_FIRST_TB_SIZE); 499*a4128aadSBjoern A. Zeeb BUILD_BUG_ON(sizeof(struct iwl_cmd_header) + 500*a4128aadSBjoern A. Zeeb offsetofend(struct iwl_tx_cmd_gen3, dram_info) > 501*a4128aadSBjoern A. Zeeb IWL_FIRST_TB_SIZE); 502*a4128aadSBjoern A. Zeeb 503*a4128aadSBjoern A. Zeeb memset(tfd, 0, sizeof(*tfd)); 504*a4128aadSBjoern A. Zeeb 505*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) 506*a4128aadSBjoern A. Zeeb len = sizeof(struct iwl_tx_cmd_gen2); 507*a4128aadSBjoern A. Zeeb else 508*a4128aadSBjoern A. Zeeb len = sizeof(struct iwl_tx_cmd_gen3); 509*a4128aadSBjoern A. Zeeb 510*a4128aadSBjoern A. Zeeb amsdu = ieee80211_is_data_qos(hdr->frame_control) && 511*a4128aadSBjoern A. Zeeb (*ieee80211_get_qos_ctl(hdr) & 512*a4128aadSBjoern A. Zeeb IEEE80211_QOS_CTL_A_MSDU_PRESENT); 513*a4128aadSBjoern A. Zeeb 514*a4128aadSBjoern A. Zeeb hdr_len = ieee80211_hdrlen(hdr->frame_control); 515*a4128aadSBjoern A. Zeeb 516*a4128aadSBjoern A. Zeeb /* 517*a4128aadSBjoern A. Zeeb * Only build A-MSDUs here if doing so by GSO, otherwise it may be 518*a4128aadSBjoern A. Zeeb * an A-MSDU for other reasons, e.g. NAN or an A-MSDU having been 519*a4128aadSBjoern A. Zeeb * built in the higher layers already. 520*a4128aadSBjoern A. Zeeb */ 521*a4128aadSBjoern A. Zeeb if (amsdu && skb_shinfo(skb)->gso_size) 522*a4128aadSBjoern A. Zeeb return iwl_txq_gen2_build_tx_amsdu(trans, txq, dev_cmd, skb, 523*a4128aadSBjoern A. Zeeb out_meta, hdr_len, len); 524*a4128aadSBjoern A. Zeeb return iwl_txq_gen2_build_tx(trans, txq, dev_cmd, skb, out_meta, 525*a4128aadSBjoern A. Zeeb hdr_len, len, !amsdu); 526*a4128aadSBjoern A. Zeeb } 527*a4128aadSBjoern A. Zeeb 528*a4128aadSBjoern A. Zeeb int iwl_txq_space(struct iwl_trans *trans, const struct iwl_txq *q) 529*a4128aadSBjoern A. Zeeb { 530*a4128aadSBjoern A. Zeeb unsigned int max; 531*a4128aadSBjoern A. Zeeb unsigned int used; 532*a4128aadSBjoern A. Zeeb 533*a4128aadSBjoern A. Zeeb /* 534*a4128aadSBjoern A. Zeeb * To avoid ambiguity between empty and completely full queues, there 535*a4128aadSBjoern A. Zeeb * should always be less than max_tfd_queue_size elements in the queue. 536*a4128aadSBjoern A. Zeeb * If q->n_window is smaller than max_tfd_queue_size, there is no need 537*a4128aadSBjoern A. Zeeb * to reserve any queue entries for this purpose. 538*a4128aadSBjoern A. Zeeb */ 539*a4128aadSBjoern A. Zeeb if (q->n_window < trans->trans_cfg->base_params->max_tfd_queue_size) 540*a4128aadSBjoern A. Zeeb max = q->n_window; 541*a4128aadSBjoern A. Zeeb else 542*a4128aadSBjoern A. Zeeb max = trans->trans_cfg->base_params->max_tfd_queue_size - 1; 543*a4128aadSBjoern A. Zeeb 544*a4128aadSBjoern A. Zeeb /* 545*a4128aadSBjoern A. Zeeb * max_tfd_queue_size is a power of 2, so the following is equivalent to 546*a4128aadSBjoern A. Zeeb * modulo by max_tfd_queue_size and is well defined. 547*a4128aadSBjoern A. Zeeb */ 548*a4128aadSBjoern A. Zeeb used = (q->write_ptr - q->read_ptr) & 549*a4128aadSBjoern A. Zeeb (trans->trans_cfg->base_params->max_tfd_queue_size - 1); 550*a4128aadSBjoern A. Zeeb 551*a4128aadSBjoern A. Zeeb if (WARN_ON(used > max)) 552*a4128aadSBjoern A. Zeeb return 0; 553*a4128aadSBjoern A. Zeeb 554*a4128aadSBjoern A. Zeeb return max - used; 555*a4128aadSBjoern A. Zeeb } 556*a4128aadSBjoern A. Zeeb 557*a4128aadSBjoern A. Zeeb /* 558*a4128aadSBjoern A. Zeeb * iwl_pcie_gen2_update_byte_tbl - Set up entry in Tx byte-count array 559*a4128aadSBjoern A. Zeeb */ 560*a4128aadSBjoern A. Zeeb static void iwl_pcie_gen2_update_byte_tbl(struct iwl_trans *trans, 561*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, u16 byte_cnt, 562*a4128aadSBjoern A. Zeeb int num_tbs) 563*a4128aadSBjoern A. Zeeb { 564*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 565*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 566*a4128aadSBjoern A. Zeeb u8 filled_tfd_size, num_fetch_chunks; 567*a4128aadSBjoern A. Zeeb u16 len = byte_cnt; 568*a4128aadSBjoern A. Zeeb __le16 bc_ent; 569*a4128aadSBjoern A. Zeeb 570*a4128aadSBjoern A. Zeeb if (WARN(idx >= txq->n_window, "%d >= %d\n", idx, txq->n_window)) 571*a4128aadSBjoern A. Zeeb return; 572*a4128aadSBjoern A. Zeeb 573*a4128aadSBjoern A. Zeeb filled_tfd_size = offsetof(struct iwl_tfh_tfd, tbs) + 574*a4128aadSBjoern A. Zeeb num_tbs * sizeof(struct iwl_tfh_tb); 575*a4128aadSBjoern A. Zeeb /* 576*a4128aadSBjoern A. Zeeb * filled_tfd_size contains the number of filled bytes in the TFD. 577*a4128aadSBjoern A. Zeeb * Dividing it by 64 will give the number of chunks to fetch 578*a4128aadSBjoern A. Zeeb * to SRAM- 0 for one chunk, 1 for 2 and so on. 579*a4128aadSBjoern A. Zeeb * If, for example, TFD contains only 3 TBs then 32 bytes 580*a4128aadSBjoern A. Zeeb * of the TFD are used, and only one chunk of 64 bytes should 581*a4128aadSBjoern A. Zeeb * be fetched 582*a4128aadSBjoern A. Zeeb */ 583*a4128aadSBjoern A. Zeeb num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1; 584*a4128aadSBjoern A. Zeeb 585*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { 586*a4128aadSBjoern A. Zeeb struct iwl_gen3_bc_tbl_entry *scd_bc_tbl_gen3 = txq->bc_tbl.addr; 587*a4128aadSBjoern A. Zeeb 588*a4128aadSBjoern A. Zeeb /* Starting from AX210, the HW expects bytes */ 589*a4128aadSBjoern A. Zeeb WARN_ON(trans_pcie->txqs.bc_table_dword); 590*a4128aadSBjoern A. Zeeb WARN_ON(len > 0x3FFF); 591*a4128aadSBjoern A. Zeeb bc_ent = cpu_to_le16(len | (num_fetch_chunks << 14)); 592*a4128aadSBjoern A. Zeeb scd_bc_tbl_gen3[idx].tfd_offset = bc_ent; 593*a4128aadSBjoern A. Zeeb } else { 594*a4128aadSBjoern A. Zeeb struct iwlagn_scd_bc_tbl *scd_bc_tbl = txq->bc_tbl.addr; 595*a4128aadSBjoern A. Zeeb 596*a4128aadSBjoern A. Zeeb /* Before AX210, the HW expects DW */ 597*a4128aadSBjoern A. Zeeb WARN_ON(!trans_pcie->txqs.bc_table_dword); 598*a4128aadSBjoern A. Zeeb len = DIV_ROUND_UP(len, 4); 599*a4128aadSBjoern A. Zeeb WARN_ON(len > 0xFFF); 600*a4128aadSBjoern A. Zeeb bc_ent = cpu_to_le16(len | (num_fetch_chunks << 12)); 601*a4128aadSBjoern A. Zeeb scd_bc_tbl->tfd_offset[idx] = bc_ent; 602*a4128aadSBjoern A. Zeeb } 603*a4128aadSBjoern A. Zeeb } 604*a4128aadSBjoern A. Zeeb 605*a4128aadSBjoern A. Zeeb static u8 iwl_txq_gen2_get_num_tbs(struct iwl_tfh_tfd *tfd) 606*a4128aadSBjoern A. Zeeb { 607*a4128aadSBjoern A. Zeeb return le16_to_cpu(tfd->num_tbs) & 0x1f; 608*a4128aadSBjoern A. Zeeb } 609*a4128aadSBjoern A. Zeeb 610*a4128aadSBjoern A. Zeeb int iwl_txq_gen2_set_tb(struct iwl_trans *trans, struct iwl_tfh_tfd *tfd, 611*a4128aadSBjoern A. Zeeb dma_addr_t addr, u16 len) 612*a4128aadSBjoern A. Zeeb { 613*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 614*a4128aadSBjoern A. Zeeb int idx = iwl_txq_gen2_get_num_tbs(tfd); 615*a4128aadSBjoern A. Zeeb struct iwl_tfh_tb *tb; 616*a4128aadSBjoern A. Zeeb 617*a4128aadSBjoern A. Zeeb /* Only WARN here so we know about the issue, but we mess up our 618*a4128aadSBjoern A. Zeeb * unmap path because not every place currently checks for errors 619*a4128aadSBjoern A. Zeeb * returned from this function - it can only return an error if 620*a4128aadSBjoern A. Zeeb * there's no more space, and so when we know there is enough we 621*a4128aadSBjoern A. Zeeb * don't always check ... 622*a4128aadSBjoern A. Zeeb */ 623*a4128aadSBjoern A. Zeeb WARN(iwl_txq_crosses_4g_boundary(addr, len), 624*a4128aadSBjoern A. Zeeb "possible DMA problem with iova:0x%llx, len:%d\n", 625*a4128aadSBjoern A. Zeeb (unsigned long long)addr, len); 626*a4128aadSBjoern A. Zeeb 627*a4128aadSBjoern A. Zeeb if (WARN_ON(idx >= IWL_TFH_NUM_TBS)) 628*a4128aadSBjoern A. Zeeb return -EINVAL; 629*a4128aadSBjoern A. Zeeb tb = &tfd->tbs[idx]; 630*a4128aadSBjoern A. Zeeb 631*a4128aadSBjoern A. Zeeb /* Each TFD can point to a maximum max_tbs Tx buffers */ 632*a4128aadSBjoern A. Zeeb if (le16_to_cpu(tfd->num_tbs) >= trans_pcie->txqs.tfd.max_tbs) { 633*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Error can not send more than %d chunks\n", 634*a4128aadSBjoern A. Zeeb trans_pcie->txqs.tfd.max_tbs); 635*a4128aadSBjoern A. Zeeb return -EINVAL; 636*a4128aadSBjoern A. Zeeb } 637*a4128aadSBjoern A. Zeeb 638*a4128aadSBjoern A. Zeeb put_unaligned_le64(addr, &tb->addr); 639*a4128aadSBjoern A. Zeeb tb->tb_len = cpu_to_le16(len); 640*a4128aadSBjoern A. Zeeb 641*a4128aadSBjoern A. Zeeb tfd->num_tbs = cpu_to_le16(idx + 1); 642*a4128aadSBjoern A. Zeeb 643*a4128aadSBjoern A. Zeeb return idx; 644*a4128aadSBjoern A. Zeeb } 645*a4128aadSBjoern A. Zeeb 646*a4128aadSBjoern A. Zeeb void iwl_txq_gen2_tfd_unmap(struct iwl_trans *trans, 647*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *meta, 648*a4128aadSBjoern A. Zeeb struct iwl_tfh_tfd *tfd) 649*a4128aadSBjoern A. Zeeb { 650*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 651*a4128aadSBjoern A. Zeeb int i, num_tbs; 652*a4128aadSBjoern A. Zeeb 653*a4128aadSBjoern A. Zeeb /* Sanity check on number of chunks */ 654*a4128aadSBjoern A. Zeeb num_tbs = iwl_txq_gen2_get_num_tbs(tfd); 655*a4128aadSBjoern A. Zeeb 656*a4128aadSBjoern A. Zeeb if (num_tbs > trans_pcie->txqs.tfd.max_tbs) { 657*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); 658*a4128aadSBjoern A. Zeeb return; 659*a4128aadSBjoern A. Zeeb } 660*a4128aadSBjoern A. Zeeb 661*a4128aadSBjoern A. Zeeb /* TB1 is mapped directly, the rest is the TSO page and SG list. */ 662*a4128aadSBjoern A. Zeeb if (meta->sg_offset) 663*a4128aadSBjoern A. Zeeb num_tbs = 2; 664*a4128aadSBjoern A. Zeeb 665*a4128aadSBjoern A. Zeeb /* first TB is never freed - it's the bidirectional DMA data */ 666*a4128aadSBjoern A. Zeeb for (i = 1; i < num_tbs; i++) { 667*a4128aadSBjoern A. Zeeb if (meta->tbs & BIT(i)) 668*a4128aadSBjoern A. Zeeb dma_unmap_page(trans->dev, 669*a4128aadSBjoern A. Zeeb le64_to_cpu(tfd->tbs[i].addr), 670*a4128aadSBjoern A. Zeeb le16_to_cpu(tfd->tbs[i].tb_len), 671*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 672*a4128aadSBjoern A. Zeeb else 673*a4128aadSBjoern A. Zeeb dma_unmap_single(trans->dev, 674*a4128aadSBjoern A. Zeeb le64_to_cpu(tfd->tbs[i].addr), 675*a4128aadSBjoern A. Zeeb le16_to_cpu(tfd->tbs[i].tb_len), 676*a4128aadSBjoern A. Zeeb DMA_TO_DEVICE); 677*a4128aadSBjoern A. Zeeb } 678*a4128aadSBjoern A. Zeeb 679*a4128aadSBjoern A. Zeeb iwl_txq_set_tfd_invalid_gen2(trans, tfd); 680*a4128aadSBjoern A. Zeeb } 681*a4128aadSBjoern A. Zeeb 682*a4128aadSBjoern A. Zeeb static void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) 683*a4128aadSBjoern A. Zeeb { 684*a4128aadSBjoern A. Zeeb /* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and 685*a4128aadSBjoern A. Zeeb * idx is bounded by n_window 686*a4128aadSBjoern A. Zeeb */ 687*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, txq->read_ptr); 688*a4128aadSBjoern A. Zeeb struct sk_buff *skb; 689*a4128aadSBjoern A. Zeeb 690*a4128aadSBjoern A. Zeeb lockdep_assert_held(&txq->lock); 691*a4128aadSBjoern A. Zeeb 692*a4128aadSBjoern A. Zeeb if (!txq->entries) 693*a4128aadSBjoern A. Zeeb return; 694*a4128aadSBjoern A. Zeeb 695*a4128aadSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, &txq->entries[idx].meta, 696*a4128aadSBjoern A. Zeeb iwl_txq_get_tfd(trans, txq, idx)); 697*a4128aadSBjoern A. Zeeb 698*a4128aadSBjoern A. Zeeb skb = txq->entries[idx].skb; 699*a4128aadSBjoern A. Zeeb 700*a4128aadSBjoern A. Zeeb /* Can be called from irqs-disabled context 701*a4128aadSBjoern A. Zeeb * If skb is not NULL, it means that the whole queue is being 702*a4128aadSBjoern A. Zeeb * freed and that the queue is not empty - free the skb 703*a4128aadSBjoern A. Zeeb */ 704*a4128aadSBjoern A. Zeeb if (skb) { 705*a4128aadSBjoern A. Zeeb iwl_op_mode_free_skb(trans->op_mode, skb); 706*a4128aadSBjoern A. Zeeb txq->entries[idx].skb = NULL; 707*a4128aadSBjoern A. Zeeb } 708*a4128aadSBjoern A. Zeeb } 709*a4128aadSBjoern A. Zeeb 710*a4128aadSBjoern A. Zeeb /* 711*a4128aadSBjoern A. Zeeb * iwl_txq_inc_wr_ptr - Send new write index to hardware 712*a4128aadSBjoern A. Zeeb */ 713*a4128aadSBjoern A. Zeeb static void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq) 714*a4128aadSBjoern A. Zeeb { 715*a4128aadSBjoern A. Zeeb lockdep_assert_held(&txq->lock); 716*a4128aadSBjoern A. Zeeb 717*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq->id, txq->write_ptr); 718*a4128aadSBjoern A. Zeeb 719*a4128aadSBjoern A. Zeeb /* 720*a4128aadSBjoern A. Zeeb * if not in power-save mode, uCode will never sleep when we're 721*a4128aadSBjoern A. Zeeb * trying to tx (during RFKILL, we're not trying to tx). 722*a4128aadSBjoern A. Zeeb */ 723*a4128aadSBjoern A. Zeeb iwl_write32(trans, HBUS_TARG_WRPTR, txq->write_ptr | (txq->id << 16)); 724*a4128aadSBjoern A. Zeeb } 725*a4128aadSBjoern A. Zeeb 726*a4128aadSBjoern A. Zeeb int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, 727*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd *dev_cmd, int txq_id) 728*a4128aadSBjoern A. Zeeb { 729*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 730*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *out_meta; 731*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 732*a4128aadSBjoern A. Zeeb u16 cmd_len; 733*a4128aadSBjoern A. Zeeb int idx; 734*a4128aadSBjoern A. Zeeb void *tfd; 735*a4128aadSBjoern A. Zeeb 736*a4128aadSBjoern A. Zeeb if (WARN_ONCE(txq_id >= IWL_MAX_TVQM_QUEUES, 737*a4128aadSBjoern A. Zeeb "queue %d out of range", txq_id)) 738*a4128aadSBjoern A. Zeeb return -EINVAL; 739*a4128aadSBjoern A. Zeeb 740*a4128aadSBjoern A. Zeeb if (WARN_ONCE(!test_bit(txq_id, trans_pcie->txqs.queue_used), 741*a4128aadSBjoern A. Zeeb "TX on unused queue %d\n", txq_id)) 742*a4128aadSBjoern A. Zeeb return -EINVAL; 743*a4128aadSBjoern A. Zeeb 744*a4128aadSBjoern A. Zeeb if (skb_is_nonlinear(skb) && 745*a4128aadSBjoern A. Zeeb skb_shinfo(skb)->nr_frags > IWL_TRANS_PCIE_MAX_FRAGS(trans_pcie) && 746*a4128aadSBjoern A. Zeeb __skb_linearize(skb)) 747*a4128aadSBjoern A. Zeeb return -ENOMEM; 748*a4128aadSBjoern A. Zeeb 749*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 750*a4128aadSBjoern A. Zeeb 751*a4128aadSBjoern A. Zeeb if (iwl_txq_space(trans, txq) < txq->high_mark) { 752*a4128aadSBjoern A. Zeeb iwl_txq_stop(trans, txq); 753*a4128aadSBjoern A. Zeeb 754*a4128aadSBjoern A. Zeeb /* don't put the packet on the ring, if there is no room */ 755*a4128aadSBjoern A. Zeeb if (unlikely(iwl_txq_space(trans, txq) < 3)) { 756*a4128aadSBjoern A. Zeeb struct iwl_device_tx_cmd **dev_cmd_ptr; 757*a4128aadSBjoern A. Zeeb 758*a4128aadSBjoern A. Zeeb dev_cmd_ptr = (void *)((u8 *)skb->cb + 759*a4128aadSBjoern A. Zeeb trans_pcie->txqs.dev_cmd_offs); 760*a4128aadSBjoern A. Zeeb 761*a4128aadSBjoern A. Zeeb *dev_cmd_ptr = dev_cmd; 762*a4128aadSBjoern A. Zeeb __skb_queue_tail(&txq->overflow_q, skb); 763*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 764*a4128aadSBjoern A. Zeeb return 0; 765*a4128aadSBjoern A. Zeeb } 766*a4128aadSBjoern A. Zeeb } 767*a4128aadSBjoern A. Zeeb 768*a4128aadSBjoern A. Zeeb idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 769*a4128aadSBjoern A. Zeeb 770*a4128aadSBjoern A. Zeeb /* Set up driver data for this TFD */ 771*a4128aadSBjoern A. Zeeb txq->entries[idx].skb = skb; 772*a4128aadSBjoern A. Zeeb txq->entries[idx].cmd = dev_cmd; 773*a4128aadSBjoern A. Zeeb 774*a4128aadSBjoern A. Zeeb dev_cmd->hdr.sequence = 775*a4128aadSBjoern A. Zeeb cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | 776*a4128aadSBjoern A. Zeeb INDEX_TO_SEQ(idx))); 777*a4128aadSBjoern A. Zeeb 778*a4128aadSBjoern A. Zeeb /* Set up first empty entry in queue's array of Tx/cmd buffers */ 779*a4128aadSBjoern A. Zeeb out_meta = &txq->entries[idx].meta; 780*a4128aadSBjoern A. Zeeb memset(out_meta, 0, sizeof(*out_meta)); 781*a4128aadSBjoern A. Zeeb 782*a4128aadSBjoern A. Zeeb tfd = iwl_txq_gen2_build_tfd(trans, txq, dev_cmd, skb, out_meta); 783*a4128aadSBjoern A. Zeeb if (!tfd) { 784*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 785*a4128aadSBjoern A. Zeeb return -1; 786*a4128aadSBjoern A. Zeeb } 787*a4128aadSBjoern A. Zeeb 788*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { 789*a4128aadSBjoern A. Zeeb struct iwl_tx_cmd_gen3 *tx_cmd_gen3 = 790*a4128aadSBjoern A. Zeeb (void *)dev_cmd->payload; 791*a4128aadSBjoern A. Zeeb 792*a4128aadSBjoern A. Zeeb cmd_len = le16_to_cpu(tx_cmd_gen3->len); 793*a4128aadSBjoern A. Zeeb } else { 794*a4128aadSBjoern A. Zeeb struct iwl_tx_cmd_gen2 *tx_cmd_gen2 = 795*a4128aadSBjoern A. Zeeb (void *)dev_cmd->payload; 796*a4128aadSBjoern A. Zeeb 797*a4128aadSBjoern A. Zeeb cmd_len = le16_to_cpu(tx_cmd_gen2->len); 798*a4128aadSBjoern A. Zeeb } 799*a4128aadSBjoern A. Zeeb 800*a4128aadSBjoern A. Zeeb /* Set up entry for this TFD in Tx byte-count array */ 801*a4128aadSBjoern A. Zeeb iwl_pcie_gen2_update_byte_tbl(trans, txq, cmd_len, 802*a4128aadSBjoern A. Zeeb iwl_txq_gen2_get_num_tbs(tfd)); 803*a4128aadSBjoern A. Zeeb 804*a4128aadSBjoern A. Zeeb /* start timer if queue currently empty */ 805*a4128aadSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr && txq->wd_timeout) 806*a4128aadSBjoern A. Zeeb mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); 807*a4128aadSBjoern A. Zeeb 808*a4128aadSBjoern A. Zeeb /* Tell device the write index *just past* this latest filled TFD */ 809*a4128aadSBjoern A. Zeeb txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr); 810*a4128aadSBjoern A. Zeeb iwl_txq_inc_wr_ptr(trans, txq); 811*a4128aadSBjoern A. Zeeb /* 812*a4128aadSBjoern A. Zeeb * At this point the frame is "transmitted" successfully 813*a4128aadSBjoern A. Zeeb * and we will get a TX status notification eventually. 814*a4128aadSBjoern A. Zeeb */ 815*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 816*a4128aadSBjoern A. Zeeb return 0; 817*a4128aadSBjoern A. Zeeb } 818*a4128aadSBjoern A. Zeeb 819*a4128aadSBjoern A. Zeeb /*************** HOST COMMAND QUEUE FUNCTIONS *****/ 820*a4128aadSBjoern A. Zeeb 821*a4128aadSBjoern A. Zeeb /* 822*a4128aadSBjoern A. Zeeb * iwl_txq_gen2_unmap - Unmap any remaining DMA mappings and free skb's 823*a4128aadSBjoern A. Zeeb */ 824*a4128aadSBjoern A. Zeeb static void iwl_txq_gen2_unmap(struct iwl_trans *trans, int txq_id) 825*a4128aadSBjoern A. Zeeb { 826*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 827*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[txq_id]; 828*a4128aadSBjoern A. Zeeb 829*a4128aadSBjoern A. Zeeb spin_lock_bh(&txq->reclaim_lock); 830*a4128aadSBjoern A. Zeeb spin_lock(&txq->lock); 831*a4128aadSBjoern A. Zeeb while (txq->write_ptr != txq->read_ptr) { 832*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", 833*a4128aadSBjoern A. Zeeb txq_id, txq->read_ptr); 834*a4128aadSBjoern A. Zeeb 835*a4128aadSBjoern A. Zeeb if (txq_id != trans_pcie->txqs.cmd.q_id) { 836*a4128aadSBjoern A. Zeeb int idx = iwl_txq_get_cmd_index(txq, txq->read_ptr); 837*a4128aadSBjoern A. Zeeb struct iwl_cmd_meta *cmd_meta = &txq->entries[idx].meta; 838*a4128aadSBjoern A. Zeeb struct sk_buff *skb = txq->entries[idx].skb; 839*a4128aadSBjoern A. Zeeb 840*a4128aadSBjoern A. Zeeb if (!WARN_ON_ONCE(!skb)) 841*a4128aadSBjoern A. Zeeb iwl_pcie_free_tso_pages(trans, skb, cmd_meta); 842*a4128aadSBjoern A. Zeeb } 843*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free_tfd(trans, txq); 844*a4128aadSBjoern A. Zeeb txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr); 845*a4128aadSBjoern A. Zeeb } 846*a4128aadSBjoern A. Zeeb 847*a4128aadSBjoern A. Zeeb while (!skb_queue_empty(&txq->overflow_q)) { 848*a4128aadSBjoern A. Zeeb struct sk_buff *skb = __skb_dequeue(&txq->overflow_q); 849*a4128aadSBjoern A. Zeeb 850*a4128aadSBjoern A. Zeeb iwl_op_mode_free_skb(trans->op_mode, skb); 851*a4128aadSBjoern A. Zeeb } 852*a4128aadSBjoern A. Zeeb 853*a4128aadSBjoern A. Zeeb spin_unlock(&txq->lock); 854*a4128aadSBjoern A. Zeeb spin_unlock_bh(&txq->reclaim_lock); 855*a4128aadSBjoern A. Zeeb 856*a4128aadSBjoern A. Zeeb /* just in case - this queue may have been stopped */ 857*a4128aadSBjoern A. Zeeb iwl_trans_pcie_wake_queue(trans, txq); 858*a4128aadSBjoern A. Zeeb } 859*a4128aadSBjoern A. Zeeb 860*a4128aadSBjoern A. Zeeb static void iwl_txq_gen2_free_memory(struct iwl_trans *trans, 861*a4128aadSBjoern A. Zeeb struct iwl_txq *txq) 862*a4128aadSBjoern A. Zeeb { 863*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 864*a4128aadSBjoern A. Zeeb struct device *dev = trans->dev; 865*a4128aadSBjoern A. Zeeb 866*a4128aadSBjoern A. Zeeb /* De-alloc circular buffer of TFDs */ 867*a4128aadSBjoern A. Zeeb if (txq->tfds) { 868*a4128aadSBjoern A. Zeeb dma_free_coherent(dev, 869*a4128aadSBjoern A. Zeeb trans_pcie->txqs.tfd.size * txq->n_window, 870*a4128aadSBjoern A. Zeeb txq->tfds, txq->dma_addr); 871*a4128aadSBjoern A. Zeeb dma_free_coherent(dev, 872*a4128aadSBjoern A. Zeeb sizeof(*txq->first_tb_bufs) * txq->n_window, 873*a4128aadSBjoern A. Zeeb txq->first_tb_bufs, txq->first_tb_dma); 874*a4128aadSBjoern A. Zeeb } 875*a4128aadSBjoern A. Zeeb 876*a4128aadSBjoern A. Zeeb kfree(txq->entries); 877*a4128aadSBjoern A. Zeeb if (txq->bc_tbl.addr) 878*a4128aadSBjoern A. Zeeb dma_pool_free(trans_pcie->txqs.bc_pool, 879*a4128aadSBjoern A. Zeeb txq->bc_tbl.addr, txq->bc_tbl.dma); 880*a4128aadSBjoern A. Zeeb kfree(txq); 881*a4128aadSBjoern A. Zeeb } 882*a4128aadSBjoern A. Zeeb 883*a4128aadSBjoern A. Zeeb /* 884*a4128aadSBjoern A. Zeeb * iwl_pcie_txq_free - Deallocate DMA queue. 885*a4128aadSBjoern A. Zeeb * @txq: Transmit queue to deallocate. 886*a4128aadSBjoern A. Zeeb * 887*a4128aadSBjoern A. Zeeb * Empty queue by removing and destroying all BD's. 888*a4128aadSBjoern A. Zeeb * Free all buffers. 889*a4128aadSBjoern A. Zeeb * 0-fill, but do not free "txq" descriptor structure. 890*a4128aadSBjoern A. Zeeb */ 891*a4128aadSBjoern A. Zeeb static void iwl_txq_gen2_free(struct iwl_trans *trans, int txq_id) 892*a4128aadSBjoern A. Zeeb { 893*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 894*a4128aadSBjoern A. Zeeb struct iwl_txq *txq; 895*a4128aadSBjoern A. Zeeb int i; 896*a4128aadSBjoern A. Zeeb 897*a4128aadSBjoern A. Zeeb if (WARN_ONCE(txq_id >= IWL_MAX_TVQM_QUEUES, 898*a4128aadSBjoern A. Zeeb "queue %d out of range", txq_id)) 899*a4128aadSBjoern A. Zeeb return; 900*a4128aadSBjoern A. Zeeb 901*a4128aadSBjoern A. Zeeb txq = trans_pcie->txqs.txq[txq_id]; 902*a4128aadSBjoern A. Zeeb 903*a4128aadSBjoern A. Zeeb if (WARN_ON(!txq)) 904*a4128aadSBjoern A. Zeeb return; 905*a4128aadSBjoern A. Zeeb 906*a4128aadSBjoern A. Zeeb iwl_txq_gen2_unmap(trans, txq_id); 907*a4128aadSBjoern A. Zeeb 908*a4128aadSBjoern A. Zeeb /* De-alloc array of command/tx buffers */ 909*a4128aadSBjoern A. Zeeb if (txq_id == trans_pcie->txqs.cmd.q_id) 910*a4128aadSBjoern A. Zeeb for (i = 0; i < txq->n_window; i++) { 911*a4128aadSBjoern A. Zeeb kfree_sensitive(txq->entries[i].cmd); 912*a4128aadSBjoern A. Zeeb kfree_sensitive(txq->entries[i].free_buf); 913*a4128aadSBjoern A. Zeeb } 914*a4128aadSBjoern A. Zeeb del_timer_sync(&txq->stuck_timer); 915*a4128aadSBjoern A. Zeeb 916*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free_memory(trans, txq); 917*a4128aadSBjoern A. Zeeb 918*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id] = NULL; 919*a4128aadSBjoern A. Zeeb 920*a4128aadSBjoern A. Zeeb clear_bit(txq_id, trans_pcie->txqs.queue_used); 921*a4128aadSBjoern A. Zeeb } 922*a4128aadSBjoern A. Zeeb 923*a4128aadSBjoern A. Zeeb static struct iwl_txq * 924*a4128aadSBjoern A. Zeeb iwl_txq_dyn_alloc_dma(struct iwl_trans *trans, int size, unsigned int timeout) 925*a4128aadSBjoern A. Zeeb { 926*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 927*a4128aadSBjoern A. Zeeb size_t bc_tbl_size, bc_tbl_entries; 928*a4128aadSBjoern A. Zeeb struct iwl_txq *txq; 929*a4128aadSBjoern A. Zeeb int ret; 930*a4128aadSBjoern A. Zeeb 931*a4128aadSBjoern A. Zeeb WARN_ON(!trans_pcie->txqs.bc_tbl_size); 932*a4128aadSBjoern A. Zeeb 933*a4128aadSBjoern A. Zeeb bc_tbl_size = trans_pcie->txqs.bc_tbl_size; 934*a4128aadSBjoern A. Zeeb bc_tbl_entries = bc_tbl_size / sizeof(u16); 935*a4128aadSBjoern A. Zeeb 936*a4128aadSBjoern A. Zeeb if (WARN_ON(size > bc_tbl_entries)) 937*a4128aadSBjoern A. Zeeb return ERR_PTR(-EINVAL); 938*a4128aadSBjoern A. Zeeb 939*a4128aadSBjoern A. Zeeb txq = kzalloc(sizeof(*txq), GFP_KERNEL); 940*a4128aadSBjoern A. Zeeb if (!txq) 941*a4128aadSBjoern A. Zeeb return ERR_PTR(-ENOMEM); 942*a4128aadSBjoern A. Zeeb 943*a4128aadSBjoern A. Zeeb txq->bc_tbl.addr = dma_pool_alloc(trans_pcie->txqs.bc_pool, GFP_KERNEL, 944*a4128aadSBjoern A. Zeeb &txq->bc_tbl.dma); 945*a4128aadSBjoern A. Zeeb if (!txq->bc_tbl.addr) { 946*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); 947*a4128aadSBjoern A. Zeeb kfree(txq); 948*a4128aadSBjoern A. Zeeb return ERR_PTR(-ENOMEM); 949*a4128aadSBjoern A. Zeeb } 950*a4128aadSBjoern A. Zeeb 951*a4128aadSBjoern A. Zeeb ret = iwl_pcie_txq_alloc(trans, txq, size, false); 952*a4128aadSBjoern A. Zeeb if (ret) { 953*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Tx queue alloc failed\n"); 954*a4128aadSBjoern A. Zeeb goto error; 955*a4128aadSBjoern A. Zeeb } 956*a4128aadSBjoern A. Zeeb ret = iwl_txq_init(trans, txq, size, false); 957*a4128aadSBjoern A. Zeeb if (ret) { 958*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Tx queue init failed\n"); 959*a4128aadSBjoern A. Zeeb goto error; 960*a4128aadSBjoern A. Zeeb } 961*a4128aadSBjoern A. Zeeb 962*a4128aadSBjoern A. Zeeb txq->wd_timeout = msecs_to_jiffies(timeout); 963*a4128aadSBjoern A. Zeeb 964*a4128aadSBjoern A. Zeeb return txq; 965*a4128aadSBjoern A. Zeeb 966*a4128aadSBjoern A. Zeeb error: 967*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free_memory(trans, txq); 968*a4128aadSBjoern A. Zeeb return ERR_PTR(ret); 969*a4128aadSBjoern A. Zeeb } 970*a4128aadSBjoern A. Zeeb 971*a4128aadSBjoern A. Zeeb static int iwl_pcie_txq_alloc_response(struct iwl_trans *trans, 972*a4128aadSBjoern A. Zeeb struct iwl_txq *txq, 973*a4128aadSBjoern A. Zeeb struct iwl_host_cmd *hcmd) 974*a4128aadSBjoern A. Zeeb { 975*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 976*a4128aadSBjoern A. Zeeb struct iwl_tx_queue_cfg_rsp *rsp; 977*a4128aadSBjoern A. Zeeb int ret, qid; 978*a4128aadSBjoern A. Zeeb u32 wr_ptr; 979*a4128aadSBjoern A. Zeeb 980*a4128aadSBjoern A. Zeeb if (WARN_ON(iwl_rx_packet_payload_len(hcmd->resp_pkt) != 981*a4128aadSBjoern A. Zeeb sizeof(*rsp))) { 982*a4128aadSBjoern A. Zeeb ret = -EINVAL; 983*a4128aadSBjoern A. Zeeb goto error_free_resp; 984*a4128aadSBjoern A. Zeeb } 985*a4128aadSBjoern A. Zeeb 986*a4128aadSBjoern A. Zeeb rsp = (void *)hcmd->resp_pkt->data; 987*a4128aadSBjoern A. Zeeb qid = le16_to_cpu(rsp->queue_number); 988*a4128aadSBjoern A. Zeeb wr_ptr = le16_to_cpu(rsp->write_pointer); 989*a4128aadSBjoern A. Zeeb 990*a4128aadSBjoern A. Zeeb if (qid >= ARRAY_SIZE(trans_pcie->txqs.txq)) { 991*a4128aadSBjoern A. Zeeb WARN_ONCE(1, "queue index %d unsupported", qid); 992*a4128aadSBjoern A. Zeeb ret = -EIO; 993*a4128aadSBjoern A. Zeeb goto error_free_resp; 994*a4128aadSBjoern A. Zeeb } 995*a4128aadSBjoern A. Zeeb 996*a4128aadSBjoern A. Zeeb if (test_and_set_bit(qid, trans_pcie->txqs.queue_used)) { 997*a4128aadSBjoern A. Zeeb WARN_ONCE(1, "queue %d already used", qid); 998*a4128aadSBjoern A. Zeeb ret = -EIO; 999*a4128aadSBjoern A. Zeeb goto error_free_resp; 1000*a4128aadSBjoern A. Zeeb } 1001*a4128aadSBjoern A. Zeeb 1002*a4128aadSBjoern A. Zeeb if (WARN_ONCE(trans_pcie->txqs.txq[qid], 1003*a4128aadSBjoern A. Zeeb "queue %d already allocated\n", qid)) { 1004*a4128aadSBjoern A. Zeeb ret = -EIO; 1005*a4128aadSBjoern A. Zeeb goto error_free_resp; 1006*a4128aadSBjoern A. Zeeb } 1007*a4128aadSBjoern A. Zeeb 1008*a4128aadSBjoern A. Zeeb txq->id = qid; 1009*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[qid] = txq; 1010*a4128aadSBjoern A. Zeeb wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1); 1011*a4128aadSBjoern A. Zeeb 1012*a4128aadSBjoern A. Zeeb /* Place first TFD at index corresponding to start sequence number */ 1013*a4128aadSBjoern A. Zeeb txq->read_ptr = wr_ptr; 1014*a4128aadSBjoern A. Zeeb txq->write_ptr = wr_ptr; 1015*a4128aadSBjoern A. Zeeb 1016*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d\n", qid); 1017*a4128aadSBjoern A. Zeeb 1018*a4128aadSBjoern A. Zeeb iwl_free_resp(hcmd); 1019*a4128aadSBjoern A. Zeeb return qid; 1020*a4128aadSBjoern A. Zeeb 1021*a4128aadSBjoern A. Zeeb error_free_resp: 1022*a4128aadSBjoern A. Zeeb iwl_free_resp(hcmd); 1023*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free_memory(trans, txq); 1024*a4128aadSBjoern A. Zeeb return ret; 1025*a4128aadSBjoern A. Zeeb } 1026*a4128aadSBjoern A. Zeeb 1027*a4128aadSBjoern A. Zeeb int iwl_txq_dyn_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask, 1028*a4128aadSBjoern A. Zeeb u8 tid, int size, unsigned int timeout) 1029*a4128aadSBjoern A. Zeeb { 1030*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1031*a4128aadSBjoern A. Zeeb struct iwl_txq *txq; 1032*a4128aadSBjoern A. Zeeb union { 1033*a4128aadSBjoern A. Zeeb struct iwl_tx_queue_cfg_cmd old; 1034*a4128aadSBjoern A. Zeeb struct iwl_scd_queue_cfg_cmd new; 1035*a4128aadSBjoern A. Zeeb } cmd; 1036*a4128aadSBjoern A. Zeeb struct iwl_host_cmd hcmd = { 1037*a4128aadSBjoern A. Zeeb .flags = CMD_WANT_SKB, 1038*a4128aadSBjoern A. Zeeb }; 1039*a4128aadSBjoern A. Zeeb int ret; 1040*a4128aadSBjoern A. Zeeb 1041*a4128aadSBjoern A. Zeeb /* take the min with bytecount table entries allowed */ 1042*a4128aadSBjoern A. Zeeb size = min_t(u32, size, trans_pcie->txqs.bc_tbl_size / sizeof(u16)); 1043*a4128aadSBjoern A. Zeeb /* but must be power of 2 values for calculating read/write pointers */ 1044*a4128aadSBjoern A. Zeeb size = rounddown_pow_of_two(size); 1045*a4128aadSBjoern A. Zeeb 1046*a4128aadSBjoern A. Zeeb if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ && 1047*a4128aadSBjoern A. Zeeb trans->hw_rev_step == SILICON_A_STEP) { 1048*a4128aadSBjoern A. Zeeb size = 4096; 1049*a4128aadSBjoern A. Zeeb txq = iwl_txq_dyn_alloc_dma(trans, size, timeout); 1050*a4128aadSBjoern A. Zeeb } else { 1051*a4128aadSBjoern A. Zeeb do { 1052*a4128aadSBjoern A. Zeeb txq = iwl_txq_dyn_alloc_dma(trans, size, timeout); 1053*a4128aadSBjoern A. Zeeb if (!IS_ERR(txq)) 1054*a4128aadSBjoern A. Zeeb break; 1055*a4128aadSBjoern A. Zeeb 1056*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, 1057*a4128aadSBjoern A. Zeeb "Failed allocating TXQ of size %d for sta mask %x tid %d, ret: %ld\n", 1058*a4128aadSBjoern A. Zeeb size, sta_mask, tid, 1059*a4128aadSBjoern A. Zeeb PTR_ERR(txq)); 1060*a4128aadSBjoern A. Zeeb size /= 2; 1061*a4128aadSBjoern A. Zeeb } while (size >= 16); 1062*a4128aadSBjoern A. Zeeb } 1063*a4128aadSBjoern A. Zeeb 1064*a4128aadSBjoern A. Zeeb if (IS_ERR(txq)) 1065*a4128aadSBjoern A. Zeeb return PTR_ERR(txq); 1066*a4128aadSBjoern A. Zeeb 1067*a4128aadSBjoern A. Zeeb if (trans_pcie->txqs.queue_alloc_cmd_ver == 0) { 1068*a4128aadSBjoern A. Zeeb memset(&cmd.old, 0, sizeof(cmd.old)); 1069*a4128aadSBjoern A. Zeeb cmd.old.tfdq_addr = cpu_to_le64(txq->dma_addr); 1070*a4128aadSBjoern A. Zeeb cmd.old.byte_cnt_addr = cpu_to_le64(txq->bc_tbl.dma); 1071*a4128aadSBjoern A. Zeeb cmd.old.cb_size = cpu_to_le32(TFD_QUEUE_CB_SIZE(size)); 1072*a4128aadSBjoern A. Zeeb cmd.old.flags = cpu_to_le16(flags | TX_QUEUE_CFG_ENABLE_QUEUE); 1073*a4128aadSBjoern A. Zeeb cmd.old.tid = tid; 1074*a4128aadSBjoern A. Zeeb 1075*a4128aadSBjoern A. Zeeb if (hweight32(sta_mask) != 1) { 1076*a4128aadSBjoern A. Zeeb ret = -EINVAL; 1077*a4128aadSBjoern A. Zeeb goto error; 1078*a4128aadSBjoern A. Zeeb } 1079*a4128aadSBjoern A. Zeeb cmd.old.sta_id = ffs(sta_mask) - 1; 1080*a4128aadSBjoern A. Zeeb 1081*a4128aadSBjoern A. Zeeb hcmd.id = SCD_QUEUE_CFG; 1082*a4128aadSBjoern A. Zeeb hcmd.len[0] = sizeof(cmd.old); 1083*a4128aadSBjoern A. Zeeb hcmd.data[0] = &cmd.old; 1084*a4128aadSBjoern A. Zeeb } else if (trans_pcie->txqs.queue_alloc_cmd_ver == 3) { 1085*a4128aadSBjoern A. Zeeb memset(&cmd.new, 0, sizeof(cmd.new)); 1086*a4128aadSBjoern A. Zeeb cmd.new.operation = cpu_to_le32(IWL_SCD_QUEUE_ADD); 1087*a4128aadSBjoern A. Zeeb cmd.new.u.add.tfdq_dram_addr = cpu_to_le64(txq->dma_addr); 1088*a4128aadSBjoern A. Zeeb cmd.new.u.add.bc_dram_addr = cpu_to_le64(txq->bc_tbl.dma); 1089*a4128aadSBjoern A. Zeeb cmd.new.u.add.cb_size = cpu_to_le32(TFD_QUEUE_CB_SIZE(size)); 1090*a4128aadSBjoern A. Zeeb cmd.new.u.add.flags = cpu_to_le32(flags); 1091*a4128aadSBjoern A. Zeeb cmd.new.u.add.sta_mask = cpu_to_le32(sta_mask); 1092*a4128aadSBjoern A. Zeeb cmd.new.u.add.tid = tid; 1093*a4128aadSBjoern A. Zeeb 1094*a4128aadSBjoern A. Zeeb hcmd.id = WIDE_ID(DATA_PATH_GROUP, SCD_QUEUE_CONFIG_CMD); 1095*a4128aadSBjoern A. Zeeb hcmd.len[0] = sizeof(cmd.new); 1096*a4128aadSBjoern A. Zeeb hcmd.data[0] = &cmd.new; 1097*a4128aadSBjoern A. Zeeb } else { 1098*a4128aadSBjoern A. Zeeb ret = -EOPNOTSUPP; 1099*a4128aadSBjoern A. Zeeb goto error; 1100*a4128aadSBjoern A. Zeeb } 1101*a4128aadSBjoern A. Zeeb 1102*a4128aadSBjoern A. Zeeb ret = iwl_trans_send_cmd(trans, &hcmd); 1103*a4128aadSBjoern A. Zeeb if (ret) 1104*a4128aadSBjoern A. Zeeb goto error; 1105*a4128aadSBjoern A. Zeeb 1106*a4128aadSBjoern A. Zeeb return iwl_pcie_txq_alloc_response(trans, txq, &hcmd); 1107*a4128aadSBjoern A. Zeeb 1108*a4128aadSBjoern A. Zeeb error: 1109*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free_memory(trans, txq); 1110*a4128aadSBjoern A. Zeeb return ret; 1111*a4128aadSBjoern A. Zeeb } 1112*a4128aadSBjoern A. Zeeb 1113*a4128aadSBjoern A. Zeeb void iwl_txq_dyn_free(struct iwl_trans *trans, int queue) 1114*a4128aadSBjoern A. Zeeb { 1115*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1116*a4128aadSBjoern A. Zeeb 1117*a4128aadSBjoern A. Zeeb if (WARN(queue >= IWL_MAX_TVQM_QUEUES, 1118*a4128aadSBjoern A. Zeeb "queue %d out of range", queue)) 1119*a4128aadSBjoern A. Zeeb return; 1120*a4128aadSBjoern A. Zeeb 1121*a4128aadSBjoern A. Zeeb /* 1122*a4128aadSBjoern A. Zeeb * Upon HW Rfkill - we stop the device, and then stop the queues 1123*a4128aadSBjoern A. Zeeb * in the op_mode. Just for the sake of the simplicity of the op_mode, 1124*a4128aadSBjoern A. Zeeb * allow the op_mode to call txq_disable after it already called 1125*a4128aadSBjoern A. Zeeb * stop_device. 1126*a4128aadSBjoern A. Zeeb */ 1127*a4128aadSBjoern A. Zeeb if (!test_and_clear_bit(queue, trans_pcie->txqs.queue_used)) { 1128*a4128aadSBjoern A. Zeeb WARN_ONCE(test_bit(STATUS_DEVICE_ENABLED, &trans->status), 1129*a4128aadSBjoern A. Zeeb "queue %d not used", queue); 1130*a4128aadSBjoern A. Zeeb return; 1131*a4128aadSBjoern A. Zeeb } 1132*a4128aadSBjoern A. Zeeb 1133*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free(trans, queue); 1134*a4128aadSBjoern A. Zeeb 1135*a4128aadSBjoern A. Zeeb IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", queue); 1136*a4128aadSBjoern A. Zeeb } 1137*a4128aadSBjoern A. Zeeb 1138*a4128aadSBjoern A. Zeeb void iwl_txq_gen2_tx_free(struct iwl_trans *trans) 1139*a4128aadSBjoern A. Zeeb { 1140*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1141*a4128aadSBjoern A. Zeeb int i; 1142*a4128aadSBjoern A. Zeeb 1143*a4128aadSBjoern A. Zeeb memset(trans_pcie->txqs.queue_used, 0, 1144*a4128aadSBjoern A. Zeeb sizeof(trans_pcie->txqs.queue_used)); 1145*a4128aadSBjoern A. Zeeb 1146*a4128aadSBjoern A. Zeeb /* Free all TX queues */ 1147*a4128aadSBjoern A. Zeeb for (i = 0; i < ARRAY_SIZE(trans_pcie->txqs.txq); i++) { 1148*a4128aadSBjoern A. Zeeb if (!trans_pcie->txqs.txq[i]) 1149*a4128aadSBjoern A. Zeeb continue; 1150*a4128aadSBjoern A. Zeeb 1151*a4128aadSBjoern A. Zeeb iwl_txq_gen2_free(trans, i); 1152*a4128aadSBjoern A. Zeeb } 1153*a4128aadSBjoern A. Zeeb } 1154*a4128aadSBjoern A. Zeeb 1155*a4128aadSBjoern A. Zeeb int iwl_txq_gen2_init(struct iwl_trans *trans, int txq_id, int queue_size) 1156*a4128aadSBjoern A. Zeeb { 1157*a4128aadSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1158*a4128aadSBjoern A. Zeeb struct iwl_txq *queue; 1159*a4128aadSBjoern A. Zeeb int ret; 1160*a4128aadSBjoern A. Zeeb 1161*a4128aadSBjoern A. Zeeb /* alloc and init the tx queue */ 1162*a4128aadSBjoern A. Zeeb if (!trans_pcie->txqs.txq[txq_id]) { 1163*a4128aadSBjoern A. Zeeb queue = kzalloc(sizeof(*queue), GFP_KERNEL); 1164*a4128aadSBjoern A. Zeeb if (!queue) { 1165*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Not enough memory for tx queue\n"); 1166*a4128aadSBjoern A. Zeeb return -ENOMEM; 1167*a4128aadSBjoern A. Zeeb } 1168*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id] = queue; 1169*a4128aadSBjoern A. Zeeb ret = iwl_pcie_txq_alloc(trans, queue, queue_size, true); 1170*a4128aadSBjoern A. Zeeb if (ret) { 1171*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Tx %d queue init failed\n", txq_id); 1172*a4128aadSBjoern A. Zeeb goto error; 1173*a4128aadSBjoern A. Zeeb } 1174*a4128aadSBjoern A. Zeeb } else { 1175*a4128aadSBjoern A. Zeeb queue = trans_pcie->txqs.txq[txq_id]; 1176*a4128aadSBjoern A. Zeeb } 1177*a4128aadSBjoern A. Zeeb 1178*a4128aadSBjoern A. Zeeb ret = iwl_txq_init(trans, queue, queue_size, 1179*a4128aadSBjoern A. Zeeb (txq_id == trans_pcie->txqs.cmd.q_id)); 1180*a4128aadSBjoern A. Zeeb if (ret) { 1181*a4128aadSBjoern A. Zeeb IWL_ERR(trans, "Tx %d queue alloc failed\n", txq_id); 1182*a4128aadSBjoern A. Zeeb goto error; 1183*a4128aadSBjoern A. Zeeb } 1184*a4128aadSBjoern A. Zeeb trans_pcie->txqs.txq[txq_id]->id = txq_id; 1185*a4128aadSBjoern A. Zeeb set_bit(txq_id, trans_pcie->txqs.queue_used); 1186*a4128aadSBjoern A. Zeeb 1187*a4128aadSBjoern A. Zeeb return 0; 1188*a4128aadSBjoern A. Zeeb 1189*a4128aadSBjoern A. Zeeb error: 1190*a4128aadSBjoern A. Zeeb iwl_txq_gen2_tx_free(trans); 1191*a4128aadSBjoern A. Zeeb return ret; 1192*a4128aadSBjoern A. Zeeb } 1193bfcc09ddSBjoern A. Zeeb 1194bfcc09ddSBjoern A. Zeeb /*************** HOST COMMAND QUEUE FUNCTIONS *****/ 1195bfcc09ddSBjoern A. Zeeb 1196bfcc09ddSBjoern A. Zeeb /* 1197bfcc09ddSBjoern A. Zeeb * iwl_pcie_gen2_enqueue_hcmd - enqueue a uCode command 1198bfcc09ddSBjoern A. Zeeb * @priv: device private data point 1199bfcc09ddSBjoern A. Zeeb * @cmd: a pointer to the ucode command structure 1200bfcc09ddSBjoern A. Zeeb * 1201bfcc09ddSBjoern A. Zeeb * The function returns < 0 values to indicate the operation 1202bfcc09ddSBjoern A. Zeeb * failed. On success, it returns the index (>= 0) of command in the 1203bfcc09ddSBjoern A. Zeeb * command queue. 1204bfcc09ddSBjoern A. Zeeb */ 1205bfcc09ddSBjoern A. Zeeb int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans, 1206bfcc09ddSBjoern A. Zeeb struct iwl_host_cmd *cmd) 1207bfcc09ddSBjoern A. Zeeb { 1208bfcc09ddSBjoern A. Zeeb struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 1209*a4128aadSBjoern A. Zeeb struct iwl_txq *txq = trans_pcie->txqs.txq[trans_pcie->txqs.cmd.q_id]; 1210bfcc09ddSBjoern A. Zeeb struct iwl_device_cmd *out_cmd; 1211bfcc09ddSBjoern A. Zeeb struct iwl_cmd_meta *out_meta; 1212bfcc09ddSBjoern A. Zeeb void *dup_buf = NULL; 1213bfcc09ddSBjoern A. Zeeb dma_addr_t phys_addr; 1214bfcc09ddSBjoern A. Zeeb int i, cmd_pos, idx; 1215bfcc09ddSBjoern A. Zeeb u16 copy_size, cmd_size, tb0_size; 1216bfcc09ddSBjoern A. Zeeb bool had_nocopy = false; 1217bfcc09ddSBjoern A. Zeeb u8 group_id = iwl_cmd_groupid(cmd->id); 1218bfcc09ddSBjoern A. Zeeb const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; 1219bfcc09ddSBjoern A. Zeeb u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; 1220bfcc09ddSBjoern A. Zeeb struct iwl_tfh_tfd *tfd; 1221bfcc09ddSBjoern A. Zeeb unsigned long flags; 1222bfcc09ddSBjoern A. Zeeb 1223*a4128aadSBjoern A. Zeeb if (WARN_ON(cmd->flags & CMD_BLOCK_TXQS)) 1224*a4128aadSBjoern A. Zeeb return -EINVAL; 1225*a4128aadSBjoern A. Zeeb 1226bfcc09ddSBjoern A. Zeeb copy_size = sizeof(struct iwl_cmd_header_wide); 1227bfcc09ddSBjoern A. Zeeb cmd_size = sizeof(struct iwl_cmd_header_wide); 1228bfcc09ddSBjoern A. Zeeb 1229bfcc09ddSBjoern A. Zeeb for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { 1230bfcc09ddSBjoern A. Zeeb cmddata[i] = cmd->data[i]; 1231bfcc09ddSBjoern A. Zeeb cmdlen[i] = cmd->len[i]; 1232bfcc09ddSBjoern A. Zeeb 1233bfcc09ddSBjoern A. Zeeb if (!cmd->len[i]) 1234bfcc09ddSBjoern A. Zeeb continue; 1235bfcc09ddSBjoern A. Zeeb 1236bfcc09ddSBjoern A. Zeeb /* need at least IWL_FIRST_TB_SIZE copied */ 1237bfcc09ddSBjoern A. Zeeb if (copy_size < IWL_FIRST_TB_SIZE) { 1238bfcc09ddSBjoern A. Zeeb int copy = IWL_FIRST_TB_SIZE - copy_size; 1239bfcc09ddSBjoern A. Zeeb 1240bfcc09ddSBjoern A. Zeeb if (copy > cmdlen[i]) 1241bfcc09ddSBjoern A. Zeeb copy = cmdlen[i]; 1242bfcc09ddSBjoern A. Zeeb cmdlen[i] -= copy; 1243bfcc09ddSBjoern A. Zeeb cmddata[i] += copy; 1244bfcc09ddSBjoern A. Zeeb copy_size += copy; 1245bfcc09ddSBjoern A. Zeeb } 1246bfcc09ddSBjoern A. Zeeb 1247bfcc09ddSBjoern A. Zeeb if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { 1248bfcc09ddSBjoern A. Zeeb had_nocopy = true; 1249bfcc09ddSBjoern A. Zeeb if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { 1250bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1251bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1252bfcc09ddSBjoern A. Zeeb } 1253bfcc09ddSBjoern A. Zeeb } else if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) { 1254bfcc09ddSBjoern A. Zeeb /* 1255bfcc09ddSBjoern A. Zeeb * This is also a chunk that isn't copied 1256bfcc09ddSBjoern A. Zeeb * to the static buffer so set had_nocopy. 1257bfcc09ddSBjoern A. Zeeb */ 1258bfcc09ddSBjoern A. Zeeb had_nocopy = true; 1259bfcc09ddSBjoern A. Zeeb 1260bfcc09ddSBjoern A. Zeeb /* only allowed once */ 1261bfcc09ddSBjoern A. Zeeb if (WARN_ON(dup_buf)) { 1262bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1263bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1264bfcc09ddSBjoern A. Zeeb } 1265bfcc09ddSBjoern A. Zeeb 1266bfcc09ddSBjoern A. Zeeb dup_buf = kmemdup(cmddata[i], cmdlen[i], 1267bfcc09ddSBjoern A. Zeeb GFP_ATOMIC); 1268bfcc09ddSBjoern A. Zeeb if (!dup_buf) 1269bfcc09ddSBjoern A. Zeeb return -ENOMEM; 1270bfcc09ddSBjoern A. Zeeb } else { 1271bfcc09ddSBjoern A. Zeeb /* NOCOPY must not be followed by normal! */ 1272bfcc09ddSBjoern A. Zeeb if (WARN_ON(had_nocopy)) { 1273bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1274bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1275bfcc09ddSBjoern A. Zeeb } 1276bfcc09ddSBjoern A. Zeeb copy_size += cmdlen[i]; 1277bfcc09ddSBjoern A. Zeeb } 1278bfcc09ddSBjoern A. Zeeb cmd_size += cmd->len[i]; 1279bfcc09ddSBjoern A. Zeeb } 1280bfcc09ddSBjoern A. Zeeb 1281bfcc09ddSBjoern A. Zeeb /* 1282bfcc09ddSBjoern A. Zeeb * If any of the command structures end up being larger than the 1283bfcc09ddSBjoern A. Zeeb * TFD_MAX_PAYLOAD_SIZE and they aren't dynamically allocated into 1284bfcc09ddSBjoern A. Zeeb * separate TFDs, then we will need to increase the size of the buffers 1285bfcc09ddSBjoern A. Zeeb */ 1286bfcc09ddSBjoern A. Zeeb if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, 1287bfcc09ddSBjoern A. Zeeb "Command %s (%#x) is too large (%d bytes)\n", 1288bfcc09ddSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd->id), cmd->id, copy_size)) { 1289bfcc09ddSBjoern A. Zeeb idx = -EINVAL; 1290bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1291bfcc09ddSBjoern A. Zeeb } 1292bfcc09ddSBjoern A. Zeeb 1293bfcc09ddSBjoern A. Zeeb spin_lock_irqsave(&txq->lock, flags); 1294bfcc09ddSBjoern A. Zeeb 1295bfcc09ddSBjoern A. Zeeb idx = iwl_txq_get_cmd_index(txq, txq->write_ptr); 1296bfcc09ddSBjoern A. Zeeb tfd = iwl_txq_get_tfd(trans, txq, txq->write_ptr); 1297bfcc09ddSBjoern A. Zeeb memset(tfd, 0, sizeof(*tfd)); 1298bfcc09ddSBjoern A. Zeeb 1299bfcc09ddSBjoern A. Zeeb if (iwl_txq_space(trans, txq) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { 1300bfcc09ddSBjoern A. Zeeb spin_unlock_irqrestore(&txq->lock, flags); 1301bfcc09ddSBjoern A. Zeeb 1302bfcc09ddSBjoern A. Zeeb IWL_ERR(trans, "No space in command queue\n"); 1303bfcc09ddSBjoern A. Zeeb iwl_op_mode_cmd_queue_full(trans->op_mode); 1304bfcc09ddSBjoern A. Zeeb idx = -ENOSPC; 1305bfcc09ddSBjoern A. Zeeb goto free_dup_buf; 1306bfcc09ddSBjoern A. Zeeb } 1307bfcc09ddSBjoern A. Zeeb 1308bfcc09ddSBjoern A. Zeeb out_cmd = txq->entries[idx].cmd; 1309bfcc09ddSBjoern A. Zeeb out_meta = &txq->entries[idx].meta; 1310bfcc09ddSBjoern A. Zeeb 1311*a4128aadSBjoern A. Zeeb /* re-initialize, this also marks the SG list as unused */ 1312bfcc09ddSBjoern A. Zeeb memset(out_meta, 0, sizeof(*out_meta)); 1313bfcc09ddSBjoern A. Zeeb if (cmd->flags & CMD_WANT_SKB) 1314bfcc09ddSBjoern A. Zeeb out_meta->source = cmd; 1315bfcc09ddSBjoern A. Zeeb 1316bfcc09ddSBjoern A. Zeeb /* set up the header */ 1317bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.cmd = iwl_cmd_opcode(cmd->id); 1318bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.group_id = group_id; 1319bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.version = iwl_cmd_version(cmd->id); 1320bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.length = 1321bfcc09ddSBjoern A. Zeeb cpu_to_le16(cmd_size - sizeof(struct iwl_cmd_header_wide)); 1322bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.reserved = 0; 1323bfcc09ddSBjoern A. Zeeb out_cmd->hdr_wide.sequence = 1324*a4128aadSBjoern A. Zeeb cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->txqs.cmd.q_id) | 1325bfcc09ddSBjoern A. Zeeb INDEX_TO_SEQ(txq->write_ptr)); 1326bfcc09ddSBjoern A. Zeeb 1327bfcc09ddSBjoern A. Zeeb cmd_pos = sizeof(struct iwl_cmd_header_wide); 1328bfcc09ddSBjoern A. Zeeb copy_size = sizeof(struct iwl_cmd_header_wide); 1329bfcc09ddSBjoern A. Zeeb 1330bfcc09ddSBjoern A. Zeeb /* and copy the data that needs to be copied */ 1331bfcc09ddSBjoern A. Zeeb for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { 1332bfcc09ddSBjoern A. Zeeb int copy; 1333bfcc09ddSBjoern A. Zeeb 1334bfcc09ddSBjoern A. Zeeb if (!cmd->len[i]) 1335bfcc09ddSBjoern A. Zeeb continue; 1336bfcc09ddSBjoern A. Zeeb 1337bfcc09ddSBjoern A. Zeeb /* copy everything if not nocopy/dup */ 1338bfcc09ddSBjoern A. Zeeb if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | 1339bfcc09ddSBjoern A. Zeeb IWL_HCMD_DFL_DUP))) { 1340bfcc09ddSBjoern A. Zeeb copy = cmd->len[i]; 1341bfcc09ddSBjoern A. Zeeb 1342bfcc09ddSBjoern A. Zeeb memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); 1343bfcc09ddSBjoern A. Zeeb cmd_pos += copy; 1344bfcc09ddSBjoern A. Zeeb copy_size += copy; 1345bfcc09ddSBjoern A. Zeeb continue; 1346bfcc09ddSBjoern A. Zeeb } 1347bfcc09ddSBjoern A. Zeeb 1348bfcc09ddSBjoern A. Zeeb /* 1349bfcc09ddSBjoern A. Zeeb * Otherwise we need at least IWL_FIRST_TB_SIZE copied 1350bfcc09ddSBjoern A. Zeeb * in total (for bi-directional DMA), but copy up to what 1351bfcc09ddSBjoern A. Zeeb * we can fit into the payload for debug dump purposes. 1352bfcc09ddSBjoern A. Zeeb */ 1353bfcc09ddSBjoern A. Zeeb copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]); 1354bfcc09ddSBjoern A. Zeeb 1355bfcc09ddSBjoern A. Zeeb memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); 1356bfcc09ddSBjoern A. Zeeb cmd_pos += copy; 1357bfcc09ddSBjoern A. Zeeb 1358bfcc09ddSBjoern A. Zeeb /* However, treat copy_size the proper way, we need it below */ 1359bfcc09ddSBjoern A. Zeeb if (copy_size < IWL_FIRST_TB_SIZE) { 1360bfcc09ddSBjoern A. Zeeb copy = IWL_FIRST_TB_SIZE - copy_size; 1361bfcc09ddSBjoern A. Zeeb 1362bfcc09ddSBjoern A. Zeeb if (copy > cmd->len[i]) 1363bfcc09ddSBjoern A. Zeeb copy = cmd->len[i]; 1364bfcc09ddSBjoern A. Zeeb copy_size += copy; 1365bfcc09ddSBjoern A. Zeeb } 1366bfcc09ddSBjoern A. Zeeb } 1367bfcc09ddSBjoern A. Zeeb 1368bfcc09ddSBjoern A. Zeeb IWL_DEBUG_HC(trans, 1369bfcc09ddSBjoern A. Zeeb "Sending command %s (%.2x.%.2x), seq: 0x%04X, %d bytes at %d[%d]:%d\n", 1370bfcc09ddSBjoern A. Zeeb iwl_get_cmd_string(trans, cmd->id), group_id, 1371bfcc09ddSBjoern A. Zeeb out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), 1372*a4128aadSBjoern A. Zeeb cmd_size, txq->write_ptr, idx, trans_pcie->txqs.cmd.q_id); 1373bfcc09ddSBjoern A. Zeeb 1374bfcc09ddSBjoern A. Zeeb /* start the TFD with the minimum copy bytes */ 1375bfcc09ddSBjoern A. Zeeb tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE); 1376bfcc09ddSBjoern A. Zeeb memcpy(&txq->first_tb_bufs[idx], out_cmd, tb0_size); 1377bfcc09ddSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, iwl_txq_get_first_tb_dma(txq, idx), 1378bfcc09ddSBjoern A. Zeeb tb0_size); 1379bfcc09ddSBjoern A. Zeeb 1380bfcc09ddSBjoern A. Zeeb /* map first command fragment, if any remains */ 1381bfcc09ddSBjoern A. Zeeb if (copy_size > tb0_size) { 1382bfcc09ddSBjoern A. Zeeb phys_addr = dma_map_single(trans->dev, 1383bfcc09ddSBjoern A. Zeeb (u8 *)out_cmd + tb0_size, 1384bfcc09ddSBjoern A. Zeeb copy_size - tb0_size, 1385bfcc09ddSBjoern A. Zeeb DMA_TO_DEVICE); 1386bfcc09ddSBjoern A. Zeeb if (dma_mapping_error(trans->dev, phys_addr)) { 1387bfcc09ddSBjoern A. Zeeb idx = -ENOMEM; 1388bfcc09ddSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, out_meta, tfd); 1389bfcc09ddSBjoern A. Zeeb goto out; 1390bfcc09ddSBjoern A. Zeeb } 1391bfcc09ddSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, phys_addr, 1392bfcc09ddSBjoern A. Zeeb copy_size - tb0_size); 1393bfcc09ddSBjoern A. Zeeb } 1394bfcc09ddSBjoern A. Zeeb 1395bfcc09ddSBjoern A. Zeeb /* map the remaining (adjusted) nocopy/dup fragments */ 1396bfcc09ddSBjoern A. Zeeb for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { 1397bfcc09ddSBjoern A. Zeeb void *data = (void *)(uintptr_t)cmddata[i]; 1398bfcc09ddSBjoern A. Zeeb 1399bfcc09ddSBjoern A. Zeeb if (!cmdlen[i]) 1400bfcc09ddSBjoern A. Zeeb continue; 1401bfcc09ddSBjoern A. Zeeb if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | 1402bfcc09ddSBjoern A. Zeeb IWL_HCMD_DFL_DUP))) 1403bfcc09ddSBjoern A. Zeeb continue; 1404bfcc09ddSBjoern A. Zeeb if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) 1405bfcc09ddSBjoern A. Zeeb data = dup_buf; 1406bfcc09ddSBjoern A. Zeeb phys_addr = dma_map_single(trans->dev, data, 1407bfcc09ddSBjoern A. Zeeb cmdlen[i], DMA_TO_DEVICE); 1408bfcc09ddSBjoern A. Zeeb if (dma_mapping_error(trans->dev, phys_addr)) { 1409bfcc09ddSBjoern A. Zeeb idx = -ENOMEM; 1410bfcc09ddSBjoern A. Zeeb iwl_txq_gen2_tfd_unmap(trans, out_meta, tfd); 1411bfcc09ddSBjoern A. Zeeb goto out; 1412bfcc09ddSBjoern A. Zeeb } 1413bfcc09ddSBjoern A. Zeeb iwl_txq_gen2_set_tb(trans, tfd, phys_addr, cmdlen[i]); 1414bfcc09ddSBjoern A. Zeeb } 1415bfcc09ddSBjoern A. Zeeb 1416bfcc09ddSBjoern A. Zeeb BUILD_BUG_ON(IWL_TFH_NUM_TBS > sizeof(out_meta->tbs) * BITS_PER_BYTE); 1417bfcc09ddSBjoern A. Zeeb out_meta->flags = cmd->flags; 1418bfcc09ddSBjoern A. Zeeb if (WARN_ON_ONCE(txq->entries[idx].free_buf)) 1419bfcc09ddSBjoern A. Zeeb kfree_sensitive(txq->entries[idx].free_buf); 1420bfcc09ddSBjoern A. Zeeb txq->entries[idx].free_buf = dup_buf; 1421bfcc09ddSBjoern A. Zeeb 1422bfcc09ddSBjoern A. Zeeb trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr_wide); 1423bfcc09ddSBjoern A. Zeeb 1424bfcc09ddSBjoern A. Zeeb /* start timer if queue currently empty */ 1425bfcc09ddSBjoern A. Zeeb if (txq->read_ptr == txq->write_ptr && txq->wd_timeout) 1426bfcc09ddSBjoern A. Zeeb mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout); 1427bfcc09ddSBjoern A. Zeeb 1428bfcc09ddSBjoern A. Zeeb spin_lock(&trans_pcie->reg_lock); 1429bfcc09ddSBjoern A. Zeeb /* Increment and update queue's write index */ 1430bfcc09ddSBjoern A. Zeeb txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr); 1431bfcc09ddSBjoern A. Zeeb iwl_txq_inc_wr_ptr(trans, txq); 1432bfcc09ddSBjoern A. Zeeb spin_unlock(&trans_pcie->reg_lock); 1433bfcc09ddSBjoern A. Zeeb 1434bfcc09ddSBjoern A. Zeeb out: 1435bfcc09ddSBjoern A. Zeeb spin_unlock_irqrestore(&txq->lock, flags); 1436bfcc09ddSBjoern A. Zeeb free_dup_buf: 1437bfcc09ddSBjoern A. Zeeb if (idx < 0) 1438bfcc09ddSBjoern A. Zeeb kfree(dup_buf); 1439bfcc09ddSBjoern A. Zeeb return idx; 1440bfcc09ddSBjoern A. Zeeb } 1441