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);
2300cd1ad2dSMordechay Goodstein #endif /* __iwl_trans_queue_tx_h__ */
231