On Thu, 7 Apr 2022, Ricardo Martinez wrote: > From: Haijun Liu <haijun.liu@xxxxxxxxxxxx> > > Control Port implements driver control messages such as modem-host > handshaking, controls port enumeration, and handles exception messages. > > The handshaking process between the driver and the modem happens during > the init sequence. The process involves the exchange of a list of > supported runtime features to make sure that modem and host are ready > to provide proper feature lists including port enumeration. Further > features can be enabled and controlled in this handshaking process. > > Signed-off-by: Haijun Liu <haijun.liu@xxxxxxxxxxxx> > Signed-off-by: Chandrashekar Devegowda <chandrashekar.devegowda@xxxxxxxxx> > Co-developed-by: Ricardo Martinez <ricardo.martinez@xxxxxxxxxxxxxxx> > Signed-off-by: Ricardo Martinez <ricardo.martinez@xxxxxxxxxxxxxxx> > > >From a WWAN framework perspective: > Reviewed-by: Loic Poulain <loic.poulain@xxxxxxxxxx> > > Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@xxxxxxxxxxxxxxx> > +static int t7xx_prepare_device_rt_data(struct t7xx_sys_info *core, struct device *dev, > + void *data) > +{ > + struct feature_query *md_feature = data; > + struct mtk_runtime_feature *rt_feature; > + unsigned int i, rt_data_len = 0; > + struct sk_buff *skb; > + > + /* Parse MD runtime data query */ > + if (le32_to_cpu(md_feature->head_pattern) != MD_FEATURE_QUERY_ID || > + le32_to_cpu(md_feature->tail_pattern) != MD_FEATURE_QUERY_ID) { > + dev_err(dev, "Invalid feature pattern: head 0x%x, tail 0x%x\n", > + le32_to_cpu(md_feature->head_pattern), > + le32_to_cpu(md_feature->tail_pattern)); > + return -EINVAL; > + } > + > + for (i = 0; i < FEATURE_COUNT; i++) { > + if (FIELD_GET(FEATURE_MSK, md_feature->feature_set[i]) != > + MTK_FEATURE_MUST_BE_SUPPORTED) > + rt_data_len += sizeof(*rt_feature); > + } > + > + skb = t7xx_ctrl_alloc_skb(rt_data_len); > + if (!skb) > + return -ENOMEM; > + > + rt_feature = skb_put(skb, rt_data_len); > + memset(rt_feature, 0, rt_data_len); > + > + /* Fill runtime feature */ > + for (i = 0; i < FEATURE_COUNT; i++) { > + u8 md_feature_mask = FIELD_GET(FEATURE_MSK, md_feature->feature_set[i]); > + > + if (md_feature_mask == MTK_FEATURE_MUST_BE_SUPPORTED) > + continue; > + > + rt_feature->feature_id = i; > + if (md_feature_mask == MTK_FEATURE_DOES_NOT_EXIST) > + rt_feature->support_info = md_feature->feature_set[i]; > + > + rt_feature++; > + } > + > + /* Send HS3 message to device */ > + t7xx_port_send_ctl_skb(core->ctl_port, skb, CTL_ID_HS3_MSG, 0); > + return 0; > +} > + > +static int t7xx_parse_host_rt_data(struct t7xx_fsm_ctl *ctl, struct t7xx_sys_info *core, > + struct device *dev, void *data, int data_length) > +{ > + enum mtk_feature_support_type ft_spt_st, ft_spt_cfg; > + struct mtk_runtime_feature *rt_feature; > + int i, offset; > + > + offset = sizeof(struct feature_query); > + for (i = 0; i < FEATURE_COUNT && offset < data_length; i++) { > + rt_feature = data + offset; > + offset += sizeof(*rt_feature) + le32_to_cpu(rt_feature->data_len); > + > + ft_spt_cfg = FIELD_GET(FEATURE_MSK, core->feature_set[i]); > + if (ft_spt_cfg != MTK_FEATURE_MUST_BE_SUPPORTED) > + continue; Do MTK_FEATURE_MUST_BE_SUPPORTED appear in the host rt_features (unlike in the device rt_features)? > + port_count = FIELD_GET(PORT_MSG_PRT_CNT, le32_to_cpu(port_msg->info)); > + for (i = 0; i < port_count; i++) { > + u32 port_info = le32_to_cpu(port_msg->data[i]); > + unsigned int ch_id; > + bool en_flag; > + > + ch_id = FIELD_GET(PORT_INFO_CH_ID, port_info); > + en_flag = !!(port_info & PORT_INFO_ENFLG); Unnecessary !! -- i.