xref: /linux/drivers/net/wireless/morsemicro/mm81x/skbq.h (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1*b1906ceaSLachlan Hodges /* SPDX-License-Identifier: GPL-2.0-only */
2*b1906ceaSLachlan Hodges /*
3*b1906ceaSLachlan Hodges  * Copyright (c) 2017-2026 Morse Micro
4*b1906ceaSLachlan Hodges  */
5*b1906ceaSLachlan Hodges 
6*b1906ceaSLachlan Hodges #ifndef _MM81X_SKBQ_H_
7*b1906ceaSLachlan Hodges #define _MM81X_SKBQ_H_
8*b1906ceaSLachlan Hodges 
9*b1906ceaSLachlan Hodges #include <linux/skbuff.h>
10*b1906ceaSLachlan Hodges #include <linux/workqueue.h>
11*b1906ceaSLachlan Hodges #include "rate_code.h"
12*b1906ceaSLachlan Hodges 
13*b1906ceaSLachlan Hodges /* Sync value of skb header to indicate a valid skb */
14*b1906ceaSLachlan Hodges #define MM81X_SKB_HEADER_SYNC (0xAA)
15*b1906ceaSLachlan Hodges /* Sync value indicating that the chip owns this skb */
16*b1906ceaSLachlan Hodges #define MM81X_SKB_HEADER_CHIP_OWNED_SYNC (0xBB)
17*b1906ceaSLachlan Hodges 
18*b1906ceaSLachlan Hodges enum mm81x_tx_status_and_conf_flags {
19*b1906ceaSLachlan Hodges 	MM81X_TX_STATUS_FLAGS_NO_ACK = BIT(0),
20*b1906ceaSLachlan Hodges 	MM81X_TX_STATUS_FLAGS_NO_REPORT = BIT(1),
21*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_CTL_AMPDU = BIT(2),
22*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_HW_ENCRYPT = BIT(3),
23*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_VIF_ID = (BIT(4) | BIT(5) | BIT(6) | BIT(7) |
24*b1906ceaSLachlan Hodges 				      BIT(8) | BIT(9) | BIT(10) | BIT(11)),
25*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_KEY_IDX = (BIT(12) | BIT(13) | BIT(14)),
26*b1906ceaSLachlan Hodges 	MM81X_TX_STATUS_FLAGS_PS_FILTERED = (BIT(15)),
27*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_IGNORE_TWT = (BIT(16)),
28*b1906ceaSLachlan Hodges 	MM81X_TX_STATUS_PAGE_INVALID = (BIT(17)),
29*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_NO_PS_BUFFER = (BIT(18)),
30*b1906ceaSLachlan Hodges 	MM81X_TX_STATUS_DUTY_CYCLE_CANT_SEND = (BIT(19)),
31*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_HAS_PV1_BPN_IN_BODY = (BIT(21)),
32*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_SEND_AFTER_DTIM = (BIT(22)),
33*b1906ceaSLachlan Hodges 	MM81X_TX_STATUS_WAS_AGGREGATED = (BIT(23)),
34*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_FULLMAC_REPORT = BIT(24),
35*b1906ceaSLachlan Hodges 	MM81X_TX_CONF_FLAGS_IMMEDIATE_REPORT = (BIT(31))
36*b1906ceaSLachlan Hodges };
37*b1906ceaSLachlan Hodges 
38*b1906ceaSLachlan Hodges /* Getter and setter macros for vif id */
39*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_VIF_ID_MASK (0xFF)
40*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_VIF_ID_SET(x) \
41*b1906ceaSLachlan Hodges 	(((x) & MM81X_TX_CONF_FLAGS_VIF_ID_MASK) << 4)
42*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_VIF_ID_GET(x) \
43*b1906ceaSLachlan Hodges 	(((x) & MM81X_TX_CONF_FLAGS_VIF_ID) >> 4)
44*b1906ceaSLachlan Hodges 
45*b1906ceaSLachlan Hodges /* Getter and setter macros for key index */
46*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_KEY_IDX_SET(x) (((x) & 0x07) << 12)
47*b1906ceaSLachlan Hodges #define MM81X_TX_CONF_FLAGS_KEY_IDX_GET(x) \
48*b1906ceaSLachlan Hodges 	(((x) & MM81X_TX_CONF_FLAGS_KEY_IDX) >> 12)
49*b1906ceaSLachlan Hodges 
50*b1906ceaSLachlan Hodges enum mm81x_rx_status_flags {
51*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_ERROR = BIT(0),
52*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_DECRYPTED = BIT(1),
53*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_FCS_INCLUDED = BIT(2),
54*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_EOF = BIT(3),
55*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_AMPDU = BIT(4),
56*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_NDP = BIT(7),
57*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_UPLINK = BIT(8),
58*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_RI = (BIT(9) | BIT(10)),
59*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_NDP_TYPE = (BIT(11) | BIT(12) | BIT(13)),
60*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_CRC_ERROR = BIT(14),
61*b1906ceaSLachlan Hodges 	MM81X_RX_STATUS_FLAGS_VIF_ID = GENMASK(24, 17),
62*b1906ceaSLachlan Hodges };
63*b1906ceaSLachlan Hodges 
64*b1906ceaSLachlan Hodges /* Getter and Setter macros for vif id */
65*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_MASK (0xFF)
66*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_SET(x) \
67*b1906ceaSLachlan Hodges 	(((x) & MM81X_RX_STATUS_FLAGS_VIF_ID_MASK) << 17)
68*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_GET(x) \
69*b1906ceaSLachlan Hodges 	(((x) & MM81X_RX_STATUS_FLAGS_VIF_ID) >> 17)
70*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_VIF_ID_CLEAR(x) \
71*b1906ceaSLachlan Hodges 	((x) & ~(MM81X_RX_STATUS_FLAGS_VIF_ID_MASK << 17))
72*b1906ceaSLachlan Hodges 
73*b1906ceaSLachlan Hodges /* Getter macro for guard interval */
74*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_UPL_IND_GET(x) \
75*b1906ceaSLachlan Hodges 	(((x) & MM81X_RX_STATUS_FLAGS_UPLINK) >> 8)
76*b1906ceaSLachlan Hodges 
77*b1906ceaSLachlan Hodges /* Getter macro for response indication */
78*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_RI_GET(x) (((x) & MM81X_RX_STATUS_FLAGS_RI) >> 9)
79*b1906ceaSLachlan Hodges 
80*b1906ceaSLachlan Hodges /* Getter macro for NDP type */
81*b1906ceaSLachlan Hodges #define MM81X_RX_STATUS_FLAGS_NDP_TYPE_GET(x) \
82*b1906ceaSLachlan Hodges 	(((x) & MM81X_RX_STATUS_FLAGS_NDP_TYPE) >> 11)
83*b1906ceaSLachlan Hodges 
84*b1906ceaSLachlan Hodges enum mm81x_skb_channel {
85*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_DATA = 0x0,
86*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_NDP_FRAMES = 0x1,
87*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_DATA_NOACK = 0x2,
88*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_BEACON = 0x3,
89*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_MGMT = 0x4,
90*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_INTERNAL_CRIT_BEACON = 0x80,
91*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_COMMAND = 0xFE,
92*b1906ceaSLachlan Hodges 	MM81X_SKB_CHAN_TX_STATUS = 0xFF
93*b1906ceaSLachlan Hodges };
94*b1906ceaSLachlan Hodges 
95*b1906ceaSLachlan Hodges #define MM81X_SKB_MAX_RATES (4)
96*b1906ceaSLachlan Hodges 
97*b1906ceaSLachlan Hodges struct mm81x_skb_rate_info {
98*b1906ceaSLachlan Hodges 	mm81x_rate_code_t mm81x_ratecode;
99*b1906ceaSLachlan Hodges 	u8 count;
100*b1906ceaSLachlan Hodges } __packed;
101*b1906ceaSLachlan Hodges 
102*b1906ceaSLachlan Hodges struct mm81x_skb_tx_status {
103*b1906ceaSLachlan Hodges 	__le32 flags;
104*b1906ceaSLachlan Hodges 	__le32 pkt_id;
105*b1906ceaSLachlan Hodges 	u8 tid;
106*b1906ceaSLachlan Hodges 	u8 channel;
107*b1906ceaSLachlan Hodges 	__le16 ampdu_info;
108*b1906ceaSLachlan Hodges 	struct mm81x_skb_rate_info rates[MM81X_SKB_MAX_RATES];
109*b1906ceaSLachlan Hodges } __packed;
110*b1906ceaSLachlan Hodges 
111*b1906ceaSLachlan Hodges #define MM81X_TXSTS_AMPDU_INFO_GET_TAG(x) (((x) >> 10) & 0x3F)
112*b1906ceaSLachlan Hodges #define MM81X_TXSTS_AMPDU_INFO_GET_LEN(x) (((x) >> 5) & 0x1F)
113*b1906ceaSLachlan Hodges #define MM81X_TXSTS_AMPDU_INFO_GET_SUC(x) ((x) & 0x1F)
114*b1906ceaSLachlan Hodges 
115*b1906ceaSLachlan Hodges struct mm81x_skb_tx_info {
116*b1906ceaSLachlan Hodges 	__le32 flags;
117*b1906ceaSLachlan Hodges 	__le32 pkt_id;
118*b1906ceaSLachlan Hodges 	u8 tid;
119*b1906ceaSLachlan Hodges 	u8 tid_params;
120*b1906ceaSLachlan Hodges 	u8 mmss_params;
121*b1906ceaSLachlan Hodges 	u8 padding[1];
122*b1906ceaSLachlan Hodges 	struct mm81x_skb_rate_info rates[MM81X_SKB_MAX_RATES];
123*b1906ceaSLachlan Hodges } __packed;
124*b1906ceaSLachlan Hodges 
125*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_MAX_REORDER_BUF 0x1f
126*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_AMPDU_ENABLED 0x20
127*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_AMSDU_SUPPORTED 0x40
128*b1906ceaSLachlan Hodges #define TX_INFO_TID_PARAMS_USE_LEGACY_BA 0x80
129*b1906ceaSLachlan Hodges 
130*b1906ceaSLachlan Hodges /* Bitmap for MMSS (Minimum MPDU start spacing) parameters
131*b1906ceaSLachlan Hodges  * +-----------+-----------+
132*b1906ceaSLachlan Hodges  * | Morse     | MMSS set  |
133*b1906ceaSLachlan Hodges  * | MMSS      | by S1G cap|
134*b1906ceaSLachlan Hodges  * | offset    | IE        |
135*b1906ceaSLachlan Hodges  * |-----------|-----------|
136*b1906ceaSLachlan Hodges  * |b7|b6|b5|b4|b3|b2|b1|b0|
137*b1906ceaSLachlan Hodges  */
138*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_MMSS_MASK GENMASK(3, 0)
139*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_MMSS_OFFSET_START 4
140*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_MMSS_OFFSET_MASK GENMASK(7, 4)
141*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_SET_MMSS(x) ((x) & TX_INFO_MMSS_PARAMS_MMSS_MASK)
142*b1906ceaSLachlan Hodges #define TX_INFO_MMSS_PARAMS_SET_MMSS_OFFSET(x)            \
143*b1906ceaSLachlan Hodges 	(((x) << TX_INFO_MMSS_PARAMS_MMSS_OFFSET_START) & \
144*b1906ceaSLachlan Hodges 	 TX_INFO_MMSS_PARAMS_MMSS_OFFSET_MASK)
145*b1906ceaSLachlan Hodges 
146*b1906ceaSLachlan Hodges struct mm81x_skb_rx_status {
147*b1906ceaSLachlan Hodges 	__le32 flags;
148*b1906ceaSLachlan Hodges 	mm81x_rate_code_t mm81x_ratecode;
149*b1906ceaSLachlan Hodges 	__le16 rssi;
150*b1906ceaSLachlan Hodges 	__le16 freq_100khz;
151*b1906ceaSLachlan Hodges 	u8 bss_color;
152*b1906ceaSLachlan Hodges 	s8 noise_dbm;
153*b1906ceaSLachlan Hodges 	/** Padding for word alignment */
154*b1906ceaSLachlan Hodges 	u8 padding[2];
155*b1906ceaSLachlan Hodges 	__le64 rx_timestamp_us;
156*b1906ceaSLachlan Hodges } __packed;
157*b1906ceaSLachlan Hodges 
158*b1906ceaSLachlan Hodges struct mm81x_skb_hdr {
159*b1906ceaSLachlan Hodges 	u8 sync;
160*b1906ceaSLachlan Hodges 	u8 channel;
161*b1906ceaSLachlan Hodges 	__le16 len;
162*b1906ceaSLachlan Hodges 	u8 offset;
163*b1906ceaSLachlan Hodges 	u8 checksum_lower;
164*b1906ceaSLachlan Hodges 	__le16 checksum_upper;
165*b1906ceaSLachlan Hodges 	union {
166*b1906ceaSLachlan Hodges 		struct mm81x_skb_tx_info tx_info;
167*b1906ceaSLachlan Hodges 		struct mm81x_skb_tx_status tx_status;
168*b1906ceaSLachlan Hodges 		struct mm81x_skb_rx_status rx_status;
169*b1906ceaSLachlan Hodges 	};
170*b1906ceaSLachlan Hodges } __packed;
171*b1906ceaSLachlan Hodges 
172*b1906ceaSLachlan Hodges #define MM81X_SKBQ_SIZE (4 * 128 * 1024)
173*b1906ceaSLachlan Hodges 
174*b1906ceaSLachlan Hodges struct mm81x;
175*b1906ceaSLachlan Hodges 
176*b1906ceaSLachlan Hodges struct mm81x_skbq {
177*b1906ceaSLachlan Hodges 	struct mm81x *mors;
178*b1906ceaSLachlan Hodges 	u32 pkt_seq; /* SKB sequence used in tx_status */
179*b1906ceaSLachlan Hodges 	u16 flags;
180*b1906ceaSLachlan Hodges 	u32 skbq_size; /* current off loaded size */
181*b1906ceaSLachlan Hodges 	spinlock_t lock;
182*b1906ceaSLachlan Hodges 	struct sk_buff_head skbq;
183*b1906ceaSLachlan Hodges 	struct sk_buff_head pending; /* packets sent pending feedback */
184*b1906ceaSLachlan Hodges 	struct work_struct dispatch_work;
185*b1906ceaSLachlan Hodges };
186*b1906ceaSLachlan Hodges 
187*b1906ceaSLachlan Hodges void mm81x_skbq_purge(struct mm81x_skbq *mq, struct sk_buff_head *skbq);
188*b1906ceaSLachlan Hodges void mm81x_skbq_purge_aged(struct mm81x *mors, struct mm81x_skbq *mq);
189*b1906ceaSLachlan Hodges u32 mm81x_skbq_space(struct mm81x_skbq *mq);
190*b1906ceaSLachlan Hodges u32 mm81x_skbq_size(struct mm81x_skbq *mq);
191*b1906ceaSLachlan Hodges int mm81x_skbq_deq_num_skb(struct mm81x_skbq *mq, struct sk_buff_head *skbq,
192*b1906ceaSLachlan Hodges 			   int num_skb);
193*b1906ceaSLachlan Hodges struct sk_buff *mm81x_skbq_alloc_skb(struct mm81x_skbq *mq,
194*b1906ceaSLachlan Hodges 				     unsigned int length);
195*b1906ceaSLachlan Hodges int mm81x_skbq_skb_tx(struct mm81x_skbq *mq, struct sk_buff **skb,
196*b1906ceaSLachlan Hodges 		      struct mm81x_skb_tx_info *tx_info, u8 channel);
197*b1906ceaSLachlan Hodges int mm81x_skbq_put(struct mm81x_skbq *mq, struct sk_buff *skb);
198*b1906ceaSLachlan Hodges void mm81x_skbq_enq(struct mm81x_skbq *mq, struct sk_buff_head *skbq);
199*b1906ceaSLachlan Hodges void mm81x_skbq_enq_prepend(struct mm81x_skbq *mq, struct sk_buff_head *skbq);
200*b1906ceaSLachlan Hodges void mm81x_skbq_tx_complete(struct mm81x_skbq *mq, struct sk_buff_head *skbq);
201*b1906ceaSLachlan Hodges struct sk_buff *mm81x_skbq_tx_pending(struct mm81x_skbq *mq);
202*b1906ceaSLachlan Hodges void mm81x_skbq_init(struct mm81x *mors, struct mm81x_skbq *mq, u16 flags);
203*b1906ceaSLachlan Hodges void mm81x_skbq_finish(struct mm81x_skbq *mq);
204*b1906ceaSLachlan Hodges void mm81x_skbq_pull_hdr_post_tx(struct sk_buff *skb);
205*b1906ceaSLachlan Hodges void mm81x_skbq_mon_dump(struct mm81x *mors, struct seq_file *file);
206*b1906ceaSLachlan Hodges void mm81x_skbq_skb_finish(struct mm81x_skbq *mq, struct sk_buff *skb,
207*b1906ceaSLachlan Hodges 			   struct mm81x_skb_tx_status *tx_sts);
208*b1906ceaSLachlan Hodges void mm81x_skbq_tx_flush(struct mm81x_skbq *mq);
209*b1906ceaSLachlan Hodges int mm81x_skbq_check_for_stale_tx(struct mm81x *mors, struct mm81x_skbq *mq);
210*b1906ceaSLachlan Hodges void mm81x_skbq_may_wake_tx_queues(struct mm81x *mors);
211*b1906ceaSLachlan Hodges u32 mm81x_skbq_count_tx_ready(struct mm81x_skbq *mq);
212*b1906ceaSLachlan Hodges u32 mm81x_skbq_count(struct mm81x_skbq *mq);
213*b1906ceaSLachlan Hodges u32 mm81x_skbq_pending_count(struct mm81x_skbq *mq);
214*b1906ceaSLachlan Hodges void mm81x_skbq_data_traffic_pause(struct mm81x *mors);
215*b1906ceaSLachlan Hodges void mm81x_skbq_data_traffic_resume(struct mm81x *mors);
216*b1906ceaSLachlan Hodges bool mm81x_skbq_validate_checksum(u8 *data);
217*b1906ceaSLachlan Hodges 
218*b1906ceaSLachlan Hodges #endif /* !_MM81X_SKBQ_H_ */
219