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#define T7XX_MAX_POSSIBLE_PORTS_NUM	\
52	(max(ARRAY_SIZE(t7xx_port_conf), ARRAY_SIZE(t7xx_early_port_conf)))
53
54static const struct t7xx_port_conf t7xx_port_conf[] = {
55	{
56		.tx_ch = PORT_CH_UART2_TX,
57		.rx_ch = PORT_CH_UART2_RX,
58		.txq_index = Q_IDX_AT_CMD,
59		.rxq_index = Q_IDX_AT_CMD,
60		.txq_exp_index = 0xff,
61		.rxq_exp_index = 0xff,
62		.path_id = CLDMA_ID_MD,
63		.ops = &wwan_sub_port_ops,
64		.name = "AT",
65		.port_type = WWAN_PORT_AT,
66	}, {
67		.tx_ch = PORT_CH_MBIM_TX,
68		.rx_ch = PORT_CH_MBIM_RX,
69		.txq_index = Q_IDX_MBIM,
70		.rxq_index = Q_IDX_MBIM,
71		.path_id = CLDMA_ID_MD,
72		.ops = &wwan_sub_port_ops,
73		.name = "MBIM",
74		.port_type = WWAN_PORT_MBIM,
75	}, {
76#ifdef CONFIG_WWAN_DEBUGFS
77		.tx_ch = PORT_CH_MD_LOG_TX,
78		.rx_ch = PORT_CH_MD_LOG_RX,
79		.txq_index = 7,
80		.rxq_index = 7,
81		.txq_exp_index = 7,
82		.rxq_exp_index = 7,
83		.path_id = CLDMA_ID_MD,
84		.ops = &t7xx_trace_port_ops,
85		.name = "mdlog",
86	}, {
87#endif
88		.tx_ch = PORT_CH_CONTROL_TX,
89		.rx_ch = PORT_CH_CONTROL_RX,
90		.txq_index = Q_IDX_CTRL,
91		.rxq_index = Q_IDX_CTRL,
92		.path_id = CLDMA_ID_MD,
93		.ops = &ctl_port_ops,
94		.name = "t7xx_ctrl",
95	}, {
96		.tx_ch = PORT_CH_AP_CONTROL_TX,
97		.rx_ch = PORT_CH_AP_CONTROL_RX,
98		.txq_index = Q_IDX_CTRL,
99		.rxq_index = Q_IDX_CTRL,
100		.path_id = CLDMA_ID_AP,
101		.ops = &ctl_port_ops,
102		.name = "t7xx_ap_ctrl",
103	},
104};
105
106static const struct t7xx_port_conf t7xx_early_port_conf[] = {
107	{
108		.tx_ch = PORT_CH_UNIMPORTANT,
109		.rx_ch = PORT_CH_UNIMPORTANT,
110		.txq_index = CLDMA_Q_IDX_DUMP,
111		.rxq_index = CLDMA_Q_IDX_DUMP,
112		.txq_exp_index = CLDMA_Q_IDX_DUMP,
113		.rxq_exp_index = CLDMA_Q_IDX_DUMP,
114		.path_id = CLDMA_ID_AP,
115		.ops = &wwan_sub_port_ops,
116		.name = "fastboot",
117		.port_type = WWAN_PORT_FASTBOOT,
118	},
119};
120
121static struct t7xx_port *t7xx_proxy_get_port_by_ch(struct port_proxy *port_prox, enum port_ch ch)
122{
123	const struct t7xx_port_conf *port_conf;
124	struct t7xx_port *port;
125	int i;
126
127	for_each_proxy_port(i, port, port_prox) {
128		port_conf = port->port_conf;
129		if (port_conf->rx_ch == ch || port_conf->tx_ch == ch)
130			return port;
131	}
132
133	return NULL;
134}
135
136static u16 t7xx_port_next_rx_seq_num(struct t7xx_port *port, struct ccci_header *ccci_h)
137{
138	u32 status = le32_to_cpu(ccci_h->status);
139	u16 seq_num, next_seq_num;
140	bool assert_bit;
141
142	seq_num = FIELD_GET(CCCI_H_SEQ_FLD, status);
143	next_seq_num = (seq_num + 1) & FIELD_MAX(CCCI_H_SEQ_FLD);
144	assert_bit = status & CCCI_H_AST_BIT;
145	if (!assert_bit || port->seq_nums[MTK_RX] == INVALID_SEQ_NUM)
146		return next_seq_num;
147
148	if (seq_num != port->seq_nums[MTK_RX])
149		dev_warn_ratelimited(port->dev,
150				     "seq num out-of-order %u != %u (header %X, len %X)\n",
151				     seq_num, port->seq_nums[MTK_RX],
152				     le32_to_cpu(ccci_h->packet_header),
153				     le32_to_cpu(ccci_h->packet_len));
154
155	return next_seq_num;
156}
157
158void t7xx_port_proxy_reset(struct port_proxy *port_prox)
159{
160	struct t7xx_port *port;
161	int i;
162
163	for_each_proxy_port(i, port, port_prox) {
164		port->seq_nums[MTK_RX] = INVALID_SEQ_NUM;
165		port->seq_nums[MTK_TX] = 0;
166	}
167}
168
169static int t7xx_port_get_queue_no(struct t7xx_port *port)
170{
171	const struct t7xx_port_conf *port_conf = port->port_conf;
172	struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
173
174	return t7xx_fsm_get_md_state(ctl) == MD_STATE_EXCEPTION ?
175		port_conf->txq_exp_index : port_conf->txq_index;
176}
177
178static void t7xx_port_struct_init(struct t7xx_port *port)
179{
180	INIT_LIST_HEAD(&port->entry);
181	INIT_LIST_HEAD(&port->queue_entry);
182	skb_queue_head_init(&port->rx_skb_list);
183	init_waitqueue_head(&port->rx_wq);
184	port->seq_nums[MTK_RX] = INVALID_SEQ_NUM;
185	port->seq_nums[MTK_TX] = 0;
186	atomic_set(&port->usage_cnt, 0);
187}
188
189struct sk_buff *t7xx_port_alloc_skb(int payload)
190{
191	struct sk_buff *skb = __dev_alloc_skb(payload + sizeof(struct ccci_header), GFP_KERNEL);
192
193	if (skb)
194		skb_reserve(skb, sizeof(struct ccci_header));
195
196	return skb;
197}
198
199struct sk_buff *t7xx_ctrl_alloc_skb(int payload)
200{
201	struct sk_buff *skb = t7xx_port_alloc_skb(payload + sizeof(struct ctrl_msg_header));
202
203	if (skb)
204		skb_reserve(skb, sizeof(struct ctrl_msg_header));
205
206	return skb;
207}
208
209/**
210 * t7xx_port_enqueue_skb() - Enqueue the received skb into the port's rx_skb_list.
211 * @port: port context.
212 * @skb: received skb.
213 *
214 * Return:
215 * * 0		- Success.
216 * * -ENOBUFS	- Not enough buffer space. Caller will try again later, skb is not consumed.
217 */
218int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb)
219{
220	unsigned long flags;
221
222	spin_lock_irqsave(&port->rx_wq.lock, flags);
223	if (port->rx_skb_list.qlen >= port->rx_length_th) {
224		spin_unlock_irqrestore(&port->rx_wq.lock, flags);
225
226		return -ENOBUFS;
227	}
228	__skb_queue_tail(&port->rx_skb_list, skb);
229	spin_unlock_irqrestore(&port->rx_wq.lock, flags);
230
231	wake_up_all(&port->rx_wq);
232	return 0;
233}
234
235int t7xx_get_port_mtu(struct t7xx_port *port)
236{
237	enum cldma_id path_id = port->port_conf->path_id;
238	int tx_qno = t7xx_port_get_queue_no(port);
239	struct cldma_ctrl *md_ctrl;
240
241	md_ctrl = port->t7xx_dev->md->md_ctrl[path_id];
242	return md_ctrl->tx_ring[tx_qno].pkt_size;
243}
244
245int t7xx_port_send_raw_skb(struct t7xx_port *port, struct sk_buff *skb)
246{
247	enum cldma_id path_id = port->port_conf->path_id;
248	struct cldma_ctrl *md_ctrl;
249	int ret, tx_qno;
250
251	md_ctrl = port->t7xx_dev->md->md_ctrl[path_id];
252	tx_qno = t7xx_port_get_queue_no(port);
253	ret = t7xx_cldma_send_skb(md_ctrl, tx_qno, skb);
254	if (ret)
255		dev_err(port->dev, "Failed to send skb: %d\n", ret);
256
257	return ret;
258}
259
260static int t7xx_port_send_ccci_skb(struct t7xx_port *port, struct sk_buff *skb,
261				   unsigned int pkt_header, unsigned int ex_msg)
262{
263	const struct t7xx_port_conf *port_conf = port->port_conf;
264	struct ccci_header *ccci_h;
265	u32 status;
266	int ret;
267
268	ccci_h = skb_push(skb, sizeof(*ccci_h));
269	status = FIELD_PREP(CCCI_H_CHN_FLD, port_conf->tx_ch) |
270		 FIELD_PREP(CCCI_H_SEQ_FLD, port->seq_nums[MTK_TX]) | CCCI_H_AST_BIT;
271	ccci_h->status = cpu_to_le32(status);
272	ccci_h->packet_header = cpu_to_le32(pkt_header);
273	ccci_h->packet_len = cpu_to_le32(skb->len);
274	ccci_h->ex_msg = cpu_to_le32(ex_msg);
275
276	ret = t7xx_port_send_raw_skb(port, skb);
277	if (ret)
278		return ret;
279
280	port->seq_nums[MTK_TX]++;
281	return 0;
282}
283
284int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg,
285			   unsigned int ex_msg)
286{
287	struct ctrl_msg_header *ctrl_msg_h;
288	unsigned int msg_len = skb->len;
289	u32 pkt_header = 0;
290
291	ctrl_msg_h = skb_push(skb, sizeof(*ctrl_msg_h));
292	ctrl_msg_h->ctrl_msg_id = cpu_to_le32(msg);
293	ctrl_msg_h->ex_msg = cpu_to_le32(ex_msg);
294	ctrl_msg_h->data_length = cpu_to_le32(msg_len);
295
296	if (!msg_len)
297		pkt_header = CCCI_HEADER_NO_DATA;
298
299	return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg);
300}
301
302int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int pkt_header,
303		       unsigned int ex_msg)
304{
305	struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
306	unsigned int fsm_state;
307
308	fsm_state = t7xx_fsm_get_ctl_state(ctl);
309	if (fsm_state != FSM_STATE_PRE_START) {
310		const struct t7xx_port_conf *port_conf = port->port_conf;
311		enum md_state md_state = t7xx_fsm_get_md_state(ctl);
312
313		switch (md_state) {
314		case MD_STATE_EXCEPTION:
315			if (port_conf->tx_ch != PORT_CH_MD_LOG_TX)
316				return -EBUSY;
317			break;
318
319		case MD_STATE_WAITING_FOR_HS1:
320		case MD_STATE_WAITING_FOR_HS2:
321		case MD_STATE_STOPPED:
322		case MD_STATE_WAITING_TO_STOP:
323		case MD_STATE_INVALID:
324			return -ENODEV;
325
326		default:
327			break;
328		}
329	}
330
331	return t7xx_port_send_ccci_skb(port, skb, pkt_header, ex_msg);
332}
333
334static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox)
335{
336	struct t7xx_port *port;
337
338	int i, j;
339
340	for (i = 0; i < ARRAY_SIZE(port_prox->rx_ch_ports); i++)
341		INIT_LIST_HEAD(&port_prox->rx_ch_ports[i]);
342
343	for (j = 0; j < ARRAY_SIZE(port_prox->queue_ports); j++) {
344		for (i = 0; i < ARRAY_SIZE(port_prox->queue_ports[j]); i++)
345			INIT_LIST_HEAD(&port_prox->queue_ports[j][i]);
346	}
347
348	for_each_proxy_port(i, port, port_prox) {
349		const struct t7xx_port_conf *port_conf = port->port_conf;
350		enum cldma_id path_id = port_conf->path_id;
351		u8 ch_id;
352
353		ch_id = FIELD_GET(PORT_CH_ID_MASK, port_conf->rx_ch);
354		list_add_tail(&port->entry, &port_prox->rx_ch_ports[ch_id]);
355		list_add_tail(&port->queue_entry,
356			      &port_prox->queue_ports[path_id][port_conf->rxq_index]);
357	}
358}
359
360/**
361 * t7xx_port_proxy_recv_skb_from_dedicated_queue() - Dispatch early port received skb.
362 * @queue: CLDMA queue.
363 * @skb: Socket buffer.
364 *
365 * Return:
366 ** 0		- Packet consumed.
367 ** -ERROR	- Failed to process skb.
368 */
369int t7xx_port_proxy_recv_skb_from_dedicated_queue(struct cldma_queue *queue, struct sk_buff *skb)
370{
371	struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;
372	struct port_proxy *port_prox = t7xx_dev->md->port_prox;
373	const struct t7xx_port_conf *port_conf;
374	struct t7xx_port *port;
375	int ret;
376
377	port = &port_prox->ports[0];
378	if (WARN_ON_ONCE(port->port_conf->rxq_index != queue->index)) {
379		dev_kfree_skb_any(skb);
380		return -EINVAL;
381	}
382
383	port_conf = port->port_conf;
384	ret = port_conf->ops->recv_skb(port, skb);
385	if (ret < 0 && ret != -ENOBUFS) {
386		dev_err(port->dev, "drop on RX ch %d, %d\n", port_conf->rx_ch, ret);
387		dev_kfree_skb_any(skb);
388	}
389
390	return ret;
391}
392
393static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev,
394						   struct cldma_queue *queue, u16 channel)
395{
396	struct port_proxy *port_prox = t7xx_dev->md->port_prox;
397	struct list_head *port_list;
398	struct t7xx_port *port;
399	u8 ch_id;
400
401	ch_id = FIELD_GET(PORT_CH_ID_MASK, channel);
402	port_list = &port_prox->rx_ch_ports[ch_id];
403	list_for_each_entry(port, port_list, entry) {
404		const struct t7xx_port_conf *port_conf = port->port_conf;
405
406		if (queue->md_ctrl->hif_id == port_conf->path_id &&
407		    channel == port_conf->rx_ch)
408			return port;
409	}
410
411	return NULL;
412}
413
414/**
415 * t7xx_port_proxy_recv_skb() - Dispatch received skb.
416 * @queue: CLDMA queue.
417 * @skb: Socket buffer.
418 *
419 * Return:
420 ** 0		- Packet consumed.
421 ** -ERROR	- Failed to process skb.
422 */
423int t7xx_port_proxy_recv_skb(struct cldma_queue *queue, struct sk_buff *skb)
424{
425	struct ccci_header *ccci_h = (struct ccci_header *)skb->data;
426	struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;
427	struct t7xx_fsm_ctl *ctl = t7xx_dev->md->fsm_ctl;
428	struct device *dev = queue->md_ctrl->dev;
429	const struct t7xx_port_conf *port_conf;
430	struct t7xx_port *port;
431	u16 seq_num, channel;
432	int ret;
433
434	channel = FIELD_GET(CCCI_H_CHN_FLD, le32_to_cpu(ccci_h->status));
435	if (t7xx_fsm_get_md_state(ctl) == MD_STATE_INVALID) {
436		dev_err_ratelimited(dev, "Packet drop on channel 0x%x, modem not ready\n", channel);
437		goto drop_skb;
438	}
439
440	port = t7xx_port_proxy_find_port(t7xx_dev, queue, channel);
441	if (!port) {
442		dev_err_ratelimited(dev, "Packet drop on channel 0x%x, port not found\n", channel);
443		goto drop_skb;
444	}
445
446	seq_num = t7xx_port_next_rx_seq_num(port, ccci_h);
447	port_conf = port->port_conf;
448	skb_pull(skb, sizeof(*ccci_h));
449
450	ret = port_conf->ops->recv_skb(port, skb);
451	/* Error indicates to try again later */
452	if (ret) {
453		skb_push(skb, sizeof(*ccci_h));
454		return ret;
455	}
456
457	port->seq_nums[MTK_RX] = seq_num;
458	return 0;
459
460drop_skb:
461	dev_kfree_skb_any(skb);
462	return 0;
463}
464
465/**
466 * t7xx_port_proxy_md_status_notify() - Notify all ports of state.
467 *@port_prox: The port_proxy pointer.
468 *@state: State.
469 *
470 * Called by t7xx_fsm. Used to dispatch modem status for all ports,
471 * which want to know MD state transition.
472 */
473void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned int state)
474{
475	struct t7xx_port *port;
476	int i;
477
478	for_each_proxy_port(i, port, port_prox) {
479		const struct t7xx_port_conf *port_conf = port->port_conf;
480
481		if (port_conf->ops->md_state_notify)
482			port_conf->ops->md_state_notify(port, state);
483	}
484}
485
486static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)
487{
488	struct port_proxy *port_prox = md->port_prox;
489	struct t7xx_port *port;
490	int i;
491
492	for_each_proxy_port(i, port, port_prox) {
493		const struct t7xx_port_conf *port_conf = port->port_conf;
494
495		t7xx_port_struct_init(port);
496
497		if (port_conf->tx_ch == PORT_CH_CONTROL_TX)
498			md->core_md.ctl_port = port;
499
500		if (port_conf->tx_ch == PORT_CH_AP_CONTROL_TX)
501			md->core_ap.ctl_port = port;
502
503		port->t7xx_dev = md->t7xx_dev;
504		port->dev = &md->t7xx_dev->pdev->dev;
505		spin_lock_init(&port->port_update_lock);
506		port->chan_enable = false;
507
508		if (port_conf->ops && port_conf->ops->init)
509			port_conf->ops->init(port);
510	}
511
512	t7xx_proxy_setup_ch_mapping(port_prox);
513}
514
515void t7xx_port_proxy_set_cfg(struct t7xx_modem *md, enum port_cfg_id cfg_id)
516{
517	struct port_proxy *port_prox = md->port_prox;
518	const struct t7xx_port_conf *port_conf;
519	u32 port_count;
520	int i;
521
522	t7xx_port_proxy_uninit(port_prox);
523
524	if (cfg_id == PORT_CFG_ID_EARLY) {
525		port_conf = t7xx_early_port_conf;
526		port_count = ARRAY_SIZE(t7xx_early_port_conf);
527	} else {
528		port_conf = t7xx_port_conf;
529		port_count = ARRAY_SIZE(t7xx_port_conf);
530	}
531
532	for (i = 0; i < port_count; i++)
533		port_prox->ports[i].port_conf = &port_conf[i];
534
535	port_prox->cfg_id = cfg_id;
536	port_prox->port_count = port_count;
537
538	t7xx_proxy_init_all_ports(md);
539}
540
541static int t7xx_proxy_alloc(struct t7xx_modem *md)
542{
543	struct device *dev = &md->t7xx_dev->pdev->dev;
544	struct port_proxy *port_prox;
545
546	port_prox = devm_kzalloc(dev,
547				 struct_size(port_prox,
548					     ports,
549					     T7XX_MAX_POSSIBLE_PORTS_NUM),
550				 GFP_KERNEL);
551	if (!port_prox)
552		return -ENOMEM;
553
554	md->port_prox = port_prox;
555	port_prox->dev = dev;
556	t7xx_port_proxy_set_cfg(md, PORT_CFG_ID_EARLY);
557
558	return 0;
559}
560
561/**
562 * t7xx_port_proxy_init() - Initialize ports.
563 * @md: Modem.
564 *
565 * Create all port instances.
566 *
567 * Return:
568 * * 0		- Success.
569 * * -ERROR	- Error code from failure sub-initializations.
570 */
571int t7xx_port_proxy_init(struct t7xx_modem *md)
572{
573	int ret;
574
575	ret = t7xx_proxy_alloc(md);
576	if (ret)
577		return ret;
578
579	return 0;
580}
581
582void t7xx_port_proxy_uninit(struct port_proxy *port_prox)
583{
584	struct t7xx_port *port;
585	int i;
586
587	for_each_proxy_port(i, port, port_prox) {
588		const struct t7xx_port_conf *port_conf = port->port_conf;
589
590		if (port_conf->ops && port_conf->ops->uninit)
591			port_conf->ops->uninit(port);
592	}
593}
594
595int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned int ch_id,
596				       bool en_flag)
597{
598	struct t7xx_port *port = t7xx_proxy_get_port_by_ch(port_prox, ch_id);
599	const struct t7xx_port_conf *port_conf;
600
601	if (!port)
602		return -EINVAL;
603
604	port_conf = port->port_conf;
605
606	if (en_flag) {
607		if (port_conf->ops->enable_chl)
608			port_conf->ops->enable_chl(port);
609	} else {
610		if (port_conf->ops->disable_chl)
611			port_conf->ops->disable_chl(port);
612	}
613
614	return 0;
615}
616