Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2021, MediaTek Inc.
0004  * Copyright (c) 2021-2022, Intel Corporation.
0005  *
0006  * Authors:
0007  *  Haijun Liu <haijun.liu@mediatek.com>
0008  *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
0009  *  Moises Veleta <moises.veleta@intel.com>
0010  *
0011  * Contributors:
0012  *  Amir Hanania <amir.hanania@intel.com>
0013  *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
0014  *  Eliot Lee <eliot.lee@intel.com>
0015  *  Sreehari Kancharla <sreehari.kancharla@intel.com>
0016  */
0017 
0018 #include <linux/bitfield.h>
0019 #include <linux/device.h>
0020 #include <linux/err.h>
0021 #include <linux/kthread.h>
0022 #include <linux/netdevice.h>
0023 #include <linux/skbuff.h>
0024 #include <linux/spinlock.h>
0025 
0026 #include "t7xx_port.h"
0027 #include "t7xx_port_proxy.h"
0028 #include "t7xx_state_monitor.h"
0029 
0030 #define PORT_MSG_VERSION    GENMASK(31, 16)
0031 #define PORT_MSG_PRT_CNT    GENMASK(15, 0)
0032 
0033 struct port_msg {
0034     __le32  head_pattern;
0035     __le32  info;
0036     __le32  tail_pattern;
0037     __le32  data[];
0038 };
0039 
0040 static int port_ctl_send_msg_to_md(struct t7xx_port *port, unsigned int msg, unsigned int ex_msg)
0041 {
0042     struct sk_buff *skb;
0043     int ret;
0044 
0045     skb = t7xx_ctrl_alloc_skb(0);
0046     if (!skb)
0047         return -ENOMEM;
0048 
0049     ret = t7xx_port_send_ctl_skb(port, skb, msg, ex_msg);
0050     if (ret)
0051         dev_kfree_skb_any(skb);
0052 
0053     return ret;
0054 }
0055 
0056 static int fsm_ee_message_handler(struct t7xx_port *port, struct t7xx_fsm_ctl *ctl,
0057                   struct sk_buff *skb)
0058 {
0059     struct ctrl_msg_header *ctrl_msg_h = (struct ctrl_msg_header *)skb->data;
0060     struct device *dev = &ctl->md->t7xx_dev->pdev->dev;
0061     enum md_state md_state;
0062     int ret = -EINVAL;
0063 
0064     md_state = t7xx_fsm_get_md_state(ctl);
0065     if (md_state != MD_STATE_EXCEPTION) {
0066         dev_err(dev, "Receive invalid MD_EX %x when MD state is %d\n",
0067             ctrl_msg_h->ex_msg, md_state);
0068         return -EINVAL;
0069     }
0070 
0071     switch (le32_to_cpu(ctrl_msg_h->ctrl_msg_id)) {
0072     case CTL_ID_MD_EX:
0073         if (le32_to_cpu(ctrl_msg_h->ex_msg) != MD_EX_CHK_ID) {
0074             dev_err(dev, "Receive invalid MD_EX %x\n", ctrl_msg_h->ex_msg);
0075             break;
0076         }
0077 
0078         ret = port_ctl_send_msg_to_md(port, CTL_ID_MD_EX, MD_EX_CHK_ID);
0079         if (ret) {
0080             dev_err(dev, "Failed to send exception message to modem\n");
0081             break;
0082         }
0083 
0084         ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_EX, NULL, 0);
0085         if (ret)
0086             dev_err(dev, "Failed to append Modem Exception event");
0087 
0088         break;
0089 
0090     case CTL_ID_MD_EX_ACK:
0091         if (le32_to_cpu(ctrl_msg_h->ex_msg) != MD_EX_CHK_ACK_ID) {
0092             dev_err(dev, "Receive invalid MD_EX_ACK %x\n", ctrl_msg_h->ex_msg);
0093             break;
0094         }
0095 
0096         ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_EX_REC_OK, NULL, 0);
0097         if (ret)
0098             dev_err(dev, "Failed to append Modem Exception Received event");
0099 
0100         break;
0101 
0102     case CTL_ID_MD_EX_PASS:
0103         ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_EX_PASS, NULL, 0);
0104         if (ret)
0105             dev_err(dev, "Failed to append Modem Exception Passed event");
0106 
0107         break;
0108 
0109     case CTL_ID_DRV_VER_ERROR:
0110         dev_err(dev, "AP/MD driver version mismatch\n");
0111     }
0112 
0113     return ret;
0114 }
0115 
0116 /**
0117  * t7xx_port_enum_msg_handler() - Parse the port enumeration message to create/remove nodes.
0118  * @md: Modem context.
0119  * @msg: Message.
0120  *
0121  * Used to control create/remove device node.
0122  *
0123  * Return:
0124  * * 0      - Success.
0125  * * -EFAULT    - Message check failure.
0126  */
0127 int t7xx_port_enum_msg_handler(struct t7xx_modem *md, void *msg)
0128 {
0129     struct device *dev = &md->t7xx_dev->pdev->dev;
0130     unsigned int version, port_count, i;
0131     struct port_msg *port_msg = msg;
0132 
0133     version = FIELD_GET(PORT_MSG_VERSION, le32_to_cpu(port_msg->info));
0134     if (version != PORT_ENUM_VER ||
0135         le32_to_cpu(port_msg->head_pattern) != PORT_ENUM_HEAD_PATTERN ||
0136         le32_to_cpu(port_msg->tail_pattern) != PORT_ENUM_TAIL_PATTERN) {
0137         dev_err(dev, "Invalid port control message %x:%x:%x\n",
0138             version, le32_to_cpu(port_msg->head_pattern),
0139             le32_to_cpu(port_msg->tail_pattern));
0140         return -EFAULT;
0141     }
0142 
0143     port_count = FIELD_GET(PORT_MSG_PRT_CNT, le32_to_cpu(port_msg->info));
0144     for (i = 0; i < port_count; i++) {
0145         u32 port_info = le32_to_cpu(port_msg->data[i]);
0146         unsigned int ch_id;
0147         bool en_flag;
0148 
0149         ch_id = FIELD_GET(PORT_INFO_CH_ID, port_info);
0150         en_flag = port_info & PORT_INFO_ENFLG;
0151         if (t7xx_port_proxy_chl_enable_disable(md->port_prox, ch_id, en_flag))
0152             dev_dbg(dev, "Port:%x not found\n", ch_id);
0153     }
0154 
0155     return 0;
0156 }
0157 
0158 static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb)
0159 {
0160     const struct t7xx_port_conf *port_conf = port->port_conf;
0161     struct t7xx_fsm_ctl *ctl = port->t7xx_dev->md->fsm_ctl;
0162     struct ctrl_msg_header *ctrl_msg_h;
0163     int ret = 0;
0164 
0165     ctrl_msg_h = (struct ctrl_msg_header *)skb->data;
0166     switch (le32_to_cpu(ctrl_msg_h->ctrl_msg_id)) {
0167     case CTL_ID_HS2_MSG:
0168         skb_pull(skb, sizeof(*ctrl_msg_h));
0169 
0170         if (port_conf->rx_ch == PORT_CH_CONTROL_RX) {
0171             ret = t7xx_fsm_append_event(ctl, FSM_EVENT_MD_HS2, skb->data,
0172                             le32_to_cpu(ctrl_msg_h->data_length));
0173             if (ret)
0174                 dev_err(port->dev, "Failed to append Handshake 2 event");
0175         }
0176 
0177         dev_kfree_skb_any(skb);
0178         break;
0179 
0180     case CTL_ID_MD_EX:
0181     case CTL_ID_MD_EX_ACK:
0182     case CTL_ID_MD_EX_PASS:
0183     case CTL_ID_DRV_VER_ERROR:
0184         ret = fsm_ee_message_handler(port, ctl, skb);
0185         dev_kfree_skb_any(skb);
0186         break;
0187 
0188     case CTL_ID_PORT_ENUM:
0189         skb_pull(skb, sizeof(*ctrl_msg_h));
0190         ret = t7xx_port_enum_msg_handler(ctl->md, (struct port_msg *)skb->data);
0191         if (!ret)
0192             ret = port_ctl_send_msg_to_md(port, CTL_ID_PORT_ENUM, 0);
0193         else
0194             ret = port_ctl_send_msg_to_md(port, CTL_ID_PORT_ENUM,
0195                               PORT_ENUM_VER_MISMATCH);
0196 
0197         break;
0198 
0199     default:
0200         ret = -EINVAL;
0201         dev_err(port->dev, "Unknown control message ID to FSM %x\n",
0202             le32_to_cpu(ctrl_msg_h->ctrl_msg_id));
0203         break;
0204     }
0205 
0206     if (ret)
0207         dev_err(port->dev, "%s control message handle error: %d\n", port_conf->name, ret);
0208 
0209     return ret;
0210 }
0211 
0212 static int port_ctl_rx_thread(void *arg)
0213 {
0214     while (!kthread_should_stop()) {
0215         struct t7xx_port *port = arg;
0216         struct sk_buff *skb;
0217         unsigned long flags;
0218 
0219         spin_lock_irqsave(&port->rx_wq.lock, flags);
0220         if (skb_queue_empty(&port->rx_skb_list) &&
0221             wait_event_interruptible_locked_irq(port->rx_wq,
0222                             !skb_queue_empty(&port->rx_skb_list) ||
0223                             kthread_should_stop())) {
0224             spin_unlock_irqrestore(&port->rx_wq.lock, flags);
0225             continue;
0226         }
0227         if (kthread_should_stop()) {
0228             spin_unlock_irqrestore(&port->rx_wq.lock, flags);
0229             break;
0230         }
0231         skb = __skb_dequeue(&port->rx_skb_list);
0232         spin_unlock_irqrestore(&port->rx_wq.lock, flags);
0233 
0234         control_msg_handler(port, skb);
0235     }
0236 
0237     return 0;
0238 }
0239 
0240 static int port_ctl_init(struct t7xx_port *port)
0241 {
0242     const struct t7xx_port_conf *port_conf = port->port_conf;
0243 
0244     port->thread = kthread_run(port_ctl_rx_thread, port, "%s", port_conf->name);
0245     if (IS_ERR(port->thread)) {
0246         dev_err(port->dev, "Failed to start port control thread\n");
0247         return PTR_ERR(port->thread);
0248     }
0249 
0250     port->rx_length_th = CTRL_QUEUE_MAXLEN;
0251     return 0;
0252 }
0253 
0254 static void port_ctl_uninit(struct t7xx_port *port)
0255 {
0256     unsigned long flags;
0257     struct sk_buff *skb;
0258 
0259     if (port->thread)
0260         kthread_stop(port->thread);
0261 
0262     spin_lock_irqsave(&port->rx_wq.lock, flags);
0263     port->rx_length_th = 0;
0264     while ((skb = __skb_dequeue(&port->rx_skb_list)) != NULL)
0265         dev_kfree_skb_any(skb);
0266     spin_unlock_irqrestore(&port->rx_wq.lock, flags);
0267 }
0268 
0269 struct port_ops ctl_port_ops = {
0270     .init = port_ctl_init,
0271     .recv_skb = t7xx_port_enqueue_skb,
0272     .uninit = port_ctl_uninit,
0273 };