xref: /wlan-driver/qca-wifi-host-cmn/dp/wifi3.0/dp_rx_defrag.h (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef _DP_RX_DEFRAG_H
21 #define _DP_RX_DEFRAG_H
22 
23 #include "hal_rx.h"
24 
25 #define DEFRAG_IEEE80211_KEY_LEN	8
26 #define DEFRAG_IEEE80211_FCS_LEN	4
27 
28 #define DP_RX_DEFRAG_IEEE80211_ADDR_COPY(dst, src) \
29 	qdf_mem_copy(dst, src, QDF_MAC_ADDR_SIZE)
30 
31 #define DP_RX_DEFRAG_IEEE80211_QOS_HAS_SEQ(wh) \
32 	(((wh) & \
33 	(IEEE80211_FC0_TYPE_MASK | QDF_IEEE80211_FC0_SUBTYPE_QOS)) == \
34 	(IEEE80211_FC0_TYPE_DATA | QDF_IEEE80211_FC0_SUBTYPE_QOS))
35 
36 #define UNI_DESC_OWNER_SW 0x1
37 #define UNI_DESC_BUF_TYPE_RX_MSDU_LINK 0x6
38 /**
39  * struct dp_rx_defrag_cipher: structure to indicate cipher header
40  * @ic_name: Name
41  * @ic_header: header length
42  * @ic_trailer: trail length
43  * @ic_miclen: MIC length
44  */
45 struct dp_rx_defrag_cipher {
46 	const char *ic_name;
47 	uint16_t ic_header;
48 	uint8_t ic_trailer;
49 	uint8_t ic_miclen;
50 };
51 
52 #ifndef WLAN_SOFTUMAC_SUPPORT /* WLAN_SOFTUMAC_SUPPORT */
53 /**
54  * dp_rx_frag_handle() - Handles fragmented Rx frames
55  *
56  * @soc: core txrx main context
57  * @ring_desc: opaque pointer to the REO error ring descriptor
58  * @mpdu_desc_info: MPDU descriptor information from ring descriptor
59  * @rx_desc:
60  * @mac_id:
61  * @quota: No. of units (packets) that can be serviced in one shot.
62  *
63  * This function implements RX 802.11 fragmentation handling
64  * The handling is mostly same as legacy fragmentation handling.
65  * If required, this function can re-inject the frames back to
66  * REO ring (with proper setting to by-pass fragmentation check
67  * but use duplicate detection / re-ordering and routing these frames
68  * to a different core.
69  *
70  * Return: uint32_t: No. of elements processed
71  */
72 uint32_t dp_rx_frag_handle(struct dp_soc *soc, hal_ring_desc_t  ring_desc,
73 			   struct hal_rx_mpdu_desc_info *mpdu_desc_info,
74 			   struct dp_rx_desc *rx_desc,
75 			   uint8_t *mac_id,
76 			   uint32_t quota);
77 #endif /* WLAN_SOFTUMAC_SUPPORT */
78 
79 /**
80  * dp_rx_frag_get_mac_hdr() - Return pointer to the mac hdr
81  * @soc: DP SOC
82  * @rx_desc_info: Pointer to the pkt_tlvs in the
83  * nbuf (pkt_tlvs->mac_hdr->data)
84  *
85  * It is inefficient to peek into the packet for received
86  * frames but these APIs are required to get to some of
87  * 802.11 fields that hardware does not populate in the
88  * rx meta data.
89  *
90  * Return: pointer to ieee80211_frame
91  */
92 static inline struct ieee80211_frame *
dp_rx_frag_get_mac_hdr(struct dp_soc * soc,uint8_t * rx_desc_info)93 dp_rx_frag_get_mac_hdr(struct dp_soc *soc, uint8_t *rx_desc_info)
94 {
95 	int rx_desc_len = soc->rx_pkt_tlv_size;
96 	return (struct ieee80211_frame *)(rx_desc_info + rx_desc_len);
97 }
98 
99 /**
100  * dp_rx_frag_get_mpdu_seq_number() - Get mpdu sequence number
101  * @soc: DP SOC
102  * @rx_desc_info: Pointer to the pkt_tlvs in the
103  * nbuf (pkt_tlvs->mac_hdr->data)
104  *
105  * Return: uint16_t, rx sequence number
106  */
107 static inline uint16_t
dp_rx_frag_get_mpdu_seq_number(struct dp_soc * soc,int8_t * rx_desc_info)108 dp_rx_frag_get_mpdu_seq_number(struct dp_soc *soc, int8_t *rx_desc_info)
109 {
110 	struct ieee80211_frame *mac_hdr;
111 	mac_hdr = dp_rx_frag_get_mac_hdr(soc, rx_desc_info);
112 
113 	return qdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) >>
114 		IEEE80211_SEQ_SEQ_SHIFT;
115 }
116 
117 /**
118  * dp_rx_frag_get_mpdu_frag_number() - Get mpdu fragment number
119  * @soc: DP SOC
120  * @rx_desc_info: Pointer to the pkt_tlvs in the
121  * nbuf (pkt_tlvs->mac_hdr->data)
122  *
123  * Return: uint8_t, receive fragment number
124  */
125 static inline uint8_t
dp_rx_frag_get_mpdu_frag_number(struct dp_soc * soc,uint8_t * rx_desc_info)126 dp_rx_frag_get_mpdu_frag_number(struct dp_soc *soc, uint8_t *rx_desc_info)
127 {
128 	struct ieee80211_frame *mac_hdr;
129 	mac_hdr = dp_rx_frag_get_mac_hdr(soc, rx_desc_info);
130 
131 	return qdf_le16_to_cpu(*(uint16_t *) mac_hdr->i_seq) &
132 		IEEE80211_SEQ_FRAG_MASK;
133 }
134 
135 /**
136  * dp_rx_frag_get_more_frag_bit() - Get more fragment bit
137  * @soc: DP SOC
138  * @rx_desc_info: Pointer to the pkt_tlvs in the
139  * nbuf (pkt_tlvs->mac_hdr->data)
140  *
141  * Return: uint8_t, get more fragment bit
142  */
143 static inline
dp_rx_frag_get_more_frag_bit(struct dp_soc * soc,uint8_t * rx_desc_info)144 uint8_t dp_rx_frag_get_more_frag_bit(struct dp_soc *soc, uint8_t *rx_desc_info)
145 {
146 	struct ieee80211_frame *mac_hdr;
147 	mac_hdr = dp_rx_frag_get_mac_hdr(soc, rx_desc_info);
148 
149 	return (mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG) >> 2;
150 }
151 
152 static inline
dp_rx_get_pkt_dir(struct dp_soc * soc,uint8_t * rx_desc_info)153 uint8_t dp_rx_get_pkt_dir(struct dp_soc *soc, uint8_t *rx_desc_info)
154 {
155 	struct ieee80211_frame *mac_hdr;
156 	mac_hdr = dp_rx_frag_get_mac_hdr(soc, rx_desc_info);
157 
158 	return mac_hdr->i_fc[1] & IEEE80211_FC1_DIR_MASK;
159 }
160 
161 /**
162  * dp_rx_defrag_fraglist_insert() - Create a per-sequence fragment list
163  * @txrx_peer: Pointer to the peer data structure
164  * @tid: Transmit ID (TID)
165  * @head_addr: Pointer to head list
166  * @tail_addr: Pointer to tail list
167  * @frag: Incoming fragment
168  * @all_frag_present: Flag to indicate whether all fragments are received
169  *
170  * Build a per-tid, per-sequence fragment list.
171  *
172  * Return: Success, if inserted
173  */
174 QDF_STATUS
175 dp_rx_defrag_fraglist_insert(struct dp_txrx_peer *txrx_peer, unsigned int tid,
176 			     qdf_nbuf_t *head_addr, qdf_nbuf_t *tail_addr,
177 			     qdf_nbuf_t frag, uint8_t *all_frag_present);
178 
179 /**
180  * dp_rx_defrag_waitlist_add() - Update per-PDEV defrag wait list
181  * @txrx_peer: Pointer to the peer data structure
182  * @tid: Transmit ID (TID)
183  *
184  * Appends per-tid fragments to global fragment wait list
185  *
186  * Return: None
187  */
188 void dp_rx_defrag_waitlist_add(struct dp_txrx_peer *txrx_peer,
189 			       unsigned int tid);
190 
191 /**
192  * dp_rx_defrag() - Defragment the fragment chain
193  * @txrx_peer: Pointer to the peer
194  * @tid: Transmit Identifier
195  * @frag_list_head: Pointer to head list
196  * @frag_list_tail: Pointer to tail list
197  *
198  * Defragment the fragment chain
199  *
200  * Return: QDF_STATUS
201  */
202 QDF_STATUS dp_rx_defrag(struct dp_txrx_peer *txrx_peer, unsigned int tid,
203 			qdf_nbuf_t frag_list_head,
204 			qdf_nbuf_t frag_list_tail);
205 
206 /**
207  * dp_rx_defrag_waitlist_flush() - Flush SOC defrag wait list
208  * @soc: DP SOC
209  *
210  * Flush fragments of all waitlisted TID's
211  *
212  * Return: None
213  */
214 void dp_rx_defrag_waitlist_flush(struct dp_soc *soc);
215 
216 /**
217  * dp_rx_reorder_flush_frag() - Flush the frag list
218  * @txrx_peer: Pointer to the peer data structure
219  * @tid: Transmit ID (TID)
220  *
221  * Flush the per-TID frag list
222  *
223  * Return: None
224  */
225 void dp_rx_reorder_flush_frag(struct dp_txrx_peer *txrx_peer,
226 			      unsigned int tid);
227 
228 /**
229  * dp_rx_defrag_waitlist_remove() - Remove fragments from waitlist
230  * @txrx_peer: Pointer to the peer data structure
231  * @tid: Transmit ID (TID)
232  *
233  * Remove fragments from waitlist
234  *
235  * Return: None
236  */
237 void dp_rx_defrag_waitlist_remove(struct dp_txrx_peer *txrx_peer,
238 				  unsigned int tid);
239 
240 /**
241  * dp_rx_defrag_cleanup() - Clean up activities
242  * @txrx_peer: Pointer to the peer
243  * @tid: Transmit Identifier
244  *
245  * Return: None
246  */
247 void dp_rx_defrag_cleanup(struct dp_txrx_peer *txrx_peer, unsigned int tid);
248 
249 QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc,
250 				      struct dp_txrx_peer *peer, uint16_t tid,
251 				      uint16_t rxseq, qdf_nbuf_t nbuf);
252 #endif /* _DP_RX_DEFRAG_H */
253