1 /*
2  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 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 /**
21  * @file ol_tx.h
22  * @brief Internal definitions for the high-level tx module.
23  */
24 #ifndef _OL_TX__H_
25 #define _OL_TX__H_
26 
27 #include <qdf_nbuf.h>           /* qdf_nbuf_t */
28 #include <qdf_lock.h>
29 #include <cdp_txrx_cmn.h>       /* ol_txrx_vdev_t, etc. */
30 #include <cdp_txrx_misc.h>      /* ol_tx_spec */
31 #include <cdp_txrx_handle.h>
32 #include <ol_txrx_types.h>      /* ol_tx_desc_t, ol_txrx_msdu_info_t */
33 #include <ol_txrx.h>
34 #include <hif.h>
35 
36 #ifdef IPA_OFFLOAD
37 /**
38  * ol_tx_send_ipa_data_frame() - send IPA data frame
39  * @soc_hdl: datapath soc handle
40  * @vdev: virtual interface id
41  * @skb: skb
42  *
43  * Return: skb/ NULL is for success
44  */
45 qdf_nbuf_t ol_tx_send_ipa_data_frame(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
46 				     qdf_nbuf_t skb);
47 #endif
48 
49 #ifdef CONFIG_LL_DP_SUPPORT
50 struct ol_tx_desc_t *
51 ol_tx_prepare_ll(ol_txrx_vdev_handle vdev,
52 		 qdf_nbuf_t msdu,
53 		 struct ol_txrx_msdu_info_t *msdu_info);
54 #endif
55 
56 qdf_nbuf_t ol_tx_ll_wrapper(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
57 #ifdef WLAN_FEATURE_FASTPATH
58 qdf_nbuf_t ol_tx_ll_fast(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
59 
60 void ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc *osc,
61 				     struct ol_txrx_pdev_t *pdev);
62 #else
63 static inline
ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc * osc,struct ol_txrx_pdev_t * pdev)64 void ol_tx_setup_fastpath_ce_handles(struct hif_opaque_softc *osc,
65 				     struct ol_txrx_pdev_t *pdev)
66 { }
67 
68 qdf_nbuf_t ol_tx_ll(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
69 #endif
70 
71 qdf_nbuf_t ol_tx_ll_queue(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
72 
73 #ifdef CONFIG_HL_SUPPORT
74 #define OL_TX_SEND ol_tx_hl
75 #else
76 #define OL_TX_SEND OL_TX_LL
77 #endif
78 
79 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
80 #define OL_TX_LL ol_tx_ll_queue
81 #else
82 #define OL_TX_LL ol_tx_ll_wrapper
83 #endif
84 
85 #ifdef WLAN_SUPPORT_TXRX_HL_BUNDLE
86 void ol_tx_hl_vdev_bundle_timer(void *context);
87 
88 void ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev);
89 qdf_nbuf_t
90 ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev);
91 #else
92 static inline
ol_tx_hl_vdev_bundle_timer(void * context)93 void ol_tx_hl_vdev_bundle_timer(void *context)
94 {
95 }
96 
97 static inline
ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t * vdev)98 void ol_tx_hl_queue_flush_all(struct ol_txrx_vdev_t *vdev)
99 {
100 }
101 
102 static inline
103 qdf_nbuf_t
ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t * pdev)104 ol_tx_hl_pdev_queue_send_all(struct ol_txrx_pdev_t *pdev)
105 {
106 	return NULL;
107 }
108 #endif
109 
110 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
111 void ol_tx_vdev_ll_pause_queue_send(void *context);
112 void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev);
113 #else
ol_tx_vdev_ll_pause_queue_send(void * context)114 static inline void ol_tx_vdev_ll_pause_queue_send(void *context)
115 {
116 }
117 static inline
ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t * pdev)118 void ol_tx_pdev_ll_pause_queue_send_all(struct ol_txrx_pdev_t *pdev)
119 {
120 }
121 #endif
122 
123 /**
124  * ol_tx_comp_hw_to_qdf_status(): map ol hw to qdf status
125  * @status: hw status
126  *
127  * Return: qdf tx rx status
128  */
129 static inline enum qdf_dp_tx_rx_status
ol_tx_comp_hw_to_qdf_status(uint16_t status)130 ol_tx_comp_hw_to_qdf_status(uint16_t status)
131 {
132 	switch (status) {
133 	case HTT_TX_COMPL_IND_STAT_OK:
134 		return QDF_TX_RX_STATUS_OK;
135 	case HTT_TX_COMPL_IND_STAT_DISCARD:
136 	case HTT_TX_COMPL_IND_STAT_DROP:
137 		return QDF_TX_RX_STATUS_FW_DISCARD;
138 	case HTT_TX_COMPL_IND_STAT_NO_ACK:
139 		return QDF_TX_RX_STATUS_NO_ACK;
140 	default:
141 		return QDF_TX_RX_STATUS_DEFAULT;
142 	}
143 }
144 
145 static inline
ol_txrx_tx_is_raw(enum ol_tx_spec tx_spec)146 int ol_txrx_tx_is_raw(enum ol_tx_spec tx_spec)
147 {
148 	return	tx_spec &
149 		(OL_TX_SPEC_RAW | OL_TX_SPEC_NO_AGGR | OL_TX_SPEC_NO_ENCRYPT);
150 }
151 
152 static inline
ol_txrx_tx_raw_subtype(enum ol_tx_spec tx_spec)153 uint8_t ol_txrx_tx_raw_subtype(enum ol_tx_spec tx_spec)
154 {
155 	uint8_t sub_type = 0x1; /* 802.11 MAC header present */
156 
157 	if (tx_spec & OL_TX_SPEC_NO_AGGR)
158 		sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_AGGR_S;
159 	if (tx_spec & OL_TX_SPEC_NO_ENCRYPT)
160 		sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S;
161 	if (tx_spec & OL_TX_SPEC_NWIFI_NO_ENCRYPT)
162 		sub_type |= 0x1 << HTT_TX_MSDU_DESC_RAW_SUBTYPE_NO_ENCRYPT_S;
163 	return sub_type;
164 }
165 
166 /**
167  * ol_tx_hl() - transmit tx frames for a HL system.
168  * @vdev: the virtual device transmit the data
169  * @msdu_list: the tx frames to send
170  *
171  * Return: NULL if all MSDUs are accepted
172  */
173 qdf_nbuf_t
174 ol_tx_hl(ol_txrx_vdev_handle vdev, qdf_nbuf_t msdu_list);
175 
176 /**
177  * ol_tx_non_std() - Allow the control-path SW to send data frames
178  * @soc_hdl: Datapath soc handle
179  * @vdev_id: id of vdev
180  * @tx_spec: what non-standard handling to apply to the tx data frames
181  * @msdu_list: NULL-terminated list of tx MSDUs
182  *
183  * Generally, all tx data frames come from the OS shim into the txrx layer.
184  * However, there are rare cases such as TDLS messaging where the UMAC
185  * control-path SW creates tx data frames.
186  *  This UMAC SW can call this function to provide the tx data frames to
187  *  the txrx layer.
188  *  The UMAC SW can request a callback for these data frames after their
189  *  transmission completes, by using the ol_txrx_data_tx_cb_set function
190  *  to register a tx completion callback, and by specifying
191  *  ol_tx_spec_no_free as the tx_spec arg when giving the frames to
192  *  ol_tx_non_std.
193  *  The MSDUs need to have the appropriate L2 header type (802.3 vs. 802.11),
194  *  as specified by ol_cfg_frame_type().
195  *
196  *  Return: null - success, skb - failure
197  */
198 #ifdef CONFIG_HL_SUPPORT
199 qdf_nbuf_t ol_tx_non_std_hl(struct ol_txrx_vdev_t *vdev,
200 			    enum ol_tx_spec tx_spec,
201 			    qdf_nbuf_t msdu_list);
202 
203 static inline qdf_nbuf_t
ol_tx_non_std(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,enum ol_tx_spec tx_spec,qdf_nbuf_t msdu_list)204 ol_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
205 	      enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list)
206 {
207 	struct ol_txrx_vdev_t *vdev;
208 
209 	vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
210 
211 	if (!vdev)
212 		return msdu_list;
213 	else
214 		return ol_tx_non_std_hl(vdev, tx_spec, msdu_list);
215 }
216 #else
217 qdf_nbuf_t ol_tx_non_std_ll(struct ol_txrx_vdev_t *vdev,
218 			    enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list);
219 
220 static inline qdf_nbuf_t
ol_tx_non_std(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,enum ol_tx_spec tx_spec,qdf_nbuf_t msdu_list)221 ol_tx_non_std(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
222 	      enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list)
223 {
224 	struct ol_txrx_vdev_t *vdev;
225 
226 	vdev = (struct ol_txrx_vdev_t *)ol_txrx_get_vdev_from_vdev_id(vdev_id);
227 
228 	if (!vdev)
229 		return msdu_list;
230 	else
231 		return ol_tx_non_std_ll(vdev, tx_spec, msdu_list);
232 }
233 #endif
234 
235 /**
236  * ol_tx_trace_pkt() - Trace TX packet at OL layer
237  *
238  * @skb: skb to be traced
239  * @msdu_id: msdu_id of the packet
240  * @vdev_id: vdev_id of the packet
241  * @op_mode: Vdev Operation mode
242  *
243  * Return: None
244  */
245 void ol_tx_trace_pkt(qdf_nbuf_t skb, uint16_t msdu_id, uint8_t vdev_id,
246 		     enum QDF_OPMODE op_mode);
247 
248 void ol_txrx_mgmt_tx_complete(void *ctxt, qdf_nbuf_t netbuf, int err);
249 
250 /**
251  * ol_txrx_mgmt_tx_cb_set() - Store a callback for delivery
252  *	notifications for management frames.
253  * @soc: Datapath soc handle
254  * @pdev_id: Physical device instance id
255  * @type: the type of mgmt frame the callback is used for
256  * @download_cb: the callback for notification of delivery to the target
257  * @ota_ack_cb: the callback for notification of delivery to the peer
258  * @ctxt: context to use with the callback
259  *
260  * When the txrx SW receives notifications from the target that a tx frame
261  * has been delivered to its recipient, it will check if the tx frame
262  * is a management frame.  If so, the txrx SW will check the management
263  * frame type specified when the frame was submitted for transmission.
264  * If there is a callback function registered for the type of management
265  * frame in question, the txrx code will invoke the callback to inform
266  * the management + control SW that the mgmt frame was delivered.
267  * This function is used by the control SW to store a callback pointer
268  * for a given type of management frame.
269  */
270 QDF_STATUS
271 ol_txrx_mgmt_tx_cb_set(struct cdp_soc_t *soc, uint8_t pdev_id, uint8_t type,
272 		       ol_txrx_mgmt_tx_cb download_cb,
273 		       ol_txrx_mgmt_tx_cb ota_ack_cb, void *ctxt);
274 
275 /**
276  * ol_txrx_mgmt_send_ext() - Transmit a management frame
277  * @soc: Datapath soc handle
278  * @vdev_id: virtual interface id
279  * @tx_mgmt_frm: management frame to transmit
280  * @type: the type of management frame (determines what callback to use)
281  * @use_6mbps: specify whether management frame to transmit should
282  *	use 6 Mbps rather than 1 Mbps min rate(for 5GHz band or P2P)
283  * @chanfreq: channel to transmit the frame on
284  *
285  * Send the specified management frame from the specified virtual device.
286  * The type is used for determining whether to invoke a callback to inform
287  * the sender that the tx mgmt frame was delivered, and if so, which
288  * callback to use.
289  *
290  * Return: 0 - the frame is accepted for transmission
291  *         1 - the frame was not accepted
292  */
293 int
294 ol_txrx_mgmt_send_ext(struct cdp_soc_t *soc, uint8_t vdev_id,
295 		      qdf_nbuf_t tx_mgmt_frm,
296 		      uint8_t type, uint8_t use_6mbps, uint16_t chanfreq);
297 
298 qdf_nbuf_t
299 ol_tx_reinject(struct ol_txrx_vdev_t *vdev, qdf_nbuf_t msdu, uint16_t peer_id);
300 
301 #if defined(FEATURE_TSO)
302 void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg);
303 void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev);
304 void ol_tso_num_seg_list_init(struct ol_txrx_pdev_t *pdev, uint32_t num_seg);
305 void ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t *pdev);
306 uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev);
307 uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
308 			  qdf_nbuf_t msdu,
309 			  struct ol_txrx_msdu_info_t *msdu_info);
310 void ol_tx_tso_update_stats(struct ol_txrx_pdev_t *pdev,
311 			    struct qdf_tso_info_t  *tso_info, qdf_nbuf_t msdu,
312 			    uint32_t tso_msdu_idx);
313 #else
ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t * pdev)314 static inline uint32_t ol_tx_tso_get_stats_idx(struct ol_txrx_pdev_t *pdev)
315 {
316 	return 0;
317 }
318 
ol_tso_seg_list_init(struct ol_txrx_pdev_t * pdev,uint32_t num_seg)319 static inline void ol_tso_seg_list_init(struct ol_txrx_pdev_t *pdev,
320 	uint32_t num_seg)
321 {
322 }
323 
ol_tso_seg_list_deinit(struct ol_txrx_pdev_t * pdev)324 static inline void ol_tso_seg_list_deinit(struct ol_txrx_pdev_t *pdev)
325 {
326 }
327 
ol_tso_num_seg_list_init(struct ol_txrx_pdev_t * pdev,uint32_t num_seg)328 static inline void ol_tso_num_seg_list_init(struct ol_txrx_pdev_t *pdev,
329 	uint32_t num_seg)
330 {
331 }
332 
ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t * pdev)333 static inline void ol_tso_num_seg_list_deinit(struct ol_txrx_pdev_t *pdev)
334 {
335 }
336 
ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,qdf_nbuf_t msdu,struct ol_txrx_msdu_info_t * msdu_info)337 static inline uint8_t ol_tx_prepare_tso(ol_txrx_vdev_handle vdev,
338 					qdf_nbuf_t msdu,
339 					struct ol_txrx_msdu_info_t *msdu_info)
340 {
341 	return 0;
342 }
343 
ol_tx_tso_update_stats(struct ol_txrx_pdev_t * pdev,struct qdf_tso_info_t * tso_info,qdf_nbuf_t msdu,uint32_t tso_msdu_idx)344 static inline void ol_tx_tso_update_stats(struct ol_txrx_pdev_t *pdev,
345 					  struct qdf_tso_info_t  *tso_info,
346 					  qdf_nbuf_t msdu,
347 					  uint32_t tso_msdu_idx)
348 {
349 }
350 #endif
351 
352 #ifdef QCA_HL_NETDEV_FLOW_CONTROL
353 bool ol_tx_desc_is_high_prio(qdf_nbuf_t msdu);
354 #endif
355 
356 #if defined(HELIUMPLUS)
357 void ol_txrx_dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc);
358 #else
359 static inline
ol_txrx_dump_frag_desc(char * msg,struct ol_tx_desc_t * tx_desc)360 void ol_txrx_dump_frag_desc(char *msg, struct ol_tx_desc_t *tx_desc)
361 {
362 }
363 #endif
364 
365 #endif /* _OL_TX__H_ */
366