lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHNKnsTUSfieWKuw5WOFPidezoVWDKkLqQV6xnDs560QAGXiCQ@mail.gmail.com>
Date:   Mon, 7 Mar 2022 05:55:15 +0300
From:   Sergey Ryazanov <ryazanov.s.a@...il.com>
To:     Ricardo Martinez <ricardo.martinez@...ux.intel.com>
Cc:     netdev@...r.kernel.org, linux-wireless@...r.kernel.org,
        Jakub Kicinski <kuba@...nel.org>,
        David Miller <davem@...emloft.net>,
        Johannes Berg <johannes@...solutions.net>,
        Loic Poulain <loic.poulain@...aro.org>,
        M Chetan Kumar <m.chetan.kumar@...el.com>,
        chandrashekar.devegowda@...el.com,
        Intel Corporation <linuxwwan@...el.com>,
        chiranjeevi.rapolu@...ux.intel.com,
        Haijun Liu (刘海军) 
        <haijun.liu@...iatek.com>, amir.hanania@...el.com,
        Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
        dinesh.sharma@...el.com, eliot.lee@...el.com,
        ilpo.johannes.jarvinen@...el.com, moises.veleta@...el.com,
        pierre-louis.bossart@...el.com, muralidharan.sethuraman@...el.com,
        Soumya.Prakash.Mishra@...el.com, sreehari.kancharla@...el.com,
        madhusmita.sahu@...el.com
Subject: Re: [PATCH net-next v5 05/13] net: wwan: t7xx: Add control port

On Thu, Feb 24, 2022 at 1:35 AM Ricardo Martinez
<ricardo.martinez@...ux.intel.com> wrote:
> From: Haijun Liu <haijun.liu@...iatek.com>
>
> 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.

[skipped]

> +struct feature_query {
> +       __le32 head_pattern;
> +       u8 feature_set[FEATURE_COUNT];
> +       __le32 tail_pattern;
> +};
> +
> +static void t7xx_prepare_host_rt_data_query(struct t7xx_sys_info *core)
> +{
> +       struct t7xx_port_static *port_static = core->ctl_port->port_static;
> +       struct ctrl_msg_header *ctrl_msg_h;
> +       struct feature_query *ft_query;
> +       struct ccci_header *ccci_h;
> +       struct sk_buff *skb;
> +       size_t packet_size;
> +
> +       packet_size = sizeof(*ccci_h) + sizeof(*ctrl_msg_h) + sizeof(*ft_query);
> +       skb = __dev_alloc_skb(packet_size, GFP_KERNEL);
> +       if (!skb)
> +               return;
> +
> +       skb_put(skb, packet_size);
> +
> +       ccci_h = (struct ccci_header *)skb->data;
> +       t7xx_ccci_header_init(ccci_h, 0, packet_size, port_static->tx_ch, 0);
> +       ccci_h->status &= cpu_to_le32(~CCCI_H_SEQ_FLD);
> +
> +       ctrl_msg_h = (struct ctrl_msg_header *)(skb->data + sizeof(*ccci_h));
> +       t7xx_ctrl_msg_header_init(ctrl_msg_h, CTL_ID_HS1_MSG, 0, sizeof(*ft_query));
> +
> +       ft_query = (struct feature_query *)(skb->data + sizeof(*ccci_h) + sizeof(*ctrl_msg_h));
> +       ft_query->head_pattern = cpu_to_le32(MD_FEATURE_QUERY_ID);
> +       memcpy(ft_query->feature_set, core->feature_set, FEATURE_COUNT);
> +       ft_query->tail_pattern = cpu_to_le32(MD_FEATURE_QUERY_ID);
> +
> +       /* Send HS1 message to device */
> +       t7xx_port_proxy_send_skb(core->ctl_port, skb);
> +}

I do not care too much, but this code and many other places could be
greatly simplified. It looks like the modem communication protocol has
a layered design, skb and its API are also designed to handle layered
protocols. It just needs to rearrange the code a bit.

For example, to avoid manual accounting of each header in the stack,
skb allocation can be implemented using a stack of allocation
functions:

