xref: /linux/drivers/net/wwan/t7xx/t7xx_hif_dpmaif.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2021, MediaTek Inc.
4  * Copyright (c) 2021-2022, Intel Corporation.
5  *
6  * Authors:
7  *  Amir Hanania <amir.hanania@intel.com>
8  *  Haijun Liu <haijun.liu@mediatek.com>
9  *  Moises Veleta <moises.veleta@intel.com>
10  *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
11  *
12  * Contributors:
13  *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
14  *  Eliot Lee <eliot.lee@intel.com>
15  *  Sreehari Kancharla <sreehari.kancharla@intel.com>
16  */
17 
18 #include <linux/device.h>
19 #include <linux/gfp.h>
20 #include <linux/irqreturn.h>
21 #include <linux/kernel.h>
22 #include <linux/list.h>
23 #include <linux/string.h>
24 #include <linux/wait.h>
25 #include <linux/workqueue.h>
26 
27 #include "t7xx_dpmaif.h"
28 #include "t7xx_hif_dpmaif.h"
29 #include "t7xx_hif_dpmaif_rx.h"
30 #include "t7xx_hif_dpmaif_tx.h"
31 #include "t7xx_pci.h"
32 #include "t7xx_pcie_mac.h"
33 #include "t7xx_state_monitor.h"
34 
35 unsigned int t7xx_ring_buf_get_next_wr_idx(unsigned int buf_len, unsigned int buf_idx)
36 {
37 	buf_idx++;
38 
39 	return buf_idx < buf_len ? buf_idx : 0;
40 }
41 
42 unsigned int t7xx_ring_buf_rd_wr_count(unsigned int total_cnt, unsigned int rd_idx,
43 				       unsigned int wr_idx, enum dpmaif_rdwr rd_wr)
44 {
45 	int pkt_cnt;
46 
47 	if (rd_wr == DPMAIF_READ)
48 		pkt_cnt = wr_idx - rd_idx;
49 	else
50 		pkt_cnt = rd_idx - wr_idx - 1;
51 
52 	if (pkt_cnt < 0)
53 		pkt_cnt += total_cnt;
54 
55 	return (unsigned int)pkt_cnt;
56 }
57 
58 static void t7xx_dpmaif_enable_irq(struct dpmaif_ctrl *dpmaif_ctrl)
59 {
60 	struct dpmaif_isr_para *isr_para;
61 	int i;
62 
63 	for (i = 0; i < ARRAY_SIZE(dpmaif_ctrl->isr_para); i++) {
64 		isr_para = &dpmaif_ctrl->isr_para[i];
65 		t7xx_pcie_mac_set_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
66 	}
67 }
68 
69 static void t7xx_dpmaif_disable_irq(struct dpmaif_ctrl *dpmaif_ctrl)
70 {
71 	struct dpmaif_isr_para *isr_para;
72 	int i;
73 
74 	for (i = 0; i < ARRAY_SIZE(dpmaif_ctrl->isr_para); i++) {
75 		isr_para = &dpmaif_ctrl->isr_para[i];
76 		t7xx_pcie_mac_clear_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
77 	}
78 }
79 
80 static void t7xx_dpmaif_irq_cb(struct dpmaif_isr_para *isr_para)
81 {
82 	struct dpmaif_ctrl *dpmaif_ctrl = isr_para->dpmaif_ctrl;
83 	struct dpmaif_hw_intr_st_para intr_status;
84 	struct device *dev = dpmaif_ctrl->dev;
85 	struct dpmaif_hw_info *hw_info;
86 	int i;
87 
88 	memset(&intr_status, 0, sizeof(intr_status));
89 	hw_info = &dpmaif_ctrl->hw_info;
90 
91 	if (t7xx_dpmaif_hw_get_intr_cnt(hw_info, &intr_status, isr_para->dlq_id) < 0) {
92 		dev_err(dev, "Failed to get HW interrupt count\n");
93 		return;
94 	}
95 
96 	t7xx_pcie_mac_clear_int_status(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
97 
98 	for (i = 0; i < intr_status.intr_cnt; i++) {
99 		switch (intr_status.intr_types[i]) {
100 		case DPF_INTR_UL_DONE:
101 			t7xx_dpmaif_irq_tx_done(dpmaif_ctrl, intr_status.intr_queues[i]);
102 			break;
103 
104 		case DPF_INTR_UL_DRB_EMPTY:
105 		case DPF_INTR_UL_MD_NOTREADY:
106 		case DPF_INTR_UL_MD_PWR_NOTREADY:
107 			/* No need to log an error for these */
108 			break;
109 
110 		case DPF_INTR_DL_BATCNT_LEN_ERR:
111 			dev_err_ratelimited(dev, "DL interrupt: packet BAT count length error\n");
112 			t7xx_dpmaif_dl_unmask_batcnt_len_err_intr(hw_info);
113 			break;
114 
115 		case DPF_INTR_DL_PITCNT_LEN_ERR:
116 			dev_err_ratelimited(dev, "DL interrupt: PIT count length error\n");
117 			t7xx_dpmaif_dl_unmask_pitcnt_len_err_intr(hw_info);
118 			break;
119 
120 		case DPF_INTR_DL_Q0_PITCNT_LEN_ERR:
121 			dev_err_ratelimited(dev, "DL interrupt: DLQ0 PIT count length error\n");
122 			t7xx_dpmaif_dlq_unmask_pitcnt_len_err_intr(hw_info, DPF_RX_QNO_DFT);
123 			break;
124 
125 		case DPF_INTR_DL_Q1_PITCNT_LEN_ERR:
126 			dev_err_ratelimited(dev, "DL interrupt: DLQ1 PIT count length error\n");
127 			t7xx_dpmaif_dlq_unmask_pitcnt_len_err_intr(hw_info, DPF_RX_QNO1);
128 			break;
129 
130 		case DPF_INTR_DL_DONE:
131 		case DPF_INTR_DL_Q0_DONE:
132 		case DPF_INTR_DL_Q1_DONE:
133 			t7xx_dpmaif_irq_rx_done(dpmaif_ctrl, intr_status.intr_queues[i]);
134 			break;
135 
136 		default:
137 			dev_err_ratelimited(dev, "DL interrupt error: unknown type : %d\n",
138 					    intr_status.intr_types[i]);
139 		}
140 	}
141 }
142 
143 static irqreturn_t t7xx_dpmaif_isr_handler(int irq, void *data)
144 {
145 	struct dpmaif_isr_para *isr_para = data;
146 	struct dpmaif_ctrl *dpmaif_ctrl;
147 
148 	dpmaif_ctrl = isr_para->dpmaif_ctrl;
149 	if (dpmaif_ctrl->state != DPMAIF_STATE_PWRON) {
150 		dev_err(dpmaif_ctrl->dev, "Interrupt received before initializing DPMAIF\n");
151 		return IRQ_HANDLED;
152 	}
153 
154 	t7xx_pcie_mac_clear_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
155 
156 	return IRQ_WAKE_THREAD;
157 }
158 
159 static irqreturn_t t7xx_dpmaif_isr_thread(int irq, void *data)
160 {
161 	struct dpmaif_isr_para *isr_para = data;
162 	struct dpmaif_ctrl *dpmaif_ctrl = isr_para->dpmaif_ctrl;
163 
164 	t7xx_dpmaif_irq_cb(isr_para);
165 	t7xx_pcie_mac_set_int(dpmaif_ctrl->t7xx_dev, isr_para->pcie_int);
166 	return IRQ_HANDLED;
167 }
168 
169 static void t7xx_dpmaif_isr_parameter_init(struct dpmaif_ctrl *dpmaif_ctrl)
170 {
171 	struct dpmaif_isr_para *isr_para;
172 	unsigned char i;
173 
174 	dpmaif_ctrl->rxq_int_mapping[DPF_RX_QNO0] = DPMAIF_INT;
175 	dpmaif_ctrl->rxq_int_mapping[DPF_RX_QNO1] = DPMAIF2_INT;
176 
177 	for (i = 0; i < DPMAIF_RXQ_NUM; i++) {
178 		isr_para = &dpmaif_ctrl->isr_para[i];
179 		isr_para->dpmaif_ctrl = dpmaif_ctrl;
180 		isr_para->dlq_id = i;
181 		isr_para->pcie_int = dpmaif_ctrl->rxq_int_mapping[i];
182 	}
183 }
184 
185 static void t7xx_dpmaif_register_pcie_irq(struct dpmaif_ctrl *dpmaif_ctrl)
186 {
187 	struct t7xx_pci_dev *t7xx_dev = dpmaif_ctrl->t7xx_dev;
188 	struct dpmaif_isr_para *isr_para;
189 	enum t7xx_int int_type;
190 	int i;
191 
192 	t7xx_dpmaif_isr_parameter_init(dpmaif_ctrl);
193 
194 	for (i = 0; i < DPMAIF_RXQ_NUM; i++) {
195 		isr_para = &dpmaif_ctrl->isr_para[i];
196 		int_type = isr_para->pcie_int;
197 		t7xx_pcie_mac_clear_int(t7xx_dev, int_type);
198 
199 		t7xx_dev->intr_handler[int_type] = t7xx_dpmaif_isr_handler;
200 		t7xx_dev->intr_thread[int_type] = t7xx_dpmaif_isr_thread;
201 		t7xx_dev->callback_param[int_type] = isr_para;
202 
203 		t7xx_pcie_mac_clear_int_status(t7xx_dev, int_type);
204 		t7xx_pcie_mac_set_int(t7xx_dev, int_type);
205 	}
206 }
207 
208 static int t7xx_dpmaif_rxtx_sw_allocs(struct dpmaif_ctrl *dpmaif_ctrl)
209 {
210 	struct dpmaif_rx_queue *rx_q;
211 	struct dpmaif_tx_queue *tx_q;
212 	int ret, rx_idx, tx_idx, i;
213 
214 	ret = t7xx_dpmaif_bat_alloc(dpmaif_ctrl, &dpmaif_ctrl->bat_req, BAT_TYPE_NORMAL);
215 	if (ret) {
216 		dev_err(dpmaif_ctrl->dev, "Failed to allocate normal BAT table: %d\n", ret);
217 		return ret;
218 	}
219 
220 	ret = t7xx_dpmaif_bat_alloc(dpmaif_ctrl, &dpmaif_ctrl->bat_frag, BAT_TYPE_FRAG);
221 	if (ret) {
222 		dev_err(dpmaif_ctrl->dev, "Failed to allocate frag BAT table: %d\n", ret);
223 		goto err_free_normal_bat;
224 	}
225 
226 	for (rx_idx = 0; rx_idx < DPMAIF_RXQ_NUM; rx_idx++) {
227 		rx_q = &dpmaif_ctrl->rxq[rx_idx];
228 		rx_q->index = rx_idx;
229 		rx_q->dpmaif_ctrl = dpmaif_ctrl;
230 		ret = t7xx_dpmaif_rxq_init(rx_q);
231 		if (ret)
232 			goto err_free_rxq;
233 	}
234 
235 	for (tx_idx = 0; tx_idx < DPMAIF_TXQ_NUM; tx_idx++) {
236 		tx_q = &dpmaif_ctrl->txq[tx_idx];
237 		tx_q->index = tx_idx;
238 		tx_q->dpmaif_ctrl = dpmaif_ctrl;
239 		ret = t7xx_dpmaif_txq_init(tx_q);
240 		if (ret)
241 			goto err_free_txq;
242 	}
243 
244 	ret = t7xx_dpmaif_tx_thread_init(dpmaif_ctrl);
245 	if (ret) {
246 		dev_err(dpmaif_ctrl->dev, "Failed to start TX thread\n");
247 		goto err_free_txq;
248 	}
249 
250 	ret = t7xx_dpmaif_bat_rel_wq_alloc(dpmaif_ctrl);
251 	if (ret)
252 		goto err_thread_rel;
253 
254 	return 0;
255 
256 err_thread_rel:
257 	t7xx_dpmaif_tx_thread_rel(dpmaif_ctrl);
258 
259 err_free_txq:
260 	for (i = 0; i < tx_idx; i++) {
261 		tx_q = &dpmaif_ctrl->txq[i];
262 		t7xx_dpmaif_txq_free(tx_q);
263 	}
264 
265 err_free_rxq:
266 	for (i = 0; i < rx_idx; i++) {
267 		rx_q = &dpmaif_ctrl->rxq[i];
268 		t7xx_dpmaif_rxq_free(rx_q);
269 	}
270 
271 	t7xx_dpmaif_bat_free(dpmaif_ctrl, &dpmaif_ctrl->bat_frag);
272 
273 err_free_normal_bat:
274 	t7xx_dpmaif_bat_free(dpmaif_ctrl, &dpmaif_ctrl->bat_req);
275 
276 	return ret;
277 }
278 
279 static void t7xx_dpmaif_sw_release(struct dpmaif_ctrl *dpmaif_ctrl)
280 {
281 	struct dpmaif_rx_queue *rx_q;
282 	struct dpmaif_tx_queue *tx_q;
283 	int i;
284 
285 	t7xx_dpmaif_tx_thread_rel(dpmaif_ctrl);
286 	t7xx_dpmaif_bat_wq_rel(dpmaif_ctrl);
287 
288 	for (i = 0; i < DPMAIF_TXQ_NUM; i++) {
289 		tx_q = &dpmaif_ctrl->txq[i];
290 		t7xx_dpmaif_txq_free(tx_q);
291 	}
292 
293 	for (i = 0; i < DPMAIF_RXQ_NUM; i++) {
294 		rx_q = &dpmaif_ctrl->rxq[i];
295 		t7xx_dpmaif_rxq_free(rx_q);
296 	}
297 }
298 
299 static int t7xx_dpmaif_start(struct dpmaif_ctrl *dpmaif_ctrl)
300 {
301 	struct dpmaif_hw_info *hw_info = &dpmaif_ctrl->hw_info;
302 	struct dpmaif_hw_params hw_init_para;
303 	struct dpmaif_rx_queue *rxq;
304 	struct dpmaif_tx_queue *txq;
305 	unsigned int buf_cnt;
306 	int i, ret = 0;
307 
308 	if (dpmaif_ctrl->state == DPMAIF_STATE_PWRON)
309 		return -EFAULT;
310 
311 	memset(&hw_init_para, 0, sizeof(hw_init_para));
312 
313 	for (i = 0; i < DPMAIF_RXQ_NUM; i++) {
314 		rxq = &dpmaif_ctrl->rxq[i];
315 		rxq->que_started = true;
316 		rxq->index = i;
317 		rxq->budget = rxq->bat_req->bat_size_cnt - 1;
318 
319 		hw_init_para.pkt_bat_base_addr[i] = rxq->bat_req->bat_bus_addr;
320 		hw_init_para.pkt_bat_size_cnt[i] = rxq->bat_req->bat_size_cnt;
321 		hw_init_para.pit_base_addr[i] = rxq->pit_bus_addr;
322 		hw_init_para.pit_size_cnt[i] = rxq->pit_size_cnt;
323 		hw_init_para.frg_bat_base_addr[i] = rxq->bat_frag->bat_bus_addr;
324 		hw_init_para.frg_bat_size_cnt[i] = rxq->bat_frag->bat_size_cnt;
325 	}
326 
327 	bitmap_zero(dpmaif_ctrl->bat_req.bat_bitmap, dpmaif_ctrl->bat_req.bat_size_cnt);
328 	buf_cnt = dpmaif_ctrl->bat_req.bat_size_cnt - 1;
329 	ret = t7xx_dpmaif_rx_buf_alloc(dpmaif_ctrl, &dpmaif_ctrl->bat_req, 0, buf_cnt, true);
330 	if (ret) {
331 		dev_err(dpmaif_ctrl->dev, "Failed to allocate RX buffer: %d\n", ret);
332 		return ret;
333 	}
334 
335 	buf_cnt = dpmaif_ctrl->bat_frag.bat_size_cnt - 1;
336 	ret = t7xx_dpmaif_rx_frag_alloc(dpmaif_ctrl, &dpmaif_ctrl->bat_frag, buf_cnt, true);
337 	if (ret) {
338 		dev_err(dpmaif_ctrl->dev, "Failed to allocate frag RX buffer: %d\n", ret);
339 		goto err_free_normal_bat;
340 	}
341 
342 	for (i = 0; i < DPMAIF_TXQ_NUM; i++) {
343 		txq = &dpmaif_ctrl->txq[i];
344 		txq->que_started = true;
345 
346 		hw_init_para.drb_base_addr[i] = txq->drb_bus_addr;
347 		hw_init_para.drb_size_cnt[i] = txq->drb_size_cnt;
348 	}
349 
350 	ret = t7xx_dpmaif_hw_init(hw_info, &hw_init_para);
351 	if (ret) {
352 		dev_err(dpmaif_ctrl->dev, "Failed to initialize DPMAIF HW: %d\n", ret);
353 		goto err_free_frag_bat;
354 	}
355 
356 	ret = t7xx_dpmaif_dl_snd_hw_bat_cnt(hw_info, rxq->bat_req->bat_size_cnt - 1);
357 	if (ret)
358 		goto err_free_frag_bat;
359 
360 	ret = t7xx_dpmaif_dl_snd_hw_frg_cnt(hw_info, rxq->bat_frag->bat_size_cnt - 1);
361 	if (ret)
362 		goto err_free_frag_bat;
363 
364 	t7xx_dpmaif_ul_clr_all_intr(hw_info);
365 	t7xx_dpmaif_dl_clr_all_intr(hw_info);
366 	dpmaif_ctrl->state = DPMAIF_STATE_PWRON;
367 	t7xx_dpmaif_enable_irq(dpmaif_ctrl);
368 	wake_up(&dpmaif_ctrl->tx_wq);
369 	return 0;
370 
371 err_free_frag_bat:
372 	t7xx_dpmaif_bat_free(rxq->dpmaif_ctrl, rxq->bat_frag);
373 
374 err_free_normal_bat:
375 	t7xx_dpmaif_bat_free(rxq->dpmaif_ctrl, rxq->bat_req);
376 
377 	return ret;
378 }
379 
380 static void t7xx_dpmaif_stop_sw(struct dpmaif_ctrl *dpmaif_ctrl)
381 {
382 	t7xx_dpmaif_tx_stop(dpmaif_ctrl);
383 	t7xx_dpmaif_rx_stop(dpmaif_ctrl);
384 }
385 
386 static void t7xx_dpmaif_stop_hw(struct dpmaif_ctrl *dpmaif_ctrl)
387 {
388 	t7xx_dpmaif_hw_stop_all_txq(&dpmaif_ctrl->hw_info);
389 	t7xx_dpmaif_hw_stop_all_rxq(&dpmaif_ctrl->hw_info);
390 }
391 
392 static int t7xx_dpmaif_stop(struct dpmaif_ctrl *dpmaif_ctrl)
393 {
394 	if (!dpmaif_ctrl->dpmaif_sw_init_done) {
395 		dev_err(dpmaif_ctrl->dev, "dpmaif SW init fail\n");
396 		return -EFAULT;
397 	}
398 
399 	if (dpmaif_ctrl->state == DPMAIF_STATE_PWROFF)
400 		return -EFAULT;
401 
402 	t7xx_dpmaif_disable_irq(dpmaif_ctrl);
403 	dpmaif_ctrl->state = DPMAIF_STATE_PWROFF;
404 	t7xx_dpmaif_stop_sw(dpmaif_ctrl);
405 	t7xx_dpmaif_tx_clear(dpmaif_ctrl);
406 	t7xx_dpmaif_rx_clear(dpmaif_ctrl);
407 	return 0;
408 }
409 
410 static int t7xx_dpmaif_suspend(struct t7xx_pci_dev *t7xx_dev, void *param)
411 {
412 	struct dpmaif_ctrl *dpmaif_ctrl = param;
413 
414 	t7xx_dpmaif_tx_stop(dpmaif_ctrl);
415 	t7xx_dpmaif_hw_stop_all_txq(&dpmaif_ctrl->hw_info);
416 	t7xx_dpmaif_hw_stop_all_rxq(&dpmaif_ctrl->hw_info);
417 	t7xx_dpmaif_disable_irq(dpmaif_ctrl);
418 	t7xx_dpmaif_rx_stop(dpmaif_ctrl);
419 	return 0;
420 }
421 
422 static void t7xx_dpmaif_unmask_dlq_intr(struct dpmaif_ctrl *dpmaif_ctrl)
423 {
424 	int qno;
425 
426 	for (qno = 0; qno < DPMAIF_RXQ_NUM; qno++)
427 		t7xx_dpmaif_dlq_unmask_rx_done(&dpmaif_ctrl->hw_info, qno);
428 }
429 
430 static void t7xx_dpmaif_start_txrx_qs(struct dpmaif_ctrl *dpmaif_ctrl)
431 {
432 	struct dpmaif_rx_queue *rxq;
433 	struct dpmaif_tx_queue *txq;
434 	unsigned int que_cnt;
435 
436 	for (que_cnt = 0; que_cnt < DPMAIF_TXQ_NUM; que_cnt++) {
437 		txq = &dpmaif_ctrl->txq[que_cnt];
438 		txq->que_started = true;
439 	}
440 
441 	for (que_cnt = 0; que_cnt < DPMAIF_RXQ_NUM; que_cnt++) {
442 		rxq = &dpmaif_ctrl->rxq[que_cnt];
443 		rxq->que_started = true;
444 	}
445 }
446 
447 static int t7xx_dpmaif_resume(struct t7xx_pci_dev *t7xx_dev, void *param)
448 {
449 	struct dpmaif_ctrl *dpmaif_ctrl = param;
450 
451 	if (!dpmaif_ctrl)
452 		return 0;
453 
454 	t7xx_dpmaif_start_txrx_qs(dpmaif_ctrl);
455 	t7xx_dpmaif_enable_irq(dpmaif_ctrl);
456 	t7xx_dpmaif_unmask_dlq_intr(dpmaif_ctrl);
457 	t7xx_dpmaif_start_hw(&dpmaif_ctrl->hw_info);
458 	wake_up(&dpmaif_ctrl->tx_wq);
459 	return 0;
460 }
461 
462 static int t7xx_dpmaif_pm_entity_init(struct dpmaif_ctrl *dpmaif_ctrl)
463 {
464 	struct md_pm_entity *dpmaif_pm_entity = &dpmaif_ctrl->dpmaif_pm_entity;
465 	int ret;
466 
467 	INIT_LIST_HEAD(&dpmaif_pm_entity->entity);
468 	dpmaif_pm_entity->suspend = &t7xx_dpmaif_suspend;
469 	dpmaif_pm_entity->suspend_late = NULL;
470 	dpmaif_pm_entity->resume_early = NULL;
471 	dpmaif_pm_entity->resume = &t7xx_dpmaif_resume;
472 	dpmaif_pm_entity->id = PM_ENTITY_ID_DATA;
473 	dpmaif_pm_entity->entity_param = dpmaif_ctrl;
474 
475 	ret = t7xx_pci_pm_entity_register(dpmaif_ctrl->t7xx_dev, dpmaif_pm_entity);
476 	if (ret)
477 		dev_err(dpmaif_ctrl->dev, "dpmaif register pm_entity fail\n");
478 
479 	return ret;
480 }
481 
482 static int t7xx_dpmaif_pm_entity_release(struct dpmaif_ctrl *dpmaif_ctrl)
483 {
484 	struct md_pm_entity *dpmaif_pm_entity = &dpmaif_ctrl->dpmaif_pm_entity;
485 	int ret;
486 
487 	ret = t7xx_pci_pm_entity_unregister(dpmaif_ctrl->t7xx_dev, dpmaif_pm_entity);
488 	if (ret < 0)
489 		dev_err(dpmaif_ctrl->dev, "dpmaif register pm_entity fail\n");
490 
491 	return ret;
492 }
493 
494 int t7xx_dpmaif_md_state_callback(struct dpmaif_ctrl *dpmaif_ctrl, enum md_state state)
495 {
496 	int ret = 0;
497 
498 	switch (state) {
499 	case MD_STATE_WAITING_FOR_HS1:
500 		ret = t7xx_dpmaif_start(dpmaif_ctrl);
501 		break;
502 
503 	case MD_STATE_EXCEPTION:
504 		ret = t7xx_dpmaif_stop(dpmaif_ctrl);
505 		break;
506 
507 	case MD_STATE_STOPPED:
508 		ret = t7xx_dpmaif_stop(dpmaif_ctrl);
509 		break;
510 
511 	case MD_STATE_WAITING_TO_STOP:
512 		t7xx_dpmaif_stop_hw(dpmaif_ctrl);
513 		break;
514 
515 	default:
516 		break;
517 	}
518 
519 	return ret;
520 }
521 
522 /**
523  * t7xx_dpmaif_hif_init() - Initialize data path.
524  * @t7xx_dev: MTK context structure.
525  * @callbacks: Callbacks implemented by the network layer to handle RX skb and
526  *	       event notifications.
527  *
528  * Allocate and initialize datapath control block.
529  * Register datapath ISR, TX and RX resources.
530  *
531  * Return:
532  * * dpmaif_ctrl pointer - Pointer to DPMAIF context structure.
533  * * NULL		 - In case of error.
534  */
535 struct dpmaif_ctrl *t7xx_dpmaif_hif_init(struct t7xx_pci_dev *t7xx_dev,
536 					 struct dpmaif_callbacks *callbacks)
537 {
538 	struct device *dev = &t7xx_dev->pdev->dev;
539 	struct dpmaif_ctrl *dpmaif_ctrl;
540 	int ret;
541 
542 	if (!callbacks)
543 		return NULL;
544 
545 	dpmaif_ctrl = devm_kzalloc(dev, sizeof(*dpmaif_ctrl), GFP_KERNEL);
546 	if (!dpmaif_ctrl)
547 		return NULL;
548 
549 	dpmaif_ctrl->t7xx_dev = t7xx_dev;
550 	dpmaif_ctrl->callbacks = callbacks;
551 	dpmaif_ctrl->dev = dev;
552 	dpmaif_ctrl->dpmaif_sw_init_done = false;
553 	dpmaif_ctrl->hw_info.dev = dev;
554 	dpmaif_ctrl->hw_info.pcie_base = t7xx_dev->base_addr.pcie_ext_reg_base -
555 					 t7xx_dev->base_addr.pcie_dev_reg_trsl_addr;
556 
557 	ret = t7xx_dpmaif_pm_entity_init(dpmaif_ctrl);
558 	if (ret)
559 		return NULL;
560 
561 	t7xx_dpmaif_register_pcie_irq(dpmaif_ctrl);
562 	t7xx_dpmaif_disable_irq(dpmaif_ctrl);
563 
564 	ret = t7xx_dpmaif_rxtx_sw_allocs(dpmaif_ctrl);
565 	if (ret) {
566 		t7xx_dpmaif_pm_entity_release(dpmaif_ctrl);
567 		dev_err(dev, "Failed to allocate RX/TX SW resources: %d\n", ret);
568 		return NULL;
569 	}
570 
571 	dpmaif_ctrl->dpmaif_sw_init_done = true;
572 	return dpmaif_ctrl;
573 }
574 
575 void t7xx_dpmaif_hif_exit(struct dpmaif_ctrl *dpmaif_ctrl)
576 {
577 	if (dpmaif_ctrl->dpmaif_sw_init_done) {
578 		t7xx_dpmaif_stop(dpmaif_ctrl);
579 		t7xx_dpmaif_pm_entity_release(dpmaif_ctrl);
580 		t7xx_dpmaif_sw_release(dpmaif_ctrl);
581 		dpmaif_ctrl->dpmaif_sw_init_done = false;
582 	}
583 }
584