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