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 <amir.hanania@intel.com> 8 * Chandrashekar Devegowda <chandrashekar.devegowda@intel.com> 9 * Haijun Liu <haijun.liu@mediatek.com> 10 * Moises Veleta <moises.veleta@intel.com> 11 * Ricardo Martinez <ricardo.martinez@linux.intel.com> 12 * 13 * Contributors: 14 * Andy Shevchenko <andriy.shevchenko@linux.intel.com> 15 * Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com> 16 * Eliot Lee <eliot.lee@intel.com> 17 * Sreehari Kancharla <sreehari.kancharla@intel.com> 18 */ 19 20 #include <linux/atomic.h> 21 #include <linux/bitfield.h> 22 #include <linux/dev_printk.h> 23 #include <linux/err.h> 24 #include <linux/gfp.h> 25 #include <linux/minmax.h> 26 #include <linux/netdevice.h> 27 #include <linux/skbuff.h> 28 #include <linux/spinlock.h> 29 #include <linux/string.h> 30 #include <linux/wwan.h> 31 32 #include "t7xx_port.h" 33 #include "t7xx_port_proxy.h" 34 #include "t7xx_state_monitor.h" 35 36 static int t7xx_port_ctrl_start(struct wwan_port *port) 37 { 38 struct t7xx_port *port_mtk = wwan_port_get_drvdata(port); 39 40 if (atomic_read(&port_mtk->usage_cnt)) 41 return -EBUSY; 42 43 atomic_inc(&port_mtk->usage_cnt); 44 return 0; 45 } 46 47 static void t7xx_port_ctrl_stop(struct wwan_port *port) 48 { 49 struct t7xx_port *port_mtk = wwan_port_get_drvdata(port); 50 51 atomic_dec(&port_mtk->usage_cnt); 52 } 53 54 static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb) 55 { 56 struct t7xx_port *port_private = wwan_port_get_drvdata(port); 57 const struct t7xx_port_conf *port_conf; 58 struct sk_buff *cur = skb, *cloned; 59 struct t7xx_fsm_ctl *ctl; 60 enum md_state md_state; 61 int cnt = 0, ret; 62 63 if (!port_private->chan_enable) 64 return -EINVAL; 65 66 port_conf = port_private->port_conf; 67 ctl = port_private->t7xx_dev->md->fsm_ctl; 68 md_state = t7xx_fsm_get_md_state(ctl); 69 if (md_state == MD_STATE_WAITING_FOR_HS1 || md_state == MD_STATE_WAITING_FOR_HS2) { 70 dev_warn(port_private->dev, "Cannot write to %s port when md_state=%d\n", 71 port_conf->name, md_state); 72 return -ENODEV; 73 } 74 75 while (cur) { 76 cloned = skb_clone(cur, GFP_KERNEL); 77 cloned->len = skb_headlen(cur); 78 ret = t7xx_port_send_skb(port_private, cloned, 0, 0); 79 if (ret) { 80 dev_kfree_skb(cloned); 81 dev_err(port_private->dev, "Write error on %s port, %d\n", 82 port_conf->name, ret); 83 return cnt ? cnt + ret : ret; 84 } 85 cnt += cur->len; 86 if (cur == skb) 87 cur = skb_shinfo(skb)->frag_list; 88 else 89 cur = cur->next; 90 } 91 92 dev_kfree_skb(skb); 93 return 0; 94 } 95 96 static const struct wwan_port_ops wwan_ops = { 97 .start = t7xx_port_ctrl_start, 98 .stop = t7xx_port_ctrl_stop, 99 .tx = t7xx_port_ctrl_tx, 100 }; 101 102 static int t7xx_port_wwan_init(struct t7xx_port *port) 103 { 104 port->rx_length_th = RX_QUEUE_MAXLEN; 105 return 0; 106 } 107 108 static void t7xx_port_wwan_uninit(struct t7xx_port *port) 109 { 110 if (!port->wwan.wwan_port) 111 return; 112 113 port->rx_length_th = 0; 114 wwan_remove_port(port->wwan.wwan_port); 115 port->wwan.wwan_port = NULL; 116 } 117 118 static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb) 119 { 120 if (!atomic_read(&port->usage_cnt) || !port->chan_enable) { 121 const struct t7xx_port_conf *port_conf = port->port_conf; 122 123 dev_kfree_skb_any(skb); 124 dev_err_ratelimited(port->dev, "Port %s is not opened, drop packets\n", 125 port_conf->name); 126 /* Dropping skb, caller should not access skb.*/ 127 return 0; 128 } 129 130 wwan_port_rx(port->wwan.wwan_port, skb); 131 return 0; 132 } 133 134 static int t7xx_port_wwan_enable_chl(struct t7xx_port *port) 135 { 136 spin_lock(&port->port_update_lock); 137 port->chan_enable = true; 138 spin_unlock(&port->port_update_lock); 139 140 return 0; 141 } 142 143 static int t7xx_port_wwan_disable_chl(struct t7xx_port *port) 144 { 145 spin_lock(&port->port_update_lock); 146 port->chan_enable = false; 147 spin_unlock(&port->port_update_lock); 148 149 return 0; 150 } 151 152 static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int state) 153 { 154 const struct t7xx_port_conf *port_conf = port->port_conf; 155 unsigned int header_len = sizeof(struct ccci_header); 156 struct wwan_port_caps caps; 157 158 if (state != MD_STATE_READY) 159 return; 160 161 if (!port->wwan.wwan_port) { 162 caps.frag_len = CLDMA_MTU - header_len; 163 caps.headroom_len = header_len; 164 port->wwan.wwan_port = wwan_create_port(port->dev, port_conf->port_type, 165 &wwan_ops, &caps, port); 166 if (IS_ERR(port->wwan.wwan_port)) 167 dev_err(port->dev, "Unable to create WWWAN port %s", port_conf->name); 168 } 169 } 170 171 struct port_ops wwan_sub_port_ops = { 172 .init = t7xx_port_wwan_init, 173 .recv_skb = t7xx_port_wwan_recv_skb, 174 .uninit = t7xx_port_wwan_uninit, 175 .enable_chl = t7xx_port_wwan_enable_chl, 176 .disable_chl = t7xx_port_wwan_disable_chl, 177 .md_state_notify = t7xx_port_wwan_md_state_notify, 178 }; 179