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 } 86