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