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