xref: /openbmc/linux/drivers/net/wwan/t7xx/t7xx_port_proxy.c (revision d20ef656f9942950d67e29418512a6929682ad60)
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  *  Haijun Liu <haijun.liu@mediatek.com>
9  *  Moises Veleta <moises.veleta@intel.com>
10  *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
11  *
12  * Contributors:
13  *  Andy Shevchenko <andriy.shevchenko@linux.intel.com>
14  *  Chandrashekar Devegowda <chandrashekar.devegowda@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/bits.h>
21 #include <linux/bitfield.h>
22 #include <linux/device.h>
23 #include <linux/gfp.h>
24 #include <linux/kernel.h>
25 #include <linux/kthread.h>
26 #include <linux/list.h>
27 #include <linux/mutex.h>
28 #include <linux/netdevice.h>
29 #include <linux/skbuff.h>
30 #include <linux/spinlock.h>
31 #include <linux/wait.h>
32 #include <linux/wwan.h>
33 
34 #include "t7xx_hif_cldma.h"
35 #include "t7xx_modem_ops.h"
36 #include "t7xx_port.h"
37 #include "t7xx_port_proxy.h"
38 #include "t7xx_state_monitor.h"
39 
40 #define Q_IDX_CTRL			0
41 #define Q_IDX_MBIM			2
42 #define Q_IDX_AT_CMD			5
43 
44 #define INVALID_SEQ_NUM			GENMASK(15, 0)
45 
46 #define for_each_proxy_port(i, p, proxy)	\
47 	for (i = 0, (p) = &(proxy)->ports[i];	\
48 	     i < (proxy)->port_count;		\
49 	     i++, (p) = &(proxy)->ports[i])
50 
51 static const struct t7xx_port_conf t7xx_md_port_conf[] = {
52 	{
53 		.tx_ch = PORT_CH_UART2_TX,
54 		.rx_ch = PORT_CH_UART2_RX,
55 		.txq_index = Q_IDX_AT_CMD,
56 		.rxq_index = Q_IDX_AT_CMD,
57 		.txq_exp_index = 0xff,
58 		.rxq_exp_index = 0xff,
59 		.path_id = CLDMA_ID_MD,
60 		.ops = &wwan_sub_port_ops,
61 		.name = "AT",
62 		.port_type = WWAN_PORT_AT,
63 	}, {
64 		.tx_ch = PORT_CH_MBIM_TX,
65 		.rx_ch = PORT_CH_MBIM_RX,
66 		.txq_index = Q_IDX_MBIM,
67 		.rxq_index = Q_IDX_MBIM,
68 		.path_id = CLDMA_ID_MD,
69 		.ops = &wwan_sub_port_ops,
70 		.name = "MBIM",
71 		.port_type = WWAN_PORT_MBIM,
72 	}, {
73 		.tx_ch = PORT_CH_CONTROL_TX,
74 		.rx_ch = PORT_CH_CONTROL_RX,
75 		.txq_index = Q_IDX_CTRL,
76 		.rxq_index = Q_IDX_CTRL,
77 		.path_id = CLDMA_ID_MD,
78 		.ops = &ctl_port_ops,
79 		.name = "t7xx_ctrl",
80 	}, {
81 		.tx_ch = PORT_CH_AP_CONTROL_TX,
82 		.rx_ch = PORT_CH_AP_CONTROL_RX,
83 		.txq_index = Q_IDX_CTRL,
84 		.rxq_index = Q_IDX_CTRL,
85 		.path_id = CLDMA_ID_AP,
86 		.ops = &ctl_port_ops,
87 		.name = "t7xx_ap_ctrl",
88 	},
89 };
90 
91 static struct t7xx_port *t7xx_proxy_get_port_by_ch(struct port_proxy *port_prox, enum port_ch ch)
92 {
93 	const struct t7xx_port_conf *port_conf;
94 	struct t7xx_port *port;
95 	int i;
96 
97 	for_each_proxy_port(i, port, port_prox) {
98 		port_conf = port->port_conf;
99 		if (port_conf->rx_ch == ch || port_conf->tx_ch == ch)
100 			return port;
101 	}
102 
103 	return NULL;
104 }
105 
106 static u16 t7xx_port_next_rx_seq_num(struct t7xx_port *port, struct ccci_header *ccci_h)
107 {
108 	u32 status = le32_to_cpu(ccci_h->status);
109 	u16 seq_num, next_seq_num;
110 	bool assert_bit;
111 
112 	seq_num = FIELD_GET(CCCI_H_SEQ_FLD, status);
113 	next_seq_num = (seq_num + 1) & FIELD_MAX(CCCI_H_SEQ_FLD);
114 	assert_bit = status & CCCI_H_AST_BIT;
115 	if (!assert_bit || port->seq_nums[MTK_RX] == INVALID_SEQ_NUM)
116 		return next_seq_num;
117 
118 	if (seq_num != port->seq_nums[MTK_RX])
119 		dev_warn_ratelimited(port->dev,
120 				     "seq num out-of-order %u != %u (header %X, len %X)\n",
121 				     seq_num, port->seq_nums[MTK_RX],
122 				     le32_to_cpu(ccci_h->packet_header),
123 				     le32_to_cpu(ccci_h->packet_len));
124 
125 	return next_seq_num;
126 }
127 
128 void t7xx_port_proxy_reset(struct port_proxy *port_prox)
129 {
130 	struct t7xx_port *port;
131 	int i;
132 
133 	for_each_proxy_port(i, port, port_prox) {
134 		port->seq_nums[MTK_RX] = INVALID_SEQ_NUM;
135 		port->seq_nums[MTK_TX] = 0;
136 	}
137 }
138 
139 static int t7xx_port_get_queue_no(struct t7xx_port *port)
140 {
141 	const struct t7xx_port_conf *port_conf = port->port_conf;
142 	struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
143 
144 	return t7xx_fsm_get_md_state(ctl) == MD_STATE_EXCEPTION ?
145 		port_conf->txq_exp_index : port_conf->txq_index;
146 }
147 
148 static void t7xx_port_struct_init(struct t7xx_port *port)
149 {
150 	INIT_LIST_HEAD(&port->entry);
151 	INIT_LIST_HEAD(&port->queue_entry);
152 	skb_queue_head_init(&port->rx_skb_list);
153 	init_waitqueue_head(&port->rx_wq);
154 	port->seq_nums[MTK_RX] = INVALID_SEQ_NUM;
155 	port->seq_nums[MTK_TX] = 0;
156 	atomic_set(&port->usage_cnt, 0);
157 }
158 
159 struct sk_buff *t7xx_port_alloc_skb(int payload)
160 {
161 	struct sk_buff *skb = __dev_alloc_skb(payload + sizeof(struct ccci_header), GFP_KERNEL);
162 
163 	if (skb)
164 		skb_reserve(skb, sizeof(struct ccci_header));
165 
166 	return skb;
167 }
168 
169 struct sk_buff *t7xx_ctrl_alloc_skb(int payload)
170 {
171 	struct sk_buff *skb = t7xx_port_alloc_skb(payload + sizeof(struct ctrl_msg_header));
172 
173 	if (skb)
174 		skb_reserve(skb, sizeof(struct ctrl_msg_header));
175 
176 	return skb;
177 }
178 
179 /**
180  * t7xx_port_enqueue_skb() - Enqueue the received skb into the port's rx_skb_list.
181  * @port: port context.
182  * @skb: received skb.
183  *
184  * Return:
185  * * 0		- Success.
186  * * -ENOBUFS	- Not enough buffer space. Caller will try again later, skb is not consumed.
187  */
188 int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb)
189 {
190 	unsigned long flags;
191 
192 	spin_lock_irqsave(&port->rx_wq.lock, flags);
193 	if (port->rx_skb_list.qlen >= port->rx_length_th) {
194 		spin_unlock_irqrestore(&port->rx_wq.lock, flags);
195 
196 		return -ENOBUFS;
197 	}
198 	__skb_queue_tail(&port->rx_skb_list, skb);
199 	spin_unlock_irqrestore(&port->rx_wq.lock, flags);
200 
201 	wake_up_all(&port->rx_wq);
202 	return 0;
203 }
204 
205 static int t7xx_port_send_raw_skb(struct t7xx_port *port, struct sk_buff *skb)
206 {
207 	enum cldma_id path_id = port->port_conf->path_id;
208 	struct cldma_ctrl *md_ctrl;
209 	int ret, tx_qno;
210 
211 	md_ctrl = port->t7xx_dev->md->md_ctrl[path_id];
212 	tx_qno = t7xx_port_get_queue_no(port);
213 	ret = t7xx_cldma_send_skb(md_ctrl, tx_qno, skb);
214 	if (ret)
215 		dev_err(port->dev, "Failed to send skb: %d\n", ret);
216 
217 	return ret;
218 }
219 
220 static int t7xx_port_send_ccci_skb(struct t7xx_port *port, struct sk_buff *skb,
221 				   unsigned int pkt_header, unsigned int ex_msg)
222 {
223 	const struct t7xx_port_conf *port_conf = port->port_conf;
224 	struct ccci_header *ccci_h;
225 	u32 status;
226 	int ret;
227 
228 	ccci_h = skb_push(skb, sizeof(*ccci_h));
229 	status = FIELD_PREP(CCCI_H_CHN_FLD, port_conf->tx_ch) |
230 		 FIELD_PREP(CCCI_H_SEQ_FLD, port->seq_nums[MTK_TX]) | CCCI_H_AST_BIT;
231 	ccci_h->status = cpu_to_le32(status);
232 	ccci_h->packet_header = cpu_to_le32(pkt_header);
233 	ccci_h->packet_len = cpu_to_le32(skb->len);
234 	ccci_h->ex_msg = cpu_to_le32(ex_msg);
235 
236 	ret = t7xx_port_send_raw_skb(port, skb);
237 	if (ret)
238 		return ret;
239 
240 	port->seq_nums[MTK_TX]++;
241 	return 0;
242 }
243 
244 int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg,
245 			   unsigned int ex_msg)
246 {
247 	struct ctrl_msg_header *ctrl_msg_h;
248 	unsigned int msg_len = skb->len;
249 	u32 pkt_header = 0;
250 
251 	ctrl_msg_h = skb_push(skb, sizeof(*ctrl_msg_h));
252 	ctrl_msg_h->ctrl_msg_id = cpu_to_le32(msg);
253 	ctrl_msg_h->ex_msg = cpu_to_le32(ex_msg);
254 	ctrl_msg_h->data_length = cpu_to_le32(msg_len);
255 
256 	if (!msg_len)
257 		pkt_header = CCCI_HEADER_NO_DATA;
258 
259 	return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg);
260 }
261 
262 int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int pkt_header,
263 		       unsigned int ex_msg)
264 {
265 	struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
266 	unsigned int fsm_state;
267 
268 	fsm_state = t7xx_fsm_get_ctl_state(ctl);
269 	if (fsm_state != FSM_STATE_PRE_START) {
270 		const struct t7xx_port_conf *port_conf = port->port_conf;
271 		enum md_state md_state = t7xx_fsm_get_md_state(ctl);
272 
273 		switch (md_state) {
274 		case MD_STATE_EXCEPTION:
275 			if (port_conf->tx_ch != PORT_CH_MD_LOG_TX)
276 				return -EBUSY;
277 			break;
278 
279 		case MD_STATE_WAITING_FOR_HS1:
280 		case MD_STATE_WAITING_FOR_HS2:
281 		case MD_STATE_STOPPED:
282 		case MD_STATE_WAITING_TO_STOP:
283 		case MD_STATE_INVALID:
284 			return -ENODEV;
285 
286 		default:
287 			break;
288 		}
289 	}
290 
291 	return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg);
292 }
293 
294 static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox)
295 {
296 	struct t7xx_port *port;
297 
298 	int i, j;
299 
300 	for (i = 0; i < ARRAY_SIZE(port_prox->rx_ch_ports); i++)
301 		INIT_LIST_HEAD(&port_prox->rx_ch_ports[i]);
302 
303 	for (j = 0; j < ARRAY_SIZE(port_prox->queue_ports); j++) {
304 		for (i = 0; i < ARRAY_SIZE(port_prox->queue_ports[j]); i++)
305 			INIT_LIST_HEAD(&port_prox->queue_ports[j][i]);
306 	}
307 
308 	for_each_proxy_port(i, port, port_prox) {
309 		const struct t7xx_port_conf *port_conf = port->port_conf;
310 		enum cldma_id path_id = port_conf->path_id;
311 		u8 ch_id;
312 
313 		ch_id = FIELD_GET(PORT_CH_ID_MASK, port_conf->rx_ch);
314 		list_add_tail(&port->entry, &port_prox->rx_ch_ports[ch_id]);
315 		list_add_tail(&port->queue_entry,
316 			      &port_prox->queue_ports[path_id][port_conf->rxq_index]);
317 	}
318 }
319 
320 static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev,
321 						   struct cldma_queue *queue, u16 channel)
322 {
323 	struct port_proxy *port_prox = t7xx_dev->md->port_prox;
324 	struct list_head *port_list;
325 	struct t7xx_port *port;
326 	u8 ch_id;
327 
328 	ch_id = FIELD_GET(PORT_CH_ID_MASK, channel);
329 	port_list = &port_prox->rx_ch_ports[ch_id];
330 	list_for_each_entry(port, port_list, entry) {
331 		const struct t7xx_port_conf *port_conf = port->port_conf;
332 
333 		if (queue->md_ctrl->hif_id == port_conf->path_id &&
334 		    channel == port_conf->rx_ch)
335 			return port;
336 	}
337 
338 	return NULL;
339 }
340 
341 /**
342  * t7xx_port_proxy_recv_skb() - Dispatch received skb.
343  * @queue: CLDMA queue.
344  * @skb: Socket buffer.
345  *
346  * Return:
347  ** 0		- Packet consumed.
348  ** -ERROR	- Failed to process skb.
349  */
350 static int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb)
351 {
352 	struct ccci_header *ccci_h = (struct ccci_header *)skb->data;
353 	struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;
354 	struct t7xx_fsm_ctl *ctl = t7xx_dev->md->fsm_ctl;
355 	struct device *dev = queue->md_ctrl->dev;
356 	const struct t7xx_port_conf *port_conf;
357 	struct t7xx_port *port;
358 	u16 seq_num, channel;
359 	int ret;
360 
361 	channel = FIELD_GET(CCCI_H_CHN_FLD, le32_to_cpu(ccci_h->status));
362 	if (t7xx_fsm_get_md_state(ctl) == MD_STATE_INVALID) {
363 		dev_err_ratelimited(dev, "Packet drop on channel 0x%x, modem not ready\n", channel);
364 		goto drop_skb;
365 	}
366 
367 	port = t7xx_port_proxy_find_port(t7xx_dev, queue, channel);
368 	if (!port) {
369 		dev_err_ratelimited(dev, "Packet drop on channel 0x%x, port not found\n", channel);
370 		goto drop_skb;
371 	}
372 
373 	seq_num = t7xx_port_next_rx_seq_num(port, ccci_h);
374 	port_conf = port->port_conf;
375 	skb_pull(skb, sizeof(*ccci_h));
376 
377 	ret = port_conf->ops->recv_skb(port, skb);
378 	/* Error indicates to try again later */
379 	if (ret) {
380 		skb_push(skb, sizeof(*ccci_h));
381 		return ret;
382 	}
383 
384 	port->seq_nums[MTK_RX] = seq_num;
385 	return 0;
386 
387 drop_skb:
388 	dev_kfree_skb_any(skb);
389 	return 0;
390 }
391 
392 /**
393  * t7xx_port_proxy_md_status_notify() - Notify all ports of state.
394  *@port_prox: The port_proxy pointer.
395  *@state: State.
396  *
397  * Called by t7xx_fsm. Used to dispatch modem status for all ports,
398  * which want to know MD state transition.
399  */
400 void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned int state)
401 {
402 	struct t7xx_port *port;
403 	int i;
404 
405 	for_each_proxy_port(i, port, port_prox) {
406 		const struct t7xx_port_conf *port_conf = port->port_conf;
407 
408 		if (port_conf->ops->md_state_notify)
409 			port_conf->ops->md_state_notify(port, state);
410 	}
411 }
412 
413 static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
414 {
415 	struct port_proxy *port_prox = md->port_prox;
416 	struct t7xx_port *port;
417 	int i;
418 
419 	for_each_proxy_port(i, port, port_prox) {
420 		const struct t7xx_port_conf *port_conf = port->port_conf;
421 
422 		t7xx_port_struct_init(port);
423 
424 		if (port_conf->tx_ch == PORT_CH_CONTROL_TX)
425 			md->core_md.ctl_port = port;
426 
427 		if (port_conf->tx_ch == PORT_CH_AP_CONTROL_TX)
428 			md->core_ap.ctl_port = port;
429 
430 		port->t7xx_dev = md->t7xx_dev;
431 		port->dev = &md->t7xx_dev->pdev->dev;
432 		spin_lock_init(&port->port_update_lock);
433 		port->chan_enable = false;
434 
435 		if (port_conf->ops->init)
436 			port_conf->ops->init(port);
437 	}
438 
439 	t7xx_proxy_setup_ch_mapping(port_prox);
440 }
441 
442 static int t7xx_proxy_alloc(struct t7xx_modem *md)
443 {
444 	unsigned int port_count = ARRAY_SIZE(t7xx_md_port_conf);
445 	struct device *dev = &md->t7xx_dev->pdev->dev;
446 	struct port_proxy *port_prox;
447 	int i;
448 
449 	port_prox = devm_kzalloc(dev, sizeof(*port_prox) + sizeof(struct t7xx_port) * port_count,
450 				 GFP_KERNEL);
451 	if (!port_prox)
452 		return -ENOMEM;
453 
454 	md->port_prox = port_prox;
455 	port_prox->dev = dev;
456 
457 	for (i = 0; i < port_count; i++)
458 		port_prox->ports[i].port_conf = &t7xx_md_port_conf[i];
459 
460 	port_prox->port_count = port_count;
461 	t7xx_proxy_init_all_ports(md);
462 	return 0;
463 }
464 
465 /**
466  * t7xx_port_proxy_init() - Initialize ports.
467  * @md: Modem.
468  *
469  * Create all port instances.
470  *
471  * Return:
472  * * 0		- Success.
473  * * -ERROR	- Error code from failure sub-initializations.
474  */
475 int t7xx_port_proxy_init(struct t7xx_modem *md)
476 {
477 	int ret;
478 
479 	ret = t7xx_proxy_alloc(md);
480 	if (ret)
481 		return ret;
482 
483 	t7xx_cldma_set_recv_skb(md->md_ctrl[CLDMA_ID_AP], t7xx_port_proxy_recv_skb);
484 	t7xx_cldma_set_recv_skb(md->md_ctrl[CLDMA_ID_MD], t7xx_port_proxy_recv_skb);
485 	return 0;
486 }
487 
488 void t7xx_port_proxy_uninit(struct port_proxy *port_prox)
489 {
490 	struct t7xx_port *port;
491 	int i;
492 
493 	for_each_proxy_port(i, port, port_prox) {
494 		const struct t7xx_port_conf *port_conf = port->port_conf;
495 
496 		if (port_conf->ops->uninit)
497 			port_conf->ops->uninit(port);
498 	}
499 }
500 
501 int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned int ch_id,
502 				       bool en_flag)
503 {
504 	struct t7xx_port *port = t7xx_proxy_get_port_by_ch(port_prox, ch_id);
505 	const struct t7xx_port_conf *port_conf;
506 
507 	if (!port)
508 		return -EINVAL;
509 
510 	port_conf = port->port_conf;
511 
512 	if (en_flag) {
513 		if (port_conf->ops->enable_chl)
514 			port_conf->ops->enable_chl(port);
515 	} else {
516 		if (port_conf->ops->disable_chl)
517 			port_conf->ops->disable_chl(port);
518 	}
519 
520 	return 0;
521 }
522