10cd1ad2dSMordechay Goodstein /****************************************************************************** 20cd1ad2dSMordechay Goodstein * 30cd1ad2dSMordechay Goodstein * This file is provided under a dual BSD/GPLv2 license. When using or 40cd1ad2dSMordechay Goodstein * redistributing this file, you may do so under either license. 50cd1ad2dSMordechay Goodstein * 60cd1ad2dSMordechay Goodstein * GPL LICENSE SUMMARY 70cd1ad2dSMordechay Goodstein * 80cd1ad2dSMordechay Goodstein * Copyright(c) 2020 Intel Corporation 90cd1ad2dSMordechay Goodstein * 100cd1ad2dSMordechay Goodstein * This program is free software; you can redistribute it and/or modify it 110cd1ad2dSMordechay Goodstein * under the terms of version 2 of the GNU General Public License as 120cd1ad2dSMordechay Goodstein * published by the Free Software Foundation. 130cd1ad2dSMordechay Goodstein * 140cd1ad2dSMordechay Goodstein * This program is distributed in the hope that it will be useful, but WITHOUT 150cd1ad2dSMordechay Goodstein * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 160cd1ad2dSMordechay Goodstein * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 170cd1ad2dSMordechay Goodstein * more details. 180cd1ad2dSMordechay Goodstein * 190cd1ad2dSMordechay Goodstein * The full GNU General Public License is included in this distribution in the 200cd1ad2dSMordechay Goodstein * file called COPYING. 210cd1ad2dSMordechay Goodstein * 220cd1ad2dSMordechay Goodstein * Contact Information: 230cd1ad2dSMordechay Goodstein * Intel Linux Wireless <linuxwifi@intel.com> 240cd1ad2dSMordechay Goodstein * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 250cd1ad2dSMordechay Goodstein * 260cd1ad2dSMordechay Goodstein * BSD LICENSE 270cd1ad2dSMordechay Goodstein * 280cd1ad2dSMordechay Goodstein * Copyright(c) 2020 Intel Corporation 290cd1ad2dSMordechay Goodstein * All rights reserved. 300cd1ad2dSMordechay Goodstein * 310cd1ad2dSMordechay Goodstein * Redistribution and use in source and binary forms, with or without 320cd1ad2dSMordechay Goodstein * modification, are permitted provided that the following conditions 330cd1ad2dSMordechay Goodstein * are met: 340cd1ad2dSMordechay Goodstein * 350cd1ad2dSMordechay Goodstein * * Redistributions of source code must retain the above copyright 360cd1ad2dSMordechay Goodstein * notice, this list of conditions and the following disclaimer. 370cd1ad2dSMordechay Goodstein * * Redistributions in binary form must reproduce the above copyright 380cd1ad2dSMordechay Goodstein * notice, this list of conditions and the following disclaimer in 390cd1ad2dSMordechay Goodstein * the documentation and/or other materials provided with the 400cd1ad2dSMordechay Goodstein * distribution. 410cd1ad2dSMordechay Goodstein * * Neither the name Intel Corporation nor the names of its 420cd1ad2dSMordechay Goodstein * contributors may be used to endorse or promote products derived 430cd1ad2dSMordechay Goodstein * from this software without specific prior written permission. 440cd1ad2dSMordechay Goodstein * 450cd1ad2dSMordechay Goodstein * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 460cd1ad2dSMordechay Goodstein * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 470cd1ad2dSMordechay Goodstein * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 480cd1ad2dSMordechay Goodstein * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 490cd1ad2dSMordechay Goodstein * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 500cd1ad2dSMordechay Goodstein * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 510cd1ad2dSMordechay Goodstein * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 520cd1ad2dSMordechay Goodstein * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 530cd1ad2dSMordechay Goodstein * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 540cd1ad2dSMordechay Goodstein * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 550cd1ad2dSMordechay Goodstein * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 560cd1ad2dSMordechay Goodstein * 570cd1ad2dSMordechay Goodstein *****************************************************************************/ 580cd1ad2dSMordechay Goodstein #ifndef __iwl_trans_queue_tx_h__ 590cd1ad2dSMordechay Goodstein #define __iwl_trans_queue_tx_h__ 600cd1ad2dSMordechay Goodstein #include "iwl-fh.h" 610cd1ad2dSMordechay Goodstein #include "fw/api/tx.h" 620cd1ad2dSMordechay Goodstein 630cd1ad2dSMordechay Goodstein struct iwl_tso_hdr_page { 640cd1ad2dSMordechay Goodstein struct page *page; 650cd1ad2dSMordechay Goodstein u8 *pos; 660cd1ad2dSMordechay Goodstein }; 670cd1ad2dSMordechay Goodstein 680cd1ad2dSMordechay Goodstein static inline dma_addr_t 690cd1ad2dSMordechay Goodstein iwl_txq_get_first_tb_dma(struct iwl_txq *txq, int idx) 700cd1ad2dSMordechay Goodstein { 710cd1ad2dSMordechay Goodstein return txq->first_tb_dma + 720cd1ad2dSMordechay Goodstein sizeof(struct iwl_pcie_first_tb_buf) * idx; 730cd1ad2dSMordechay Goodstein } 740cd1ad2dSMordechay Goodstein 750cd1ad2dSMordechay Goodstein static inline u16 iwl_txq_get_cmd_index(const struct iwl_txq *q, u32 index) 760cd1ad2dSMordechay Goodstein { 770cd1ad2dSMordechay Goodstein return index & (q->n_window - 1); 780cd1ad2dSMordechay Goodstein } 790cd1ad2dSMordechay Goodstein 800cd1ad2dSMordechay Goodstein void iwl_txq_gen2_unmap(struct iwl_trans *trans, int txq_id); 810cd1ad2dSMordechay Goodstein 820cd1ad2dSMordechay Goodstein static inline void iwl_wake_queue(struct iwl_trans *trans, 830cd1ad2dSMordechay Goodstein struct iwl_txq *txq) 840cd1ad2dSMordechay Goodstein { 850cd1ad2dSMordechay Goodstein if (test_and_clear_bit(txq->id, trans->txqs.queue_stopped)) { 860cd1ad2dSMordechay Goodstein IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d\n", txq->id); 870cd1ad2dSMordechay Goodstein iwl_op_mode_queue_not_full(trans->op_mode, txq->id); 880cd1ad2dSMordechay Goodstein } 890cd1ad2dSMordechay Goodstein } 900cd1ad2dSMordechay Goodstein 910cd1ad2dSMordechay Goodstein static inline void *iwl_txq_get_tfd(struct iwl_trans *trans, 920cd1ad2dSMordechay Goodstein struct iwl_txq *txq, int idx) 930cd1ad2dSMordechay Goodstein { 940cd1ad2dSMordechay Goodstein if (trans->trans_cfg->use_tfh) 950cd1ad2dSMordechay Goodstein idx = iwl_txq_get_cmd_index(txq, idx); 960cd1ad2dSMordechay Goodstein 970cd1ad2dSMordechay Goodstein return txq->tfds + trans->txqs.tfd.size * idx; 980cd1ad2dSMordechay Goodstein } 990cd1ad2dSMordechay Goodstein 1000cd1ad2dSMordechay Goodstein int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, 1010cd1ad2dSMordechay Goodstein bool cmd_queue); 1020cd1ad2dSMordechay Goodstein /* 1030cd1ad2dSMordechay Goodstein * We need this inline in case dma_addr_t is only 32-bits - since the 1040cd1ad2dSMordechay Goodstein * hardware is always 64-bit, the issue can still occur in that case, 1050cd1ad2dSMordechay Goodstein * so use u64 for 'phys' here to force the addition in 64-bit. 1060cd1ad2dSMordechay Goodstein */ 1070cd1ad2dSMordechay Goodstein static inline bool iwl_txq_crosses_4g_boundary(u64 phys, u16 len) 1080cd1ad2dSMordechay Goodstein { 1090cd1ad2dSMordechay Goodstein return upper_32_bits(phys) != upper_32_bits(phys + len); 1100cd1ad2dSMordechay Goodstein } 1110cd1ad2dSMordechay Goodstein 1120cd1ad2dSMordechay Goodstein int iwl_txq_space(struct iwl_trans *trans, const struct iwl_txq *q); 1130cd1ad2dSMordechay Goodstein 1140cd1ad2dSMordechay Goodstein static inline void iwl_txq_stop(struct iwl_trans *trans, struct iwl_txq *txq) 1150cd1ad2dSMordechay Goodstein { 1160cd1ad2dSMordechay Goodstein if (!test_and_set_bit(txq->id, trans->txqs.queue_stopped)) { 1170cd1ad2dSMordechay Goodstein iwl_op_mode_queue_full(trans->op_mode, txq->id); 1180cd1ad2dSMordechay Goodstein IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d\n", txq->id); 1190cd1ad2dSMordechay Goodstein } else { 1200cd1ad2dSMordechay Goodstein IWL_DEBUG_TX_QUEUES(trans, "hwq %d already stopped\n", 1210cd1ad2dSMordechay Goodstein txq->id); 1220cd1ad2dSMordechay Goodstein } 1230cd1ad2dSMordechay Goodstein } 1240cd1ad2dSMordechay Goodstein 1250cd1ad2dSMordechay Goodstein /** 1260cd1ad2dSMordechay Goodstein * iwl_txq_inc_wrap - increment queue index, wrap back to beginning 1270cd1ad2dSMordechay Goodstein * @index -- current index 1280cd1ad2dSMordechay Goodstein */ 1290cd1ad2dSMordechay Goodstein static inline int iwl_txq_inc_wrap(struct iwl_trans *trans, int index) 1300cd1ad2dSMordechay Goodstein { 1310cd1ad2dSMordechay Goodstein return ++index & 1320cd1ad2dSMordechay Goodstein (trans->trans_cfg->base_params->max_tfd_queue_size - 1); 1330cd1ad2dSMordechay Goodstein } 1340cd1ad2dSMordechay Goodstein 1350cd1ad2dSMordechay Goodstein /** 1360cd1ad2dSMordechay Goodstein * iwl_txq_dec_wrap - decrement queue index, wrap back to end 1370cd1ad2dSMordechay Goodstein * @index -- current index 1380cd1ad2dSMordechay Goodstein */ 1390cd1ad2dSMordechay Goodstein static inline int iwl_txq_dec_wrap(struct iwl_trans *trans, int index) 1400cd1ad2dSMordechay Goodstein { 1410cd1ad2dSMordechay Goodstein return --index & 1420cd1ad2dSMordechay Goodstein (trans->trans_cfg->base_params->max_tfd_queue_size - 1); 1430cd1ad2dSMordechay Goodstein } 1440cd1ad2dSMordechay Goodstein 1450cd1ad2dSMordechay Goodstein static inline bool iwl_txq_used(const struct iwl_txq *q, int i) 1460cd1ad2dSMordechay Goodstein { 1470cd1ad2dSMordechay Goodstein int index = iwl_txq_get_cmd_index(q, i); 1480cd1ad2dSMordechay Goodstein int r = iwl_txq_get_cmd_index(q, q->read_ptr); 1490cd1ad2dSMordechay Goodstein int w = iwl_txq_get_cmd_index(q, q->write_ptr); 1500cd1ad2dSMordechay Goodstein 1510cd1ad2dSMordechay Goodstein return w >= r ? 1520cd1ad2dSMordechay Goodstein (index >= r && index < w) : 1530cd1ad2dSMordechay Goodstein !(index < r && index >= w); 1540cd1ad2dSMordechay Goodstein } 1550cd1ad2dSMordechay Goodstein 1560cd1ad2dSMordechay Goodstein void iwl_txq_free_tso_page(struct iwl_trans *trans, struct sk_buff *skb); 1570cd1ad2dSMordechay Goodstein 1580cd1ad2dSMordechay Goodstein void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq); 1590cd1ad2dSMordechay Goodstein 1600cd1ad2dSMordechay Goodstein int iwl_txq_gen2_set_tb(struct iwl_trans *trans, 1610cd1ad2dSMordechay Goodstein struct iwl_tfh_tfd *tfd, dma_addr_t addr, 1620cd1ad2dSMordechay Goodstein u16 len); 1630cd1ad2dSMordechay Goodstein 1640cd1ad2dSMordechay Goodstein void iwl_txq_gen2_tfd_unmap(struct iwl_trans *trans, 1650cd1ad2dSMordechay Goodstein struct iwl_cmd_meta *meta, 1660cd1ad2dSMordechay Goodstein struct iwl_tfh_tfd *tfd); 1670cd1ad2dSMordechay Goodstein 1680cd1ad2dSMordechay Goodstein int iwl_txq_dyn_alloc(struct iwl_trans *trans, 1690cd1ad2dSMordechay Goodstein __le16 flags, u8 sta_id, u8 tid, 1700cd1ad2dSMordechay Goodstein int cmd_id, int size, 1710cd1ad2dSMordechay Goodstein unsigned int timeout); 1720cd1ad2dSMordechay Goodstein 1730cd1ad2dSMordechay Goodstein int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, 1740cd1ad2dSMordechay Goodstein struct iwl_device_tx_cmd *dev_cmd, int txq_id); 1750cd1ad2dSMordechay Goodstein 1760cd1ad2dSMordechay Goodstein void iwl_txq_dyn_free(struct iwl_trans *trans, int queue); 1770cd1ad2dSMordechay Goodstein void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq); 1780cd1ad2dSMordechay Goodstein void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq); 1790cd1ad2dSMordechay Goodstein void iwl_txq_gen2_tx_stop(struct iwl_trans *trans); 1800cd1ad2dSMordechay Goodstein void iwl_txq_gen2_tx_free(struct iwl_trans *trans); 1810cd1ad2dSMordechay Goodstein int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num, 1820cd1ad2dSMordechay Goodstein bool cmd_queue); 1830cd1ad2dSMordechay Goodstein int iwl_txq_gen2_init(struct iwl_trans *trans, int txq_id, int queue_size); 1840cd1ad2dSMordechay Goodstein #ifdef CONFIG_INET 1850cd1ad2dSMordechay Goodstein struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len, 1860cd1ad2dSMordechay Goodstein struct sk_buff *skb); 1870cd1ad2dSMordechay Goodstein #endif 1880179bfffSMordechay Goodstein static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_trans *trans, 1890179bfffSMordechay Goodstein void *_tfd) 1900179bfffSMordechay Goodstein { 1910179bfffSMordechay Goodstein struct iwl_tfd *tfd; 1920179bfffSMordechay Goodstein 1930179bfffSMordechay Goodstein if (trans->trans_cfg->use_tfh) { 1940179bfffSMordechay Goodstein struct iwl_tfh_tfd *tfd = _tfd; 1950179bfffSMordechay Goodstein 1960179bfffSMordechay Goodstein return le16_to_cpu(tfd->num_tbs) & 0x1f; 1970179bfffSMordechay Goodstein } 1980179bfffSMordechay Goodstein 1990179bfffSMordechay Goodstein tfd = (struct iwl_tfd *)_tfd; 2000179bfffSMordechay Goodstein return tfd->num_tbs & 0x1f; 2010179bfffSMordechay Goodstein } 2020179bfffSMordechay Goodstein 2030179bfffSMordechay Goodstein static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans, 2040179bfffSMordechay Goodstein void *_tfd, u8 idx) 2050179bfffSMordechay Goodstein { 2060179bfffSMordechay Goodstein struct iwl_tfd *tfd; 2070179bfffSMordechay Goodstein struct iwl_tfd_tb *tb; 2080179bfffSMordechay Goodstein 2090179bfffSMordechay Goodstein if (trans->trans_cfg->use_tfh) { 2100179bfffSMordechay Goodstein struct iwl_tfh_tfd *tfd = _tfd; 2110179bfffSMordechay Goodstein struct iwl_tfh_tb *tb = &tfd->tbs[idx]; 2120179bfffSMordechay Goodstein 2130179bfffSMordechay Goodstein return le16_to_cpu(tb->tb_len); 2140179bfffSMordechay Goodstein } 2150179bfffSMordechay Goodstein 2160179bfffSMordechay Goodstein tfd = (struct iwl_tfd *)_tfd; 2170179bfffSMordechay Goodstein tb = &tfd->tbs[idx]; 2180179bfffSMordechay Goodstein 2190179bfffSMordechay Goodstein return le16_to_cpu(tb->hi_n_len) >> 4; 2200179bfffSMordechay Goodstein } 2210179bfffSMordechay Goodstein 2220179bfffSMordechay Goodstein void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans, 2230179bfffSMordechay Goodstein struct iwl_cmd_meta *meta, 2240179bfffSMordechay Goodstein struct iwl_txq *txq, int index); 2250179bfffSMordechay Goodstein void iwl_txq_gen1_inval_byte_cnt_tbl(struct iwl_trans *trans, 2260179bfffSMordechay Goodstein struct iwl_txq *txq); 2270179bfffSMordechay Goodstein void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans, 2280179bfffSMordechay Goodstein struct iwl_txq *txq, u16 byte_cnt, 2290179bfffSMordechay Goodstein int num_tbs); 230*a4450980SMordechay Goodstein void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn, 231*a4450980SMordechay Goodstein struct sk_buff_head *skbs); 232*a4450980SMordechay Goodstein void iwl_txq_set_q_ptrs(struct iwl_trans *trans, int txq_id, int ptr); 233*a4450980SMordechay Goodstein void iwl_trans_txq_freeze_timer(struct iwl_trans *trans, unsigned long txqs, 234*a4450980SMordechay Goodstein bool freeze); 235*a4450980SMordechay Goodstein void iwl_txq_progress(struct iwl_txq *txq); 236*a4450980SMordechay Goodstein void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq); 2370cd1ad2dSMordechay Goodstein #endif /* __iwl_trans_queue_tx_h__ */ 238