Implements wwan port for MBIM & AT protocol communication Signed-off-by: M Chetan Kumar <m.chetan.kumar@xxxxxxxxx> --- v3: * Renamed file to iosm_ipc_port.c * WWAN PORT adaptation for AT & MBIM protocol communication. v2: * Renamed iosm_sio struct to iosm_cdev. * Added memory barriers around atomic operations. --- drivers/net/wwan/iosm/iosm_ipc_port.c | 85 +++++++++++++++++++++++++++ drivers/net/wwan/iosm/iosm_ipc_port.h | 50 ++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 drivers/net/wwan/iosm/iosm_ipc_port.c create mode 100644 drivers/net/wwan/iosm/iosm_ipc_port.h diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.c b/drivers/net/wwan/iosm/iosm_ipc_port.c new file mode 100644 index 000000000000..beb944847398 --- /dev/null +++ b/drivers/net/wwan/iosm/iosm_ipc_port.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020-21 Intel Corporation. + */ + +#include "iosm_ipc_chnl_cfg.h" +#include "iosm_ipc_imem_ops.h" +#include "iosm_ipc_port.h" + +/* open logical channel for control communication */ +static int ipc_port_ctrl_start(struct wwan_port *port) +{ + struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + int ret = 0; + + ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem, + ipc_port->chl_id, + IPC_HP_CDEV_OPEN); + if (!ipc_port->channel) + ret = -EIO; + + return ret; +} + +/* close logical channel */ +static void ipc_port_ctrl_stop(struct wwan_port *port) +{ + struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + + ipc_imem_sys_cdev_close(ipc_port); +} + +/* transfer control data to modem */ +static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb) +{ + struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + + return ipc_imem_sys_cdev_write(ipc_port, skb); +} + +static const struct wwan_port_ops ipc_wwan_ctrl_ops = { + .start = ipc_port_ctrl_start, + .stop = ipc_port_ctrl_stop, + .tx = ipc_port_ctrl_tx, +}; + +/* Port init func */ +struct iosm_cdev *ipc_port_init(struct iosm_imem *ipc_imem, + struct ipc_chnl_cfg ipc_port_cfg) +{ + struct iosm_cdev *ipc_port = kzalloc(sizeof(*ipc_port), GFP_KERNEL); + enum wwan_port_type port_type = ipc_port_cfg.wwan_port_type; + enum ipc_channel_id chl_id = ipc_port_cfg.id; + + if (!ipc_port) + return NULL; + + ipc_port->dev = ipc_imem->dev; + ipc_port->pcie = ipc_imem->pcie; + + ipc_port->port_type = port_type; + ipc_port->chl_id = chl_id; + ipc_port->ipc_imem = ipc_imem; + + ipc_port->iosm_port = wwan_create_port(ipc_port->dev, port_type, + &ipc_wwan_ctrl_ops, ipc_port); + + return ipc_port; +} + +/* Port deinit func */ +void ipc_port_deinit(struct iosm_cdev *port[]) +{ + struct iosm_cdev *ipc_port; + u8 ctrl_chl_nr; + + for (ctrl_chl_nr = 0; ctrl_chl_nr < IPC_MEM_MAX_CHANNELS; + ctrl_chl_nr++) { + if (port[ctrl_chl_nr]) { + ipc_port = port[ctrl_chl_nr]; + wwan_remove_port(ipc_port->iosm_port); + kfree(ipc_port); + } + } +} diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.h b/drivers/net/wwan/iosm/iosm_ipc_port.h new file mode 100644 index 000000000000..11bc8ed21616 --- /dev/null +++ b/drivers/net/wwan/iosm/iosm_ipc_port.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2020-21 Intel Corporation. + */ + +#ifndef IOSM_IPC_PORT_H +#define IOSM_IPC_PORT_H + +#include <linux/wwan.h> + +#include "iosm_ipc_imem_ops.h" + +/** + * struct iosm_cdev - State of the char driver layer. + * @iosm_port: Pointer of type wwan_port + * @ipc_imem: imem instance + * @dev: Pointer to device struct + * @pcie: PCIe component + * @port_type: WWAN port type + * @channel: Channel instance + * @chl_id: Channel Indentifier + */ +struct iosm_cdev { + struct wwan_port *iosm_port; + struct iosm_imem *ipc_imem; + struct device *dev; + struct iosm_pcie *pcie; + enum wwan_port_type port_type; + struct ipc_mem_channel *channel; + enum ipc_channel_id chl_id; +}; + +/** + * ipc_port_init - Allocate IPC port & register to wwan subsystem for AT/MBIM + * communication. + * @ipc_imem: Pointer to iosm_imem structure + * @ipc_port_cfg: IPC Port Config + * + * Returns: 0 on success & NULL on failure + */ +struct iosm_cdev *ipc_port_init(struct iosm_imem *ipc_imem, + struct ipc_chnl_cfg ipc_port_cfg); + +/** + * ipc_port_deinit - Free IPC port & unregister port with wwan subsystem. + * @ipc_port: Array of pointer to the ipc port data-struct + */ +void ipc_port_deinit(struct iosm_cdev *ipc_port[]); + +#endif -- 2.25.1