xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/hal_g6/hal_tx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 - 2021 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _HAL_TX_C_
16 #include "hal_headers.h"
17 /**
18  * this function will be used in read / write pointer mechanism and
19  * return the number of available read pointer
20  * @rptr: input, the read pointer
21  * @wptr: input, the write pointer
22  * @bndy: input, the boundary of read / write pointer mechanism
23  */
hal_calc_avail_rptr(u16 rptr,u16 wptr,u16 bndy)24 u16 hal_calc_avail_rptr(u16 rptr, u16 wptr, u16 bndy)
25 {
26 	u16 avail_rptr = 0;
27 
28 	if (wptr >= rptr)
29 		avail_rptr = wptr - rptr;
30 	else if (rptr > wptr)
31 		avail_rptr = wptr + (bndy - rptr);
32 
33 	return avail_rptr;
34 }
35 
36 
37 /**
38  * this function will be used in read / write pointer mechanism and
39  * return the number of available write pointer
40  * @rptr: input, the read pointer
41  * @wptr: input, the write pointer
42  * @bndy: input, the boundary of read / write pointer mechanism
43  */
hal_calc_avail_wptr(u16 rptr,u16 wptr,u16 bndy)44 u16 hal_calc_avail_wptr(u16 rptr, u16 wptr, u16 bndy)
45 {
46 	u16 avail_wptr = 0;
47 
48 	if (rptr > wptr)
49 		avail_wptr = rptr - wptr - 1;
50 	else if (wptr >= rptr)
51 		avail_wptr = rptr + (bndy - wptr) - 1;
52 
53 	return avail_wptr;
54 }
55 
56 /**
57  * rtw_hal_tx_chnl_mapping - query hw tx dma channel mapping to the sw xmit ring
58  * identified by macid, tid and band
59  * @hal: see struct hal_info_t
60  * @macid: input target macid is 0 ~ 127
61  * @cat: input target packet category, see enum rtw_phl_ring_cat
62  * @band: input target band, 0 for band 0 / 1 for band 1
63  *
64  * returns the mapping hw tx dma channel
65  */
rtw_hal_tx_chnl_mapping(void * hal,u16 macid,enum rtw_phl_ring_cat cat,u8 band)66 u8 rtw_hal_tx_chnl_mapping(void *hal, u16 macid,
67 			   enum rtw_phl_ring_cat cat, u8 band)
68 {
69 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
70 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
71 	u8 tx_chnl = 0;
72 
73 	tx_chnl = trx_ops->map_hw_tx_chnl(macid, cat, band);
74 
75 	return tx_chnl;
76 }
77 
78 /**
79  * rtw_hal_get_fwcmd_queue_idx - get idx of fwcmd queue
80  * @hal: see struct hal_info_t
81  *
82  * returns u8 idx of fwcmd queue
83  */
rtw_hal_get_fwcmd_queue_idx(void * hal)84 u8 rtw_hal_get_fwcmd_queue_idx(void *hal)
85 {
86 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
87 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
88 
89 	return trx_ops->get_fwcmd_queue_idx();
90 }
rtw_hal_cfg_txhci(void * hal,u8 en)91 void rtw_hal_cfg_txhci(void *hal, u8 en)
92 {
93 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
94 
95 	PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s : enable %d.\n", __func__, en);
96 
97 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mac_cfg_txhci(hal_info, en))
98 		PHL_ERR("%s failure \n", __func__);
99 }
100 
101 
102 
rtw_hal_chk_allq_empty(void * hal,u8 * empty)103 enum rtw_hal_status rtw_hal_chk_allq_empty(void *hal, u8 *empty)
104 {
105 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
106 
107 	FUNCIN();
108 
109 	return rtw_hal_mac_chk_allq_empty(hal_info, empty);
110 }
111 
112 
rtw_hal_fill_txdesc(void * hal,struct rtw_xmit_req * treq,u8 * wd_buf,u32 * wd_len)113 enum rtw_hal_status rtw_hal_fill_txdesc(void *hal, struct rtw_xmit_req *treq,
114 					u8 *wd_buf, u32 *wd_len)
115 {
116 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
117 
118 
119 	return rtw_hal_mac_ax_fill_txdesc(hal_info->mac, treq, wd_buf, wd_len);
120 }
121 
122 enum rtw_hal_status
rtw_hal_poll_hw_tx_done(void * hal)123 rtw_hal_poll_hw_tx_done(void *hal)
124 {
125 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
126 	enum rtw_hal_status sts = RTW_HAL_STATUS_SUCCESS;
127 
128 	sts = rtw_hal_mac_poll_hw_tx_done(hal_info);
129 
130 	return sts;
131 }
132 
133 enum rtw_hal_status
rtw_hal_hw_tx_resume(void * hal)134 rtw_hal_hw_tx_resume(void *hal)
135 {
136 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
137 	enum rtw_hal_status sts = RTW_HAL_STATUS_SUCCESS;
138 
139 	sts = rtw_hal_mac_hw_tx_resume(hal_info);
140 
141 	return sts;
142 }
143 
144 #ifdef CONFIG_PCI_HCI
145 /**
146  * rtw_hal_convert_qsel_to_tid - convert qsel to tid value
147  * @hal: see struct hal_info_t
148  * @qsel: HW queue selection
149  *
150  * returns enum RTW_HAL_STATUS
151  */
rtw_hal_convert_qsel_to_tid(void * hal,u8 qsel_id,u8 tid_indic)152 u8 rtw_hal_convert_qsel_to_tid(void *hal, u8 qsel_id, u8 tid_indic)
153 {
154 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
155 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
156 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
157 
158 	hstatus = trx_ops->qsel_to_tid(hal_info, qsel_id, tid_indic);
159 
160 	return hstatus;
161 }
162 /**
163  * rtw_hal_tx_res_query - query current HW tx resource with specifc dma channel
164  * @hal: see struct hal_info_t
165  * @dma_ch: the target dma channel
166  * @host_idx: current host index of this channel
167  * @hw_idx: current hw index of this channel
168  *
169  * this function returns the number of available tx resource
170  * NOTE, input host_idx and hw_idx ptr shall NOT be NULL
171  */
rtw_hal_tx_res_query(void * hal,u8 dma_ch,u16 * host_idx,u16 * hw_idx)172 u16 rtw_hal_tx_res_query(void *hal, u8 dma_ch, u16 *host_idx, u16 *hw_idx)
173 {
174 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
175 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
176 	u16 res_num = 0;
177 
178 	res_num = trx_ops->query_tx_res(hal_info->hal_com, dma_ch, host_idx,
179 					hw_idx);
180 
181 	return res_num;
182 }
183 
184 
185 /**
186  * rtw_hal_query_txch_num - query total hw tx dma channels number
187  *
188  * returns the number of  hw tx dma channel
189  */
rtw_hal_query_txch_num(void * hal)190 u8 rtw_hal_query_txch_num(void *hal)
191 {
192 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
193 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
194 	u8 ch_num = 0;
195 
196 	ch_num = trx_ops->query_txch_num();
197 
198 	return ch_num;
199 }
200 
rtw_hal_trx_init(void * hal,u8 * txbd_buf,u8 * rxbd_buf)201 enum rtw_hal_status rtw_hal_trx_init(void *hal, u8 *txbd_buf, u8 *rxbd_buf)
202 {
203 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
204 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
205 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
206 
207 	hstatus = trx_ops->init(hal_info, txbd_buf, rxbd_buf);
208 
209 	return hstatus;
210 }
211 
rtw_hal_trx_deinit(void * hal)212 void rtw_hal_trx_deinit(void *hal)
213 {
214 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
215 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
216 
217 	trx_ops->deinit(hal_info);
218 }
219 
220 /**
221  * rtw_hal_update_wd_page - update wd page for xmit packet
222  * @hal: see struct hal_info_t
223  * @phl_pkt_req: packet xmit request from phl, see struct rtw_phl_pkt_req
224  *
225  * returns enum RTW_HAL_STATUS
226  */
rtw_hal_update_wd_page(void * hal,void * phl_pkt_req)227 enum rtw_hal_status rtw_hal_update_wd_page(void *hal, void *phl_pkt_req)
228 {
229 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
230 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
231 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
232 
233 	hstatus = trx_ops->update_wd(hal_info, phl_pkt_req);
234 
235 	return hstatus;
236 }
237 
238 /**
239  * rtw_hal_update_txbd - update tx bd for xmit packet
240  * @hal: see struct hal_info_t
241  * @wd: buffer pointer of wd page to fill in txbd
242  *
243  * returns enum RTW_HAL_STATUS
244  * NOTE, this function is PCIe specific function
245  */
rtw_hal_update_txbd(void * hal,void * txbd,void * wd,u8 dma_ch,u16 wd_num)246 enum rtw_hal_status rtw_hal_update_txbd(void *hal, void *txbd, void *wd, u8 dma_ch, u16 wd_num)
247 {
248 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
249 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
250 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
251 
252 	hstatus = trx_ops->update_txbd(hal, txbd, wd, dma_ch, wd_num);
253 
254 	return hstatus;
255 }
256 
257 
258 /**
259  * rtw_hal_update_trigger_txstart - trigger hw to start tx
260  * @hal: see struct hal_info_t
261  * @txbd: the target txbd to update
262  * @dma_ch: the dma channel index of this txbd_ring
263  *
264  * returns enum RTW_HAL_STATUS
265  */
rtw_hal_trigger_txstart(void * hal,void * txbd,u8 dma_ch)266 enum rtw_hal_status rtw_hal_trigger_txstart(void *hal, void *txbd, u8 dma_ch)
267 {
268 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
269 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
270 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
271 
272 	hstatus = trx_ops->tx_start(hal, txbd, dma_ch);
273 
274 	return hstatus;
275 }
276 
rtw_hal_poll_txdma_idle(void * hal)277 u8 rtw_hal_poll_txdma_idle(void *hal)
278 {
279 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
280 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
281 
282 	FUNCIN();
283 
284 	return trx_ops->poll_txdma_idle(hal_info);
285 }
286 
287 #endif /*CONFIG_PCI_HCI*/
288 
289 #ifdef CONFIG_USB_HCI
rtw_hal_trx_init(void * hal)290 enum rtw_hal_status rtw_hal_trx_init(void *hal)
291 {
292 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
293 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
294 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
295 
296 	hstatus = trx_ops->init(hal_info);
297 
298 	return hstatus;
299 }
300 
rtw_hal_trx_deinit(void * hal)301 void rtw_hal_trx_deinit(void *hal)
302 {
303 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
304 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
305 
306 	trx_ops->deinit(hal_info);
307 }
308 
rtw_hal_get_bulkout_id(void * hal,u8 dma_ch,u8 mode)309 u8 rtw_hal_get_bulkout_id(void *hal, u8 dma_ch, u8 mode)
310 {
311 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
312 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
313 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
314 
315 	hstatus = trx_ops->get_bulkout_id(hal, dma_ch, mode);
316 
317 	return hstatus;
318 }
319 
320 enum rtw_hal_status
rtw_hal_usb_tx_agg_cfg(void * hal,u8 * wd_buf,u8 agg_num)321 	rtw_hal_usb_tx_agg_cfg(void *hal, u8* wd_buf, u8 agg_num)
322 {
323 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
324 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
325 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
326 
327 	hstatus = trx_ops->usb_tx_agg_cfg(hal, wd_buf, agg_num);
328 
329 	return hstatus;
330 }
331 
332 
rtw_hal_get_max_bulkout_wd_num(void * hal)333 u8 rtw_hal_get_max_bulkout_wd_num(void *hal)
334 {
335 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
336 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
337 
338 	return trx_ops->get_max_bulkout_wd_num(hal);
339 }
340 
341 /**
342  * rtw_hal_fill_wd - fill wd-info and wd-boddy for xmit packet
343  * @hal: see struct hal_info_t
344  * @phl_pkt_req: packet xmit request from phl, see struct rtw_phl_pkt_req
345  *
346  * returns enum RTW_HAL_STATUS
347  */
rtw_hal_fill_wd(void * hal,struct rtw_xmit_req * tx_req,u8 * wd_buf,u32 * wd_len)348 enum rtw_hal_status rtw_hal_fill_wd(void *hal,
349 				struct rtw_xmit_req *tx_req,
350 				u8 *wd_buf, u32 *wd_len)
351 {
352 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
353 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
354 	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
355 
356 #ifdef RTW_WKARD_CCX_RPT_LIMIT_CTRL
357 	if (tx_req->mdata.spe_rpt) {
358 		if (tx_req->mdata.data_tx_cnt_lmt_en)
359 			hal_info->hal_com->spe_pkt_cnt_lmt = tx_req->mdata.data_tx_cnt_lmt;
360 	}
361 #endif
362 	hstatus = trx_ops->hal_fill_wd(hal_info, tx_req, wd_buf, wd_len);
363 
364 	return hstatus;
365 }
366 
367 #endif
368 
369 #ifdef CONFIG_SDIO_HCI
rtw_hal_sdio_tx_cfg(void * hal)370 void rtw_hal_sdio_tx_cfg(void *hal)
371 {
372 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
373 
374 
375 	rtw_hal_mac_sdio_tx_cfg(hal_info->hal_com);
376 }
377 
rtw_hal_sdio_tx(void * hal,u8 dma_ch,u8 * buf,u32 buf_len,u8 agg_count,u16 * pkt_len,u8 * wp_offset)378 enum rtw_hal_status rtw_hal_sdio_tx(void *hal, u8 dma_ch, u8 *buf, u32 buf_len,
379 				    u8 agg_count, u16 *pkt_len, u8 *wp_offset)
380 {
381 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
382 	u32 txaddr;
383 	u32 txlen;
384 	bool ready;
385 
386 
387 	ready = rtw_hal_mac_sdio_check_tx_allow(hal_info->hal_com, dma_ch,
388 						buf, buf_len, agg_count,
389 						pkt_len, wp_offset, &txaddr,
390 						&txlen);
391 	if (!ready)
392 		return RTW_HAL_STATUS_RESOURCE;
393 
394 	hal_sdio_cmd53_w(hal_info->hal_com, txaddr, txlen, buf);
395 
396 	return RTW_HAL_STATUS_SUCCESS;
397 }
398 #endif /* CONFIG_SDIO_HCI */
399 
400 #define TX_DBG_STATUS_DUMP_INTERVAL 30000 /* ms */
rtw_hal_tx_dbg_status_dump(void * hal)401 void rtw_hal_tx_dbg_status_dump(void *hal)
402 {
403 	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
404 	struct hal_mac_dbg_dump_cfg cfg = {0};
405 	static u32 last_dump_t = 0;
406 
407 	cfg.tx_flow_dbg = 1;
408 
409 	if (phl_get_passing_time_ms(last_dump_t) >= TX_DBG_STATUS_DUMP_INTERVAL) {
410 		rtw_hal_mac_dbg_status_dump(hal_info, &cfg);
411 		last_dump_t = _os_get_cur_time_ms();
412 	}
413 }
414 
415