162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file is part of wl1251
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 1998-2007 Texas Instruments Incorporated
662306a36Sopenharmony_ci * Copyright (C) 2008 Nokia Corporation
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __WL1251_TX_H__
1062306a36Sopenharmony_ci#define __WL1251_TX_H__
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/bitops.h>
1362306a36Sopenharmony_ci#include "acx.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci * TX PATH
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * The Tx path uses a double buffer and a tx_control structure, each located
2062306a36Sopenharmony_ci * at a fixed address in the device's memory. On startup, the host retrieves
2162306a36Sopenharmony_ci * the pointers to these addresses. A double buffer allows for continuous data
2262306a36Sopenharmony_ci * flow towards the device. The host keeps track of which buffer is available
2362306a36Sopenharmony_ci * and alternates between these two buffers on a per packet basis.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * The size of each of the two buffers is large enough to hold the longest
2662306a36Sopenharmony_ci * 802.3 packet - maximum size Ethernet packet + header + descriptor.
2762306a36Sopenharmony_ci * TX complete indication will be received a-synchronously in a TX done cyclic
2862306a36Sopenharmony_ci * buffer which is composed of 16 tx_result descriptors structures and is used
2962306a36Sopenharmony_ci * in a cyclic manner.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * The TX (HOST) procedure is as follows:
3262306a36Sopenharmony_ci * 1. Read the Tx path status, that will give the data_out_count.
3362306a36Sopenharmony_ci * 2. goto 1, if not possible.
3462306a36Sopenharmony_ci *    i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double
3562306a36Sopenharmony_ci *    buffer).
3662306a36Sopenharmony_ci * 3. Copy the packet (preceded by double_buffer_desc), if possible.
3762306a36Sopenharmony_ci *    i.e. if data_in_count - data_out_count < HwBuffer size (2 for double
3862306a36Sopenharmony_ci *    buffer).
3962306a36Sopenharmony_ci * 4. increment data_in_count.
4062306a36Sopenharmony_ci * 5. Inform the firmware by generating a firmware internal interrupt.
4162306a36Sopenharmony_ci * 6. FW will increment data_out_count after it reads the buffer.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * The TX Complete procedure:
4462306a36Sopenharmony_ci * 1. To get a TX complete indication the host enables the tx_complete flag in
4562306a36Sopenharmony_ci *    the TX descriptor Structure.
4662306a36Sopenharmony_ci * 2. For each packet with a Tx Complete field set, the firmware adds the
4762306a36Sopenharmony_ci *    transmit results to the cyclic buffer (txDoneRing) and sets both done_1
4862306a36Sopenharmony_ci *    and done_2 to 1 to indicate driver ownership.
4962306a36Sopenharmony_ci * 3. The firmware sends a Tx Complete interrupt to the host to trigger the
5062306a36Sopenharmony_ci *    host to process the new data. Note: interrupt will be send per packet if
5162306a36Sopenharmony_ci *    TX complete indication was requested in tx_control or per crossing
5262306a36Sopenharmony_ci *    aggregation threshold.
5362306a36Sopenharmony_ci * 4. After receiving the Tx Complete interrupt, the host reads the
5462306a36Sopenharmony_ci *    TxDescriptorDone information in a cyclic manner and clears both done_1
5562306a36Sopenharmony_ci *    and done_2 fields.
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci */
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define TX_COMPLETE_REQUIRED_BIT	0x80
6062306a36Sopenharmony_ci#define TX_STATUS_DATA_OUT_COUNT_MASK   0xf
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define WL1251_TX_ALIGN_TO 4
6362306a36Sopenharmony_ci#define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \
6462306a36Sopenharmony_ci			     ~(WL1251_TX_ALIGN_TO - 1))
6562306a36Sopenharmony_ci#define WL1251_TKIP_IV_SPACE 4
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistruct tx_control {
6862306a36Sopenharmony_ci	/* Rate Policy (class) index */
6962306a36Sopenharmony_ci	unsigned rate_policy:3;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/* When set, no ack policy is expected */
7262306a36Sopenharmony_ci	unsigned ack_policy:1;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/*
7562306a36Sopenharmony_ci	 * Packet type:
7662306a36Sopenharmony_ci	 * 0 -> 802.11
7762306a36Sopenharmony_ci	 * 1 -> 802.3
7862306a36Sopenharmony_ci	 * 2 -> IP
7962306a36Sopenharmony_ci	 * 3 -> raw codec
8062306a36Sopenharmony_ci	 */
8162306a36Sopenharmony_ci	unsigned packet_type:2;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/* If set, this is a QoS-Null or QoS-Data frame */
8462306a36Sopenharmony_ci	unsigned qos:1;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	/*
8762306a36Sopenharmony_ci	 * If set, the target triggers the tx complete INT
8862306a36Sopenharmony_ci	 * upon frame sending completion.
8962306a36Sopenharmony_ci	 */
9062306a36Sopenharmony_ci	unsigned tx_complete:1;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	/* 2 bytes padding before packet header */
9362306a36Sopenharmony_ci	unsigned xfer_pad:1;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	unsigned reserved:7;
9662306a36Sopenharmony_ci} __packed;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistruct tx_double_buffer_desc {
10062306a36Sopenharmony_ci	/* Length of payload, including headers. */
10162306a36Sopenharmony_ci	__le16 length;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/*
10462306a36Sopenharmony_ci	 * A bit mask that specifies the initial rate to be used
10562306a36Sopenharmony_ci	 * Possible values are:
10662306a36Sopenharmony_ci	 * 0x0001 - 1Mbits
10762306a36Sopenharmony_ci	 * 0x0002 - 2Mbits
10862306a36Sopenharmony_ci	 * 0x0004 - 5.5Mbits
10962306a36Sopenharmony_ci	 * 0x0008 - 6Mbits
11062306a36Sopenharmony_ci	 * 0x0010 - 9Mbits
11162306a36Sopenharmony_ci	 * 0x0020 - 11Mbits
11262306a36Sopenharmony_ci	 * 0x0040 - 12Mbits
11362306a36Sopenharmony_ci	 * 0x0080 - 18Mbits
11462306a36Sopenharmony_ci	 * 0x0100 - 22Mbits
11562306a36Sopenharmony_ci	 * 0x0200 - 24Mbits
11662306a36Sopenharmony_ci	 * 0x0400 - 36Mbits
11762306a36Sopenharmony_ci	 * 0x0800 - 48Mbits
11862306a36Sopenharmony_ci	 * 0x1000 - 54Mbits
11962306a36Sopenharmony_ci	 */
12062306a36Sopenharmony_ci	__le16 rate;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	/* Time in us that a packet can spend in the target */
12362306a36Sopenharmony_ci	__le32 expiry_time;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* index of the TX queue used for this packet */
12662306a36Sopenharmony_ci	u8 xmit_queue;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* Used to identify a packet */
12962306a36Sopenharmony_ci	u8 id;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	struct tx_control control;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	/*
13462306a36Sopenharmony_ci	 * The FW should cut the packet into fragments
13562306a36Sopenharmony_ci	 * of this size.
13662306a36Sopenharmony_ci	 */
13762306a36Sopenharmony_ci	__le16 frag_threshold;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	/* Numbers of HW queue blocks to be allocated */
14062306a36Sopenharmony_ci	u8 num_mem_blocks;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	u8 reserved;
14362306a36Sopenharmony_ci} __packed;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cienum {
14662306a36Sopenharmony_ci	TX_SUCCESS              = 0,
14762306a36Sopenharmony_ci	TX_DMA_ERROR            = BIT(7),
14862306a36Sopenharmony_ci	TX_DISABLED             = BIT(6),
14962306a36Sopenharmony_ci	TX_RETRY_EXCEEDED       = BIT(5),
15062306a36Sopenharmony_ci	TX_TIMEOUT              = BIT(4),
15162306a36Sopenharmony_ci	TX_KEY_NOT_FOUND        = BIT(3),
15262306a36Sopenharmony_ci	TX_ENCRYPT_FAIL         = BIT(2),
15362306a36Sopenharmony_ci	TX_UNAVAILABLE_PRIORITY = BIT(1),
15462306a36Sopenharmony_ci};
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistruct tx_result {
15762306a36Sopenharmony_ci	/*
15862306a36Sopenharmony_ci	 * Ownership synchronization between the host and
15962306a36Sopenharmony_ci	 * the firmware. If done_1 and done_2 are cleared,
16062306a36Sopenharmony_ci	 * owned by the FW (no info ready).
16162306a36Sopenharmony_ci	 */
16262306a36Sopenharmony_ci	u8 done_1;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	/* same as double_buffer_desc->id */
16562306a36Sopenharmony_ci	u8 id;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	/*
16862306a36Sopenharmony_ci	 * Total air access duration consumed by this
16962306a36Sopenharmony_ci	 * packet, including all retries and overheads.
17062306a36Sopenharmony_ci	 */
17162306a36Sopenharmony_ci	u16 medium_usage;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	/* Total media delay (from 1st EDCA AIFS counter until TX Complete). */
17462306a36Sopenharmony_ci	u32 medium_delay;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	/* Time between host xfer and tx complete */
17762306a36Sopenharmony_ci	u32 fw_hnadling_time;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	/* The LS-byte of the last TKIP sequence number. */
18062306a36Sopenharmony_ci	u8 lsb_seq_num;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	/* Retry count */
18362306a36Sopenharmony_ci	u8 ack_failures;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/* At which rate we got a ACK */
18662306a36Sopenharmony_ci	u16 rate;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	u16 reserved;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	/* TX_* */
19162306a36Sopenharmony_ci	u8 status;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	/* See done_1 */
19462306a36Sopenharmony_ci	u8 done_2;
19562306a36Sopenharmony_ci} __packed;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic inline int wl1251_tx_get_queue(int queue)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	switch (queue) {
20062306a36Sopenharmony_ci	case 0:
20162306a36Sopenharmony_ci		return QOS_AC_VO;
20262306a36Sopenharmony_ci	case 1:
20362306a36Sopenharmony_ci		return QOS_AC_VI;
20462306a36Sopenharmony_ci	case 2:
20562306a36Sopenharmony_ci		return QOS_AC_BE;
20662306a36Sopenharmony_ci	case 3:
20762306a36Sopenharmony_ci		return QOS_AC_BK;
20862306a36Sopenharmony_ci	default:
20962306a36Sopenharmony_ci		return QOS_AC_BE;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_civoid wl1251_tx_work(struct work_struct *work);
21462306a36Sopenharmony_civoid wl1251_tx_complete(struct wl1251 *wl);
21562306a36Sopenharmony_civoid wl1251_tx_flush(struct wl1251 *wl);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci#endif
218