0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
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
0118
0119
0120
0121
0122
0123
0124
0125
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 };