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 * Andy Shevchenko <andriy.shevchenko@linux.intel.com>
14 * Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
15 * Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
16 * Eliot Lee <eliot.lee@intel.com>
17 * Sreehari Kancharla <sreehari.kancharla@intel.com>
18 */
19
20 #include <linux/bits.h>
21 #include <linux/bitfield.h>
22 #include <linux/device.h>
23 #include <linux/gfp.h>
24 #include <linux/kernel.h>
25 #include <linux/kthread.h>
26 #include <linux/list.h>
27 #include <linux/mutex.h>
28 #include <linux/netdevice.h>
29 #include <linux/skbuff.h>
30 #include <linux/spinlock.h>
31 #include <linux/wait.h>
32 #include <linux/wwan.h>
33
34 #include "t7xx_hif_cldma.h"
35 #include "t7xx_modem_ops.h"
36 #include "t7xx_port.h"
37 #include "t7xx_port_proxy.h"
38 #include "t7xx_state_monitor.h"
39
40 #define Q_IDX_CTRL 0
41 #define Q_IDX_MBIM 2
42 #define Q_IDX_AT_CMD 5
43
44 #define INVALID_SEQ_NUM GENMASK(15, 0)
45
46 #define for_each_proxy_port(i, p, proxy) \
47 for (i = 0, (p) = &(proxy)->ports[i]; \
48 i < (proxy)->port_count; \
49 i++, (p) = &(proxy)->ports[i])
50
51 #define T7XX_MAX_POSSIBLE_PORTS_NUM \
52 (max(ARRAY_SIZE(t7xx_port_conf), ARRAY_SIZE(t7xx_early_port_conf)))
53
54 static const struct t7xx_port_conf t7xx_port_conf[] = {
55 {
56 .tx_ch = PORT_CH_UART2_TX,
57 .rx_ch = PORT_CH_UART2_RX,
58 .txq_index = Q_IDX_AT_CMD,
59 .rxq_index = Q_IDX_AT_CMD,
60 .txq_exp_index = 0xff,
61 .rxq_exp_index = 0xff,
62 .path_id = CLDMA_ID_MD,
63 .ops = &wwan_sub_port_ops,
64 .name = "AT",
65 .port_type = WWAN_PORT_AT,
66 }, {
67 .tx_ch = PORT_CH_MBIM_TX,
68 .rx_ch = PORT_CH_MBIM_RX,
69 .txq_index = Q_IDX_MBIM,
70 .rxq_index = Q_IDX_MBIM,
71 .path_id = CLDMA_ID_MD,
72 .ops = &wwan_sub_port_ops,
73 .name = "MBIM",
74 .port_type = WWAN_PORT_MBIM,
75 }, {
76 #ifdef CONFIG_WWAN_DEBUGFS
77 .tx_ch = PORT_CH_MD_LOG_TX,
78 .rx_ch = PORT_CH_MD_LOG_RX,
79 .txq_index = 7,
80 .rxq_index = 7,
81 .txq_exp_index = 7,
82 .rxq_exp_index = 7,
83 .path_id = CLDMA_ID_MD,
84 .ops = &t7xx_trace_port_ops,
85 .name = "mdlog",
86 }, {
87 #endif
88 .tx_ch = PORT_CH_CONTROL_TX,
89 .rx_ch = PORT_CH_CONTROL_RX,
90 .txq_index = Q_IDX_CTRL,
91 .rxq_index = Q_IDX_CTRL,
92 .path_id = CLDMA_ID_MD,
93 .ops = &ctl_port_ops,
94 .name = "t7xx_ctrl",
95 }, {
96 .tx_ch = PORT_CH_AP_CONTROL_TX,
97 .rx_ch = PORT_CH_AP_CONTROL_RX,
98 .txq_index = Q_IDX_CTRL,
99 .rxq_index = Q_IDX_CTRL,
100 .path_id = CLDMA_ID_AP,
101 .ops = &ctl_port_ops,
102 .name = "t7xx_ap_ctrl",
103 },
104 };
105
106 static const struct t7xx_port_conf t7xx_early_port_conf[] = {
107 {
108 .tx_ch = PORT_CH_UNIMPORTANT,
109 .rx_ch = PORT_CH_UNIMPORTANT,
110 .txq_index = CLDMA_Q_IDX_DUMP,
111 .rxq_index = CLDMA_Q_IDX_DUMP,
112 .txq_exp_index = CLDMA_Q_IDX_DUMP,
113 .rxq_exp_index = CLDMA_Q_IDX_DUMP,
114 .path_id = CLDMA_ID_AP,
115 .ops = &wwan_sub_port_ops,
116 .name = "fastboot",
117 .port_type = WWAN_PORT_FASTBOOT,
118 },
119 };
120
t7xx_proxy_get_port_by_ch(struct port_proxy * port_prox,enum port_ch ch)121 static struct t7xx_port *t7xx_proxy_get_port_by_ch(struct port_proxy *port_prox, enum port_ch ch)
122 {
123 const struct t7xx_port_conf *port_conf;
124 struct t7xx_port *port;
125 int i;
126
127 for_each_proxy_port(i, port, port_prox) {
128 port_conf = port->port_conf;
129 if (port_conf->rx_ch == ch || port_conf->tx_ch == ch)
130 return port;
131 }
132
133 return NULL;
134 }
135
t7xx_port_next_rx_seq_num(struct t7xx_port * port,struct ccci_header * ccci_h)136 static u16 t7xx_port_next_rx_seq_num(struct t7xx_port *port, struct ccci_header *ccci_h)
137 {
138 u32 status = le32_to_cpu(ccci_h->status);
139 u16 seq_num, next_seq_num;
140 bool assert_bit;
141
142 seq_num = FIELD_GET(CCCI_H_SEQ_FLD, status);
143 next_seq_num = (seq_num + 1) & FIELD_MAX(CCCI_H_SEQ_FLD);
144 assert_bit = status & CCCI_H_AST_BIT;
145 if (!assert_bit || port->seq_nums[MTK_RX] == INVALID_SEQ_NUM)
146 return next_seq_num;
147
148 if (seq_num != port->seq_nums[MTK_RX])
149 dev_warn_ratelimited(port->dev,
150 "seq num out-of-order %u != %u (header %X, len %X)\n",
151 seq_num, port->seq_nums[MTK_RX],
152 le32_to_cpu(ccci_h->packet_header),
153 le32_to_cpu(ccci_h->packet_len));
154
155 return next_seq_num;
156 }
157
t7xx_port_proxy_reset(struct port_proxy * port_prox)158 void t7xx_port_proxy_reset(struct port_proxy *port_prox)
159 {
160 struct t7xx_port *port;
161 int i;
162
163 for_each_proxy_port(i, port, port_prox) {
164 port->seq_nums[MTK_RX] = INVALID_SEQ_NUM;
165 port->seq_nums[MTK_TX] = 0;
166 }
167 }
168
t7xx_port_get_queue_no(struct t7xx_port * port)169 static int t7xx_port_get_queue_no(struct t7xx_port *port)
170 {
171 const struct t7xx_port_conf *port_conf = port->port_conf;
172 struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
173
174 return t7xx_fsm_get_md_state(ctl) == MD_STATE_EXCEPTION ?
175 port_conf->txq_exp_index : port_conf->txq_index;
176 }
177
t7xx_port_struct_init(struct t7xx_port * port)178 static void t7xx_port_struct_init(struct t7xx_port *port)
179 {
180 INIT_LIST_HEAD(&port->entry);
181 INIT_LIST_HEAD(&port->queue_entry);
182 skb_queue_head_init(&port->rx_skb_list);
183 init_waitqueue_head(&port->rx_wq);
184 port->seq_nums[MTK_RX] = INVALID_SEQ_NUM;
185 port->seq_nums[MTK_TX] = 0;
186 atomic_set(&port->usage_cnt, 0);
187 }
188
t7xx_port_alloc_skb(int payload)189 struct sk_buff *t7xx_port_alloc_skb(int payload)
190 {
191 struct sk_buff *skb = __dev_alloc_skb(payload + sizeof(struct ccci_header), GFP_KERNEL);
192
193 if (skb)
194 skb_reserve(skb, sizeof(struct ccci_header));
195
196 return skb;
197 }
198
t7xx_ctrl_alloc_skb(int payload)199 struct sk_buff *t7xx_ctrl_alloc_skb(int payload)
200 {
201 struct sk_buff *skb = t7xx_port_alloc_skb(payload + sizeof(struct ctrl_msg_header));
202
203 if (skb)
204 skb_reserve(skb, sizeof(struct ctrl_msg_header));
205
206 return skb;
207 }
208
209 /**
210 * t7xx_port_enqueue_skb() - Enqueue the received skb into the port's rx_skb_list.
211 * @port: port context.
212 * @skb: received skb.
213 *
214 * Return:
215 * * 0 - Success.
216 * * -ENOBUFS - Not enough buffer space. Caller will try again later, skb is not consumed.
217 */
t7xx_port_enqueue_skb(struct t7xx_port * port,struct sk_buff * skb)218 int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb)
219 {
220 unsigned long flags;
221
222 spin_lock_irqsave(&port->rx_wq.lock, flags);
223 if (port->rx_skb_list.qlen >= port->rx_length_th) {
224 spin_unlock_irqrestore(&port->rx_wq.lock, flags);
225
226 return -ENOBUFS;
227 }
228 __skb_queue_tail(&port->rx_skb_list, skb);
229 spin_unlock_irqrestore(&port->rx_wq.lock, flags);
230
231 wake_up_all(&port->rx_wq);
232 return 0;
233 }
234
t7xx_get_port_mtu(struct t7xx_port * port)235 int t7xx_get_port_mtu(struct t7xx_port *port)
236 {
237 enum cldma_id path_id = port->port_conf->path_id;
238 int tx_qno = t7xx_port_get_queue_no(port);
239 struct cldma_ctrl *md_ctrl;
240
241 md_ctrl = port->t7xx_dev->md->md_ctrl[path_id];
242 return md_ctrl->tx_ring[tx_qno].pkt_size;
243 }
244
t7xx_port_send_raw_skb(struct t7xx_port * port,struct sk_buff * skb)245 int t7xx_port_send_raw_skb(struct t7xx_port *port, struct sk_buff *skb)
246 {
247 enum cldma_id path_id = port->port_conf->path_id;
248 struct cldma_ctrl *md_ctrl;
249 int ret, tx_qno;
250
251 md_ctrl = port->t7xx_dev->md->md_ctrl[path_id];
252 tx_qno = t7xx_port_get_queue_no(port);
253 ret = t7xx_cldma_send_skb(md_ctrl, tx_qno, skb);
254 if (ret)
255 dev_err(port->dev, "Failed to send skb: %d\n", ret);
256
257 return ret;
258 }
259
t7xx_port_send_ccci_skb(struct t7xx_port * port,struct sk_buff * skb,unsigned int pkt_header,unsigned int ex_msg)260 static int t7xx_port_send_ccci_skb(struct t7xx_port *port, struct sk_buff *skb,
261 unsigned int pkt_header, unsigned int ex_msg)
262 {
263 const struct t7xx_port_conf *port_conf = port->port_conf;
264 struct ccci_header *ccci_h;
265 u32 status;
266 int ret;
267
268 ccci_h = skb_push(skb, sizeof(*ccci_h));
269 status = FIELD_PREP(CCCI_H_CHN_FLD, port_conf->tx_ch) |
270 FIELD_PREP(CCCI_H_SEQ_FLD, port->seq_nums[MTK_TX]) | CCCI_H_AST_BIT;
271 ccci_h->status = cpu_to_le32(status);
272 ccci_h->packet_header = cpu_to_le32(pkt_header);
273 ccci_h->packet_len = cpu_to_le32(skb->len);
274 ccci_h->ex_msg = cpu_to_le32(ex_msg);
275
276 ret = t7xx_port_send_raw_skb(port, skb);
277 if (ret)
278 return ret;
279
280 port->seq_nums[MTK_TX]++;
281 return 0;
282 }
283
t7xx_port_send_ctl_skb(struct t7xx_port * port,struct sk_buff * skb,unsigned int msg,unsigned int ex_msg)284 int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg,
285 unsigned int ex_msg)
286 {
287 struct ctrl_msg_header *ctrl_msg_h;
288 unsigned int msg_len = skb->len;
289 u32 pkt_header = 0;
290
291 ctrl_msg_h = skb_push(skb, sizeof(*ctrl_msg_h));
292 ctrl_msg_h->ctrl_msg_id = cpu_to_le32(msg);
293 ctrl_msg_h->ex_msg = cpu_to_le32(ex_msg);
294 ctrl_msg_h->data_length = cpu_to_le32(msg_len);
295
296 if (!msg_len)
297 pkt_header = CCCI_HEADER_NO_DATA;
298
299 return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg);
300 }
301
t7xx_port_send_skb(struct t7xx_port * port,struct sk_buff * skb,unsigned int pkt_header,unsigned int ex_msg)302 int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int pkt_header,
303 unsigned int ex_msg)
304 {
305 struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
306 unsigned int fsm_state;
307
308 fsm_state = t7xx_fsm_get_ctl_state(ctl);
309 if (fsm_state != FSM_STATE_PRE_START) {
310 const struct t7xx_port_conf *port_conf = port->port_conf;
311 enum md_state md_state = t7xx_fsm_get_md_state(ctl);
312
313 switch (md_state) {
314 case MD_STATE_EXCEPTION:
315 if (port_conf->tx_ch != PORT_CH_MD_LOG_TX)
316 return -EBUSY;
317 break;
318
319 case MD_STATE_WAITING_FOR_HS1:
320 case MD_STATE_WAITING_FOR_HS2:
321 case MD_STATE_STOPPED:
322 case MD_STATE_WAITING_TO_STOP:
323 case MD_STATE_INVALID:
324 return -ENODEV;
325
326 default:
327 break;
328 }
329 }
330
331 return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg);
332 }
333
t7xx_proxy_setup_ch_mapping(struct port_proxy * port_prox)334 static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox)
335 {
336 struct t7xx_port *port;
337
338 int i, j;
339
340 for (i = 0; i < ARRAY_SIZE(port_prox->rx_ch_ports); i++)
341 INIT_LIST_HEAD(&port_prox->rx_ch_ports[i]);
342
343 for (j = 0; j < ARRAY_SIZE(port_prox->queue_ports); j++) {
344 for (i = 0; i < ARRAY_SIZE(port_prox->queue_ports[j]); i++)
345 INIT_LIST_HEAD(&port_prox->queue_ports[j][i]);
346 }
347
348 for_each_proxy_port(i, port, port_prox) {
349 const struct t7xx_port_conf *port_conf = port->port_conf;
350 enum cldma_id path_id = port_conf->path_id;
351 u8 ch_id;
352
353 ch_id = FIELD_GET(PORT_CH_ID_MASK, port_conf->rx_ch);
354 list_add_tail(&port->entry, &port_prox->rx_ch_ports[ch_id]);
355 list_add_tail(&port->queue_entry,
356 &port_prox->queue_ports[path_id][port_conf->rxq_index]);
357 }
358 }
359
360 /**
361 * t7xx_port_proxy_recv_skb_from_dedicated_queue() - Dispatch early port received skb.
362 * @queue: CLDMA queue.
363 * @skb: Socket buffer.
364 *
365 * Return:
366 ** 0 - Packet consumed.
367 ** -ERROR - Failed to process skb.
368 */
t7xx_port_proxy_recv_skb_from_dedicated_queue(struct cldma_queue * queue,struct sk_buff * skb)369 int t7xx_port_proxy_recv_skb_from_dedicated_queue(struct cldma_queue *queue, struct sk_buff *skb)
370 {
371 struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;
372 struct port_proxy *port_prox = t7xx_dev->md->port_prox;
373 const struct t7xx_port_conf *port_conf;
374 struct t7xx_port *port;
375 int ret;
376
377 port = &port_prox->ports[0];
378 if (WARN_ON_ONCE(port->port_conf->rxq_index != queue->index)) {
379 dev_kfree_skb_any(skb);
380 return -EINVAL;
381 }
382
383 port_conf = port->port_conf;
384 ret = port_conf->ops->recv_skb(port, skb);
385 if (ret < 0 && ret != -ENOBUFS) {
386 dev_err(port->dev, "drop on RX ch %d, %d\n", port_conf->rx_ch, ret);
387 dev_kfree_skb_any(skb);
388 }
389
390 return ret;
391 }
392
t7xx_port_proxy_find_port(struct t7xx_pci_dev * t7xx_dev,struct cldma_queue * queue,u16 channel)393 static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev,
394 struct cldma_queue *queue, u16 channel)
395 {
396 struct port_proxy *port_prox = t7xx_dev->md->port_prox;
397 struct list_head *port_list;
398 struct t7xx_port *port;
399 u8 ch_id;
400
401 ch_id = FIELD_GET(PORT_CH_ID_MASK, channel);
402 port_list = &port_prox->rx_ch_ports[ch_id];
403 list_for_each_entry(port, port_list, entry) {
404 const struct t7xx_port_conf *port_conf = port->port_conf;
405
406 if (queue->md_ctrl->hif_id == port_conf->path_id &&
407 channel == port_conf->rx_ch)
408 return port;
409 }
410
411 return NULL;
412 }
413
414 /**
415 * t7xx_port_proxy_recv_skb() - Dispatch received skb.
416 * @queue: CLDMA queue.
417 * @skb: Socket buffer.
418 *
419 * Return:
420 ** 0 - Packet consumed.
421 ** -ERROR - Failed to process skb.
422 */
t7xx_port_proxy_recv_skb(struct cldma_queue * queue,struct sk_buff * skb)423 int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb)
424 {
425 struct ccci_header *ccci_h = (struct ccci_header *)skb->data;
426 struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;
427 struct t7xx_fsm_ctl *ctl = t7xx_dev->md->fsm_ctl;
428 struct device *dev = queue->md_ctrl->dev;
429 const struct t7xx_port_conf *port_conf;
430 struct t7xx_port *port;
431 u16 seq_num, channel;
432 int ret;
433
434 channel = FIELD_GET(CCCI_H_CHN_FLD, le32_to_cpu(ccci_h->status));
435 if (t7xx_fsm_get_md_state(ctl) == MD_STATE_INVALID) {
436 dev_err_ratelimited(dev, "Packet drop on channel 0x%x, modem not ready\n", channel);
437 goto drop_skb;
438 }
439
440 port = t7xx_port_proxy_find_port(t7xx_dev, queue, channel);
441 if (!port) {
442 dev_err_ratelimited(dev, "Packet drop on channel 0x%x, port not found\n", channel);
443 goto drop_skb;
444 }
445
446 seq_num = t7xx_port_next_rx_seq_num(port, ccci_h);
447 port_conf = port->port_conf;
448 skb_pull(skb, sizeof(*ccci_h));
449
450 ret = port_conf->ops->recv_skb(port, skb);
451 /* Error indicates to try again later */
452 if (ret) {
453 skb_push(skb, sizeof(*ccci_h));
454 return ret;
455 }
456
457 port->seq_nums[MTK_RX] = seq_num;
458 return 0;
459
460 drop_skb:
461 dev_kfree_skb_any(skb);
462 return 0;
463 }
464
465 /**
466 * t7xx_port_proxy_md_status_notify() - Notify all ports of state.
467 *@port_prox: The port_proxy pointer.
468 *@state: State.
469 *
470 * Called by t7xx_fsm. Used to dispatch modem status for all ports,
471 * which want to know MD state transition.
472 */
t7xx_port_proxy_md_status_notify(struct port_proxy * port_prox,unsigned int state)473 void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned int state)
474 {
475 struct t7xx_port *port;
476 int i;
477
478 for_each_proxy_port(i, port, port_prox) {
479 const struct t7xx_port_conf *port_conf = port->port_conf;
480
481 if (port_conf->ops->md_state_notify)
482 port_conf->ops->md_state_notify(port, state);
483 }
484 }
485
t7xx_proxy_init_all_ports(struct t7xx_modem * md)486 static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
487 {
488 struct port_proxy *port_prox = md->port_prox;
489 struct t7xx_port *port;
490 int i;
491
492 for_each_proxy_port(i, port, port_prox) {
493 const struct t7xx_port_conf *port_conf = port->port_conf;
494
495 t7xx_port_struct_init(port);
496
497 if (port_conf->tx_ch == PORT_CH_CONTROL_TX)
498 md->core_md.ctl_port = port;
499
500 if (port_conf->tx_ch == PORT_CH_AP_CONTROL_TX)
501 md->core_ap.ctl_port = port;
502
503 port->t7xx_dev = md->t7xx_dev;
504 port->dev = &md->t7xx_dev->pdev->dev;
505 spin_lock_init(&port->port_update_lock);
506 port->chan_enable = false;
507
508 if (port_conf->ops && port_conf->ops->init)
509 port_conf->ops->init(port);
510 }
511
512 t7xx_proxy_setup_ch_mapping(port_prox);
513 }
514
t7xx_port_proxy_set_cfg(struct t7xx_modem * md,enum port_cfg_id cfg_id)515 void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id)
516 {
517 struct port_proxy *port_prox = md->port_prox;
518 const struct t7xx_port_conf *port_conf;
519 u32 port_count;
520 int i;
521
522 t7xx_port_proxy_uninit(port_prox);
523
524 if (cfg_id == PORT_CFG_ID_EARLY) {
525 port_conf = t7xx_early_port_conf;
526 port_count = ARRAY_SIZE(t7xx_early_port_conf);
527 } else {
528 port_conf = t7xx_port_conf;
529 port_count = ARRAY_SIZE(t7xx_port_conf);
530 }
531
532 for (i = 0; i < port_count; i++)
533 port_prox->ports[i].port_conf = &port_conf[i];
534
535 port_prox->cfg_id = cfg_id;
536 port_prox->port_count = port_count;
537
538 t7xx_proxy_init_all_ports(md);
539 }
540
t7xx_proxy_alloc(struct t7xx_modem * md)541 static int t7xx_proxy_alloc(struct t7xx_modem *md)
542 {
543 struct device *dev = &md->t7xx_dev->pdev->dev;
544 struct port_proxy *port_prox;
545
546 port_prox = devm_kzalloc(dev,
547 struct_size(port_prox,
548 ports,
549 T7XX_MAX_POSSIBLE_PORTS_NUM),
550 GFP_KERNEL);
551 if (!port_prox)
552 return -ENOMEM;
553
554 md->port_prox = port_prox;
555 port_prox->dev = dev;
556
557 return 0;
558 }
559
560 /**
561 * t7xx_port_proxy_init() - Initialize ports.
562 * @md: Modem.
563 *
564 * Create all port instances.
565 *
566 * Return:
567 * * 0 - Success.
568 * * -ERROR - Error code from failure sub-initializations.
569 */
t7xx_port_proxy_init(struct t7xx_modem * md)570 int t7xx_port_proxy_init(struct t7xx_modem *md)
571 {
572 int ret;
573
574 ret = t7xx_proxy_alloc(md);
575 if (ret)
576 return ret;
577
578 return 0;
579 }
580
t7xx_port_proxy_uninit(struct port_proxy * port_prox)581 void t7xx_port_proxy_uninit(struct port_proxy *port_prox)
582 {
583 struct t7xx_port *port;
584 int i;
585
586 for_each_proxy_port(i, port, port_prox) {
587 const struct t7xx_port_conf *port_conf = port->port_conf;
588
589 if (port_conf->ops && port_conf->ops->uninit)
590 port_conf->ops->uninit(port);
591 }
592 }
593
t7xx_port_proxy_chl_enable_disable(struct port_proxy * port_prox,unsigned int ch_id,bool en_flag)594 int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned int ch_id,
595 bool en_flag)
596 {
597 struct t7xx_port *port = t7xx_proxy_get_port_by_ch(port_prox, ch_id);
598 const struct t7xx_port_conf *port_conf;
599
600 if (!port)
601 return -EINVAL;
602
603 port_conf = port->port_conf;
604
605 if (en_flag) {
606 if (port_conf->ops->enable_chl)
607 port_conf->ops->enable_chl(port);
608 } else {
609 if (port_conf->ops->disable_chl)
610 port_conf->ops->disable_chl(port);
611 }
612
613 return 0;
614 }
615