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