Merge tag 'io_uring-5.14-2021-07-24' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / net / wwan / iosm / iosm_ipc_port.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2020-21 Intel Corporation.
4  */
5
6 #include "iosm_ipc_chnl_cfg.h"
7 #include "iosm_ipc_imem_ops.h"
8 #include "iosm_ipc_port.h"
9
10 /* open logical channel for control communication */
11 static int ipc_port_ctrl_start(struct wwan_port *port)
12 {
13         struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
14         int ret = 0;
15
16         ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem,
17                                                    ipc_port->chl_id,
18                                                    IPC_HP_CDEV_OPEN);
19         if (!ipc_port->channel)
20                 ret = -EIO;
21
22         return ret;
23 }
24
25 /* close logical channel */
26 static void ipc_port_ctrl_stop(struct wwan_port *port)
27 {
28         struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
29
30         ipc_imem_sys_cdev_close(ipc_port);
31 }
32
33 /* transfer control data to modem */
34 static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
35 {
36         struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
37
38         return ipc_imem_sys_cdev_write(ipc_port, skb);
39 }
40
41 static const struct wwan_port_ops ipc_wwan_ctrl_ops = {
42         .start = ipc_port_ctrl_start,
43         .stop = ipc_port_ctrl_stop,
44         .tx = ipc_port_ctrl_tx,
45 };
46
47 /* Port init func */
48 struct iosm_cdev *ipc_port_init(struct iosm_imem *ipc_imem,
49                                 struct ipc_chnl_cfg ipc_port_cfg)
50 {
51         struct iosm_cdev *ipc_port = kzalloc(sizeof(*ipc_port), GFP_KERNEL);
52         enum wwan_port_type port_type = ipc_port_cfg.wwan_port_type;
53         enum ipc_channel_id chl_id = ipc_port_cfg.id;
54
55         if (!ipc_port)
56                 return NULL;
57
58         ipc_port->dev = ipc_imem->dev;
59         ipc_port->pcie = ipc_imem->pcie;
60
61         ipc_port->port_type = port_type;
62         ipc_port->chl_id = chl_id;
63         ipc_port->ipc_imem = ipc_imem;
64
65         ipc_port->iosm_port = wwan_create_port(ipc_port->dev, port_type,
66                                                &ipc_wwan_ctrl_ops, ipc_port);
67
68         return ipc_port;
69 }
70
71 /* Port deinit func */
72 void ipc_port_deinit(struct iosm_cdev *port[])
73 {
74         struct iosm_cdev *ipc_port;
75         u8 ctrl_chl_nr;
76
77         for (ctrl_chl_nr = 0; ctrl_chl_nr < IPC_MEM_MAX_CHANNELS;
78              ctrl_chl_nr++) {
79                 if (port[ctrl_chl_nr]) {
80                         ipc_port = port[ctrl_chl_nr];
81                         wwan_remove_port(ipc_port->iosm_port);
82                         kfree(ipc_port);
83                 }
84         }
85 }