struct sk_buff *t7xx_port_alloc_skb(int payload)
{
    struct sk_buff *skb = alloc_skb(payload + sizeof(struct ccci_header), ...);
    if (skb)
        skb_reserve(skb, sizeof(struct ccci_header));
    return skb;
}

struct sk_buff *t7xx_ctrl_alloc_skb(int payload)
{
    struct sk_buff *skb = t7xx_port_alloc_skb(payload + sizeof(struct
ctlr_msg_header), ...);
    if (skb)
        skb_reserve(skb, sizeof(struct ctrl_msg_header));
    return skb;
}

Message sending operation can also be perfectly stacked:

int t7xx_port_proxy_send_skb(*port, *skb)
{
    struct ccci_header *ccci_h = skb_push(skb, sizeof(*ccci_h));
    /* Build CCCI header (including seqno assignment) */
    ccci_h->packet_len = cpu_to_le32(skb->len);
    res = cldma_send_skb(..., skb, ...);
    if (res)
        return res;
    /* Update seqno counter here */
    return 0;
}

int t7xx_ctrl_send_msg(port, msg_id, skb)
{
    int len = skb->len; /* Preserve payload len */
    struct ctrl_msg_header *ctrl_msg_h = skb_push(skb, sizeof(*ctrl_msg_h));
    /* Build ctrl msg header here */
    ctrl_msg_h->data_length = cpu_to_le32(len);
    return t7xx_port_proxy_send_skb(port, skb);
}

So the above features request becomes as simple as:

void t7xx_prepare_host_rt_data_query(struct t7xx_sys_info *core)
{
    struct feature_query *ft_query;
    struct sk_buff *skb;

    skb = t7xx_ctrl_alloc_skb(sizeof(*ft_query));
    if (!skb)
        return;
    ft_query = skb_put(skb, sizeof(*ft_query));
    /* Build features request here */
    if (t7xx_ctrl_send_msg(core->ctl_port, CTL_ID_HS1_MSG, skb))
        kfree_skb(skb);
}

Once the allocation and sending functions are implemented in a stacked
way, many other places can be simplified in a similar way.

[skipped]

> +static void t7xx_core_hk_handler(struct t7xx_modem *md, struct t7xx_fsm_ctl *ctl,
> +                                enum t7xx_fsm_event_state event_id,
> +                                enum t7xx_fsm_event_state err_detect)
> +{
> +       struct t7xx_sys_info *core_info = &md->core_md;
> +       struct device *dev = &md->t7xx_dev->pdev->dev;
> +       struct t7xx_fsm_event *event, *event_next;
> +       unsigned long flags;
> +       void *event_data;
> +       int ret;
> +
> +       t7xx_prepare_host_rt_data_query(core_info);
> +
> +       while (!kthread_should_stop()) {
> +               bool event_received = false;
> +
> +               spin_lock_irqsave(&ctl->event_lock, flags);
> +               list_for_each_entry_safe(event, event_next, &ctl->event_queue, entry) {
> +                       if (event->event_id == err_detect) {
> +                               list_del(&event->entry);
> +                               spin_unlock_irqrestore(&ctl->event_lock, flags);
> +                               dev_err(dev, "Core handshake error event received\n");
> +                               goto err_free_event;
> +                       } else if (event->event_id == event_id) {
> +                               list_del(&event->entry);
> +                               event_received = true;
> +                               break;
> +                       }
> +               }
> +               spin_unlock_irqrestore(&ctl->event_lock, flags);
> +
> +               if (event_received)
> +                       break;
> +
> +               wait_event_interruptible(ctl->event_wq, !list_empty(&ctl->event_queue) ||
> +                                        kthread_should_stop());
> +               if (kthread_should_stop())
> +                       goto err_free_event;
> +       }
> +
> +       if (ctl->exp_flg)
> +               goto err_free_event;
> +
> +       event_data = (void *)event + sizeof(*event);

In the V2, the event structure has a data field. But then it was
dropped and now the attached data offset is manually calculated. Why
did you do this, why event->data is not suitable here?

> +       ret = t7xx_parse_host_rt_data(ctl, core_info, dev, event_data, event->length);
> +       if (ret) {
> +               dev_err(dev, "Host failure parsing runtime data: %d\n", ret);
> +               goto err_free_event;
> +       }
> +
> +       if (ctl->exp_flg)
> +               goto err_free_event;
> +
> +       ret = t7xx_prepare_device_rt_data(core_info, dev, event_data, event->length);
> +       if (ret) {
> +               dev_err(dev, "Device failure parsing runtime data: %d", ret);
> +               goto err_free_event;
> +       }
> +
> +       core_info->ready = true;
> +       core_info->handshake_ongoing = false;
> +       wake_up(&ctl->async_hk_wq);
> +err_free_event:
> +       kfree(event);
> +}

