Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2021, MediaTek Inc.
0004  * Copyright (c) 2021-2022, Intel Corporation.
0005  *
0006  * Authors:
0007  *  Amir Hanania <amir.hanania@intel.com>
0008  *  Chandrashekar Devegowda <chandrashekar.devegowda@intel.com>
0009  *  Haijun Liu <haijun.liu@mediatek.com>
0010  *  Moises Veleta <moises.veleta@intel.com>
0011  *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
0012  *
0013  * Contributors:
0014  *  Andy Shevchenko <andriy.shevchenko@linux.intel.com>
0015  *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
0016  *  Eliot Lee <eliot.lee@intel.com>
0017  *  Sreehari Kancharla <sreehari.kancharla@intel.com>
0018  */
0019 
0020 #include <linux/atomic.h>
0021 #include <linux/bitfield.h>
0022 #include <linux/dev_printk.h>
0023 #include <linux/err.h>
0024 #include <linux/gfp.h>
0025 #include <linux/minmax.h>
0026 #include <linux/netdevice.h>
0027 #include <linux/skbuff.h>
0028 #include <linux/spinlock.h>
0029 #include <linux/string.h>
0030 #include <linux/wwan.h>
0031 
0032 #include "t7xx_port.h"
0033 #include "t7xx_port_proxy.h"
0034 #include "t7xx_state_monitor.h"
0035 
0036 static int t7xx_port_ctrl_start(struct wwan_port *port)
0037 {
0038     struct t7xx_port *port_mtk = wwan_port_get_drvdata(port);
0039 
0040     if (atomic_read(&port_mtk->usage_cnt))
0041         return -EBUSY;
0042 
0043     atomic_inc(&port_mtk->usage_cnt);
0044     return 0;
0045 }
0046 
0047 static void t7xx_port_ctrl_stop(struct wwan_port *port)
0048 {
0049     struct t7xx_port *port_mtk = wwan_port_get_drvdata(port);
0050 
0051     atomic_dec(&port_mtk->usage_cnt);
0052 }
0053 
0054 static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
0055 {
0056     struct t7xx_port *port_private = wwan_port_get_drvdata(port);
0057     size_t len, offset, chunk_len = 0, txq_mtu = CLDMA_MTU;
0058     const struct t7xx_port_conf *port_conf;
0059     struct t7xx_fsm_ctl *ctl;
0060     enum md_state md_state;
0061 
0062     len = skb->len;
0063     if (!len || !port_private->chan_enable)
0064         return -EINVAL;
0065 
0066     port_conf = port_private->port_conf;
0067     ctl = port_private->t7xx_dev->md->fsm_ctl;
0068     md_state = t7xx_fsm_get_md_state(ctl);
0069     if (md_state == MD_STATE_WAITING_FOR_HS1 || md_state == MD_STATE_WAITING_FOR_HS2) {
0070         dev_warn(port_private->dev, "Cannot write to %s port when md_state=%d\n",
0071              port_conf->name, md_state);
0072         return -ENODEV;
0073     }
0074 
0075     for (offset = 0; offset < len; offset += chunk_len) {
0076         struct sk_buff *skb_ccci;
0077         int ret;
0078 
0079         chunk_len = min(len - offset, txq_mtu - sizeof(struct ccci_header));
0080         skb_ccci = t7xx_port_alloc_skb(chunk_len);
0081         if (!skb_ccci)
0082             return -ENOMEM;
0083 
0084         skb_put_data(skb_ccci, skb->data + offset, chunk_len);
0085         ret = t7xx_port_send_skb(port_private, skb_ccci, 0, 0);
0086         if (ret) {
0087             dev_kfree_skb_any(skb_ccci);
0088             dev_err(port_private->dev, "Write error on %s port, %d\n",
0089                 port_conf->name, ret);
0090             return ret;
0091         }
0092     }
0093 
0094     dev_kfree_skb(skb);
0095     return 0;
0096 }
0097 
0098 static const struct wwan_port_ops wwan_ops = {
0099     .start = t7xx_port_ctrl_start,
0100     .stop = t7xx_port_ctrl_stop,
0101     .tx = t7xx_port_ctrl_tx,
0102 };
0103 
0104 static int t7xx_port_wwan_init(struct t7xx_port *port)
0105 {
0106     port->rx_length_th = RX_QUEUE_MAXLEN;
0107     return 0;
0108 }
0109 
0110 static void t7xx_port_wwan_uninit(struct t7xx_port *port)
0111 {
0112     if (!port->wwan_port)
0113         return;
0114 
0115     port->rx_length_th = 0;
0116     wwan_remove_port(port->wwan_port);
0117     port->wwan_port = NULL;
0118 }
0119 
0120 static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb)
0121 {
0122     if (!atomic_read(&port->usage_cnt) || !port->chan_enable) {
0123         const struct t7xx_port_conf *port_conf = port->port_conf;
0124 
0125         dev_kfree_skb_any(skb);
0126         dev_err_ratelimited(port->dev, "Port %s is not opened, drop packets\n",
0127                     port_conf->name);
0128         /* Dropping skb, caller should not access skb.*/
0129         return 0;
0130     }
0131 
0132     wwan_port_rx(port->wwan_port, skb);
0133     return 0;
0134 }
0135 
0136 static int t7xx_port_wwan_enable_chl(struct t7xx_port *port)
0137 {
0138     spin_lock(&port->port_update_lock);
0139     port->chan_enable = true;
0140     spin_unlock(&port->port_update_lock);
0141 
0142     return 0;
0143 }
0144 
0145 static int t7xx_port_wwan_disable_chl(struct t7xx_port *port)
0146 {
0147     spin_lock(&port->port_update_lock);
0148     port->chan_enable = false;
0149     spin_unlock(&port->port_update_lock);
0150 
0151     return 0;
0152 }
0153 
0154 static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int state)
0155 {
0156     const struct t7xx_port_conf *port_conf = port->port_conf;
0157 
0158     if (state != MD_STATE_READY)
0159         return;
0160 
0161     if (!port->wwan_port) {
0162         port->wwan_port = wwan_create_port(port->dev, port_conf->port_type,
0163                            &wwan_ops, port);
0164         if (IS_ERR(port->wwan_port))
0165             dev_err(port->dev, "Unable to create WWWAN port %s", port_conf->name);
0166     }
0167 }
0168 
0169 struct port_ops wwan_sub_port_ops = {
0170     .init = t7xx_port_wwan_init,
0171     .recv_skb = t7xx_port_wwan_recv_skb,
0172     .uninit = t7xx_port_wwan_uninit,
0173     .enable_chl = t7xx_port_wwan_enable_chl,
0174     .disable_chl = t7xx_port_wwan_disable_chl,
0175     .md_state_notify = t7xx_port_wwan_md_state_notify,
0176 };