18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file is part of wl1251
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 1998-2007 Texas Instruments Incorporated
68c2ecf20Sopenharmony_ci * Copyright (C) 2008 Nokia Corporation
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef __WL1251_TX_H__
108c2ecf20Sopenharmony_ci#define __WL1251_TX_H__
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/bitops.h>
138c2ecf20Sopenharmony_ci#include "acx.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * TX PATH
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * The Tx path uses a double buffer and a tx_control structure, each located
208c2ecf20Sopenharmony_ci * at a fixed address in the device's memory. On startup, the host retrieves
218c2ecf20Sopenharmony_ci * the pointers to these addresses. A double buffer allows for continuous data
228c2ecf20Sopenharmony_ci * flow towards the device. The host keeps track of which buffer is available
238c2ecf20Sopenharmony_ci * and alternates between these two buffers on a per packet basis.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * The size of each of the two buffers is large enough to hold the longest
268c2ecf20Sopenharmony_ci * 802.3 packet - maximum size Ethernet packet + header + descriptor.
278c2ecf20Sopenharmony_ci * TX complete indication will be received a-synchronously in a TX done cyclic
288c2ecf20Sopenharmony_ci * buffer which is composed of 16 tx_result descriptors structures and is used
298c2ecf20Sopenharmony_ci * in a cyclic manner.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * The TX (HOST) procedure is as follows:
328c2ecf20Sopenharmony_ci * 1. Read the Tx path status, that will give the data_out_count.
338c2ecf20Sopenharmony_ci * 2. goto 1, if not possible.
348c2ecf20Sopenharmony_ci *    i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double
358c2ecf20Sopenharmony_ci *    buffer).
368c2ecf20Sopenharmony_ci * 3. Copy the packet (preceded by double_buffer_desc), if possible.
378c2ecf20Sopenharmony_ci *    i.e. if data_in_count - data_out_count < HwBuffer size (2 for double
388c2ecf20Sopenharmony_ci *    buffer).
398c2ecf20Sopenharmony_ci * 4. increment data_in_count.
408c2ecf20Sopenharmony_ci * 5. Inform the firmware by generating a firmware internal interrupt.
418c2ecf20Sopenharmony_ci * 6. FW will increment data_out_count after it reads the buffer.
428c2ecf20Sopenharmony_ci *
438c2ecf20Sopenharmony_ci * The TX Complete procedure:
448c2ecf20Sopenharmony_ci * 1. To get a TX complete indication the host enables the tx_complete flag in
458c2ecf20Sopenharmony_ci *    the TX descriptor Structure.
468c2ecf20Sopenharmony_ci * 2. For each packet with a Tx Complete field set, the firmware adds the
478c2ecf20Sopenharmony_ci *    transmit results to the cyclic buffer (txDoneRing) and sets both done_1
488c2ecf20Sopenharmony_ci *    and done_2 to 1 to indicate driver ownership.
498c2ecf20Sopenharmony_ci * 3. The firmware sends a Tx Complete interrupt to the host to trigger the
508c2ecf20Sopenharmony_ci *    host to process the new data. Note: interrupt will be send per packet if
518c2ecf20Sopenharmony_ci *    TX complete indication was requested in tx_control or per crossing
528c2ecf20Sopenharmony_ci *    aggregation threshold.
538c2ecf20Sopenharmony_ci * 4. After receiving the Tx Complete interrupt, the host reads the
548c2ecf20Sopenharmony_ci *    TxDescriptorDone information in a cyclic manner and clears both done_1
558c2ecf20Sopenharmony_ci *    and done_2 fields.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define TX_COMPLETE_REQUIRED_BIT	0x80
608c2ecf20Sopenharmony_ci#define TX_STATUS_DATA_OUT_COUNT_MASK   0xf
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define WL1251_TX_ALIGN_TO 4
638c2ecf20Sopenharmony_ci#define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \
648c2ecf20Sopenharmony_ci			     ~(WL1251_TX_ALIGN_TO - 1))
658c2ecf20Sopenharmony_ci#define WL1251_TKIP_IV_SPACE 4
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistruct tx_control {
688c2ecf20Sopenharmony_ci	/* Rate Policy (class) index */
698c2ecf20Sopenharmony_ci	unsigned rate_policy:3;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	/* When set, no ack policy is expected */
728c2ecf20Sopenharmony_ci	unsigned ack_policy:1;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/*
758c2ecf20Sopenharmony_ci	 * Packet type:
768c2ecf20Sopenharmony_ci	 * 0 -> 802.11
778c2ecf20Sopenharmony_ci	 * 1 -> 802.3
788c2ecf20Sopenharmony_ci	 * 2 -> IP
798c2ecf20Sopenharmony_ci	 * 3 -> raw codec
808c2ecf20Sopenharmony_ci	 */
818c2ecf20Sopenharmony_ci	unsigned packet_type:2;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	/* If set, this is a QoS-Null or QoS-Data frame */
848c2ecf20Sopenharmony_ci	unsigned qos:1;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/*
878c2ecf20Sopenharmony_ci	 * If set, the target triggers the tx complete INT
888c2ecf20Sopenharmony_ci	 * upon frame sending completion.
898c2ecf20Sopenharmony_ci	 */
908c2ecf20Sopenharmony_ci	unsigned tx_complete:1;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	/* 2 bytes padding before packet header */
938c2ecf20Sopenharmony_ci	unsigned xfer_pad:1;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	unsigned reserved:7;
968c2ecf20Sopenharmony_ci} __packed;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistruct tx_double_buffer_desc {
1008c2ecf20Sopenharmony_ci	/* Length of payload, including headers. */
1018c2ecf20Sopenharmony_ci	__le16 length;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	/*
1048c2ecf20Sopenharmony_ci	 * A bit mask that specifies the initial rate to be used
1058c2ecf20Sopenharmony_ci	 * Possible values are:
1068c2ecf20Sopenharmony_ci	 * 0x0001 - 1Mbits
1078c2ecf20Sopenharmony_ci	 * 0x0002 - 2Mbits
1088c2ecf20Sopenharmony_ci	 * 0x0004 - 5.5Mbits
1098c2ecf20Sopenharmony_ci	 * 0x0008 - 6Mbits
1108c2ecf20Sopenharmony_ci	 * 0x0010 - 9Mbits
1118c2ecf20Sopenharmony_ci	 * 0x0020 - 11Mbits
1128c2ecf20Sopenharmony_ci	 * 0x0040 - 12Mbits
1138c2ecf20Sopenharmony_ci	 * 0x0080 - 18Mbits
1148c2ecf20Sopenharmony_ci	 * 0x0100 - 22Mbits
1158c2ecf20Sopenharmony_ci	 * 0x0200 - 24Mbits
1168c2ecf20Sopenharmony_ci	 * 0x0400 - 36Mbits
1178c2ecf20Sopenharmony_ci	 * 0x0800 - 48Mbits
1188c2ecf20Sopenharmony_ci	 * 0x1000 - 54Mbits
1198c2ecf20Sopenharmony_ci	 */
1208c2ecf20Sopenharmony_ci	__le16 rate;
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	/* Time in us that a packet can spend in the target */
1238c2ecf20Sopenharmony_ci	__le32 expiry_time;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/* index of the TX queue used for this packet */
1268c2ecf20Sopenharmony_ci	u8 xmit_queue;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	/* Used to identify a packet */
1298c2ecf20Sopenharmony_ci	u8 id;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	struct tx_control control;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	/*
1348c2ecf20Sopenharmony_ci	 * The FW should cut the packet into fragments
1358c2ecf20Sopenharmony_ci	 * of this size.
1368c2ecf20Sopenharmony_ci	 */
1378c2ecf20Sopenharmony_ci	__le16 frag_threshold;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	/* Numbers of HW queue blocks to be allocated */
1408c2ecf20Sopenharmony_ci	u8 num_mem_blocks;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	u8 reserved;
1438c2ecf20Sopenharmony_ci} __packed;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cienum {
1468c2ecf20Sopenharmony_ci	TX_SUCCESS              = 0,
1478c2ecf20Sopenharmony_ci	TX_DMA_ERROR            = BIT(7),
1488c2ecf20Sopenharmony_ci	TX_DISABLED             = BIT(6),
1498c2ecf20Sopenharmony_ci	TX_RETRY_EXCEEDED       = BIT(5),
1508c2ecf20Sopenharmony_ci	TX_TIMEOUT              = BIT(4),
1518c2ecf20Sopenharmony_ci	TX_KEY_NOT_FOUND        = BIT(3),
1528c2ecf20Sopenharmony_ci	TX_ENCRYPT_FAIL         = BIT(2),
1538c2ecf20Sopenharmony_ci	TX_UNAVAILABLE_PRIORITY = BIT(1),
1548c2ecf20Sopenharmony_ci};
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistruct tx_result {
1578c2ecf20Sopenharmony_ci	/*
1588c2ecf20Sopenharmony_ci	 * Ownership synchronization between the host and
1598c2ecf20Sopenharmony_ci	 * the firmware. If done_1 and done_2 are cleared,
1608c2ecf20Sopenharmony_ci	 * owned by the FW (no info ready).
1618c2ecf20Sopenharmony_ci	 */
1628c2ecf20Sopenharmony_ci	u8 done_1;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	/* same as double_buffer_desc->id */
1658c2ecf20Sopenharmony_ci	u8 id;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	/*
1688c2ecf20Sopenharmony_ci	 * Total air access duration consumed by this
1698c2ecf20Sopenharmony_ci	 * packet, including all retries and overheads.
1708c2ecf20Sopenharmony_ci	 */
1718c2ecf20Sopenharmony_ci	u16 medium_usage;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	/* Total media delay (from 1st EDCA AIFS counter until TX Complete). */
1748c2ecf20Sopenharmony_ci	u32 medium_delay;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	/* Time between host xfer and tx complete */
1778c2ecf20Sopenharmony_ci	u32 fw_hnadling_time;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/* The LS-byte of the last TKIP sequence number. */
1808c2ecf20Sopenharmony_ci	u8 lsb_seq_num;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	/* Retry count */
1838c2ecf20Sopenharmony_ci	u8 ack_failures;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	/* At which rate we got a ACK */
1868c2ecf20Sopenharmony_ci	u16 rate;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	u16 reserved;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	/* TX_* */
1918c2ecf20Sopenharmony_ci	u8 status;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/* See done_1 */
1948c2ecf20Sopenharmony_ci	u8 done_2;
1958c2ecf20Sopenharmony_ci} __packed;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic inline int wl1251_tx_get_queue(int queue)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	switch (queue) {
2008c2ecf20Sopenharmony_ci	case 0:
2018c2ecf20Sopenharmony_ci		return QOS_AC_VO;
2028c2ecf20Sopenharmony_ci	case 1:
2038c2ecf20Sopenharmony_ci		return QOS_AC_VI;
2048c2ecf20Sopenharmony_ci	case 2:
2058c2ecf20Sopenharmony_ci		return QOS_AC_BE;
2068c2ecf20Sopenharmony_ci	case 3:
2078c2ecf20Sopenharmony_ci		return QOS_AC_BK;
2088c2ecf20Sopenharmony_ci	default:
2098c2ecf20Sopenharmony_ci		return QOS_AC_BE;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_civoid wl1251_tx_work(struct work_struct *work);
2148c2ecf20Sopenharmony_civoid wl1251_tx_complete(struct wl1251 *wl);
2158c2ecf20Sopenharmony_civoid wl1251_tx_flush(struct wl1251 *wl);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci#endif
218