[skipped]

> +static int port_ctl_init(struct t7xx_port *port)
> +{
> +       struct t7xx_port_static *port_static = port->port_static;
> +
> +       port->skb_handler = &control_msg_handler;

& is not necessary here and only misguides readers.

> +       port->thread = kthread_run(port_ctl_rx_thread, port, "%s", port_static->name);
> +       if (IS_ERR(port->thread)) {
> +               dev_err(port->dev, "Failed to start port control thread\n");
> +               return PTR_ERR(port->thread);
> +       }
> +
> +       port->rx_length_th = CTRL_QUEUE_MAXLEN;
> +       return 0;
> +}

[skipped]

> -static struct t7xx_port_static t7xx_md_ports[1];
> +static struct t7xx_port_static t7xx_md_ports[] = {
> +       {
> +               .tx_ch = PORT_CH_CONTROL_TX,
> +               .rx_ch = PORT_CH_CONTROL_RX,
> +               .txq_index = Q_IDX_CTRL,
> +               .rxq_index = Q_IDX_CTRL,
> +               .txq_exp_index = 0,
> +               .rxq_exp_index = 0,
> +               .path_id = CLDMA_ID_MD,
> +               .flags = 0,

Zero initializer is not needed here, a static variable is filled with
zeros automatically.

> +               .ops = &ctl_port_ops,
> +               .name = "t7xx_ctrl",
> +       },
> +};

[skipped]

> +void t7xx_port_proxy_send_msg_to_md(struct port_proxy *port_prox, enum port_ch ch,
> +                                   unsigned int msg, unsigned int ex_msg)

This function is called only from the control port code and only with
ch = PORT_CH_CONTROL_TX, so I would like to recommend to move it there
and drop the ch argument.

> +{
> +       struct ctrl_msg_header *ctrl_msg_h;
> +       struct ccci_header *ccci_h;
> +       struct t7xx_port *port;
> +       struct sk_buff *skb;
> +       int ret;
> +
> +       port = t7xx_proxy_get_port_by_ch(port_prox, ch);
> +       if (!port)
> +               return;
> +
> +       skb = __dev_alloc_skb(sizeof(*ccci_h), GFP_KERNEL);
> +       if (!skb)
> +               return;
> +
> +       if (ch == PORT_CH_CONTROL_TX) {
> +               ccci_h = (struct ccci_header *)(skb->data);
> +               t7xx_ccci_header_init(ccci_h, CCCI_HEADER_NO_DATA,
> +                                     sizeof(*ctrl_msg_h) + sizeof(*ccci_h), ch, 0);
> +               ctrl_msg_h = (struct ctrl_msg_header *)(skb->data + sizeof(*ccci_h));
> +               t7xx_ctrl_msg_header_init(ctrl_msg_h, msg, ex_msg, 0);
> +               skb_put(skb, sizeof(*ccci_h) + sizeof(*ctrl_msg_h));
> +       } else {
> +               ccci_h = skb_put(skb, sizeof(*ccci_h));
> +               t7xx_ccci_header_init(ccci_h, CCCI_HEADER_NO_DATA, msg, ch, ex_msg);
> +       }
> +
> +       ret = t7xx_port_proxy_send_skb(port, skb);
> +       if (ret) {
> +               struct t7xx_port_static *port_static = port->port_static;
> +
> +               dev_kfree_skb_any(skb);
> +               dev_err(port->dev, "port%s send to MD fail\n", port_static->name);
> +       }
> +}

--
Sergey

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