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 	size_t len, offset, chunk_len = 0, txq_mtu;
58 	const struct t7xx_port_conf *port_conf;
59 	struct t7xx_fsm_ctl *ctl;
60 	enum md_state md_state;
61 
62 	len = skb->len;
63 	if (!len || !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 	txq_mtu = t7xx_get_port_mtu(port_private);
76 	for (offset = 0; offset < len; offset += chunk_len) {
77 		struct sk_buff *skb_ccci;
78 		int ret;
79 
80 		chunk_len = min(len - offset, txq_mtu - sizeof(struct ccci_header));
81 		skb_ccci = t7xx_port_alloc_skb(chunk_len);
82 		if (!skb_ccci)
83 			return -ENOMEM;
84 
85 		skb_put_data(skb_ccci, skb->data + offset, chunk_len);
86 		ret = t7xx_port_send_skb(port_private, skb_ccci, 0, 0);
87 		if (ret) {
88 			dev_kfree_skb_any(skb_ccci);
89 			dev_err(port_private->dev, "Write error on %s port, %d\n",
90 				port_conf->name, ret);
91 			return ret;
92 		}
93 	}
94 
95 	dev_kfree_skb(skb);
96 	return 0;
97 }
98 
99 static const struct wwan_port_ops wwan_ops = {
100 	.start = t7xx_port_ctrl_start,
101 	.stop = t7xx_port_ctrl_stop,
102 	.tx = t7xx_port_ctrl_tx,
103 };
104 
105 static int t7xx_port_wwan_init(struct t7xx_port *port)
106 {
107 	port->rx_length_th = RX_QUEUE_MAXLEN;
108 	return 0;
109 }
110 
111 static void t7xx_port_wwan_uninit(struct t7xx_port *port)
112 {
113 	if (!port->wwan_port)
114 		return;
115 
116 	port->rx_length_th = 0;
117 	wwan_remove_port(port->wwan_port);
118 	port->wwan_port = NULL;
119 }
120 
121 static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb)
122 {
123 	if (!atomic_read(&port->usage_cnt) || !port->chan_enable) {
124 		const struct t7xx_port_conf *port_conf = port->port_conf;
125 
126 		dev_kfree_skb_any(skb);
127 		dev_err_ratelimited(port->dev, "Port %s is not opened, drop packets\n",
128 				    port_conf->name);
129 		/* Dropping skb, caller should not access skb.*/
130 		return 0;
131 	}
132 
133 	wwan_port_rx(port->wwan_port, skb);
134 	return 0;
135 }
136 
137 static int t7xx_port_wwan_enable_chl(struct t7xx_port *port)
138 {
139 	spin_lock(&port->port_update_lock);
140 	port->chan_enable = true;
141 	spin_unlock(&port->port_update_lock);
142 
143 	return 0;
144 }
145 
146 static int t7xx_port_wwan_disable_chl(struct t7xx_port *port)
147 {
148 	spin_lock(&port->port_update_lock);
149 	port->chan_enable = false;
150 	spin_unlock(&port->port_update_lock);
151 
152 	return 0;
153 }
154 
155 static void t7xx_port_wwan_md_state_notify(struct t7xx_port *port, unsigned int state)
156 {
157 	const struct t7xx_port_conf *port_conf = port->port_conf;
158 
159 	if (state != MD_STATE_READY)
160 		return;
161 
162 	if (!port->wwan_port) {
163 		port->wwan_port = wwan_create_port(port->dev, port_conf->port_type,
164 						   &wwan_ops, port);
165 		if (IS_ERR(port->wwan_port))
166 			dev_err(port->dev, "Unable to create WWWAN port %s", port_conf->name);
167 	}
168 }
169 
170 struct port_ops wwan_sub_port_ops = {
171 	.init = t7xx_port_wwan_init,
172 	.recv_skb = t7xx_port_wwan_recv_skb,
173 	.uninit = t7xx_port_wwan_uninit,
174 	.enable_chl = t7xx_port_wwan_enable_chl,
175 	.disable_chl = t7xx_port_wwan_disable_chl,
176 	.md_state_notify = t7xx_port_wwan_md_state_notify,
177 };
178