[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAOoeyxW7=mLCcthVcQKnf7ikxEdQ09SzmOT5puD-AuhgpRHLkQ@mail.gmail.com>
Date: Thu, 2 Jan 2025 13:25:27 +0800
From: Ming Yu <a0282524688@...il.com>
To: Vincent Mailhol <mailhol.vincent@...adoo.fr>
Cc: linux-kernel@...r.kernel.org, linux-gpio@...r.kernel.org,
linux-i2c@...r.kernel.org, linux-can@...r.kernel.org, netdev@...r.kernel.org,
linux-watchdog@...r.kernel.org, linux-hwmon@...r.kernel.org,
linux-rtc@...r.kernel.org, tmyu0@...oton.com, lee@...nel.org,
linus.walleij@...aro.org, brgl@...ev.pl, andi.shyti@...nel.org,
mkl@...gutronix.de, andrew+netdev@...n.ch, davem@...emloft.net,
edumazet@...gle.com, kuba@...nel.org, pabeni@...hat.com,
wim@...ux-watchdog.org, linux@...ck-us.net, jdelvare@...e.com,
alexandre.belloni@...tlin.com
Subject: Re: [PATCH v4 4/7] can: Add Nuvoton NCT6694 CAN support
Dear Vincent,
Thank you for your comments,
Vincent Mailhol <mailhol.vincent@...adoo.fr> 於 2024年12月27日 週五 下午11:59寫道:
>
> > +
> > +struct __packed nct6694_can_event_channel {
> > + u8 err;
> > + u8 status;
> > + u8 tx_evt;
> > + u8 rx_evt;
> > + u8 rec;
> > + u8 tec;
> > + u8 reserved[2];
> > +};
> > +
> > +struct __packed nct6694_can_event {
> > + struct nct6694_can_event_channel evt_ch[2];
> > +};
>
> Remove this intermediate struct...
>
> > +struct __packed nct6694_can_frame {
> > + u8 tag;
> > + u8 flag;
> > + u8 reserved;
> > + u8 length;
> > + __le32 id;
> > + u8 data[64];
> > +};
> > +
> > +union nct6694_can_tx {
> > + struct nct6694_can_frame frame;
> > + struct nct6694_can_setting setting;
> > +};
> > +
> > +union nct6694_can_rx {
> > + struct nct6694_can_event event;
>
> ... and instead, dircectly declare the array here:
>
> struct nct6694_can_event event[2];
>
Okay! Fix it in v5.
> > + struct nct6694_can_frame frame;
> > + struct nct6694_can_information info;
> > +};
> > +
> > +struct nct6694_can_priv {
> > + struct can_priv can; /* must be the first member */
> > + struct can_rx_offload offload;
> > + struct net_device *ndev;
> > + struct nct6694 *nct6694;
> > + struct mutex lock;
> > + struct sk_buff *tx_skb;
> > + struct workqueue_struct *wq;
> > + struct work_struct tx_work;
> > + union nct6694_can_tx *tx;
> > + union nct6694_can_rx *rx;
> > + unsigned char can_idx;
> > + bool tx_busy;
>
> tx_busy is only set when the network queue is stopped, right? Isn't it
> possible to use netif_tx_queue_stopped() instead of tx_busy?
>
Yes, I'll make the modification in v5.
> > +};
> > +
...
> > +static void nct6694_can_handle_state_change(struct net_device *ndev,
> > + u8 status)
> > +{
> > + struct nct6694_can_priv *priv = netdev_priv(ndev);
> > + enum can_state new_state = priv->can.state;
> > + enum can_state rx_state, tx_state;
> > + struct can_berr_counter bec;
> > + struct can_frame *cf;
> > + struct sk_buff *skb;
> > +
> > + nct6694_can_get_berr_counter(ndev, &bec);
> > + can_state_get_by_berr_counter(ndev, &bec, &tx_state, &rx_state);
> > +
> > + if (status & NCT6694_CAN_EVT_STS_BUS_OFF)
> > + new_state = CAN_STATE_BUS_OFF;
> > + else if (status & NCT6694_CAN_EVT_STS_ERROR_PASSIVE)
> > + new_state = CAN_STATE_ERROR_PASSIVE;
> > + else if (status & NCT6694_CAN_EVT_STS_WARNING)
> > + new_state = CAN_STATE_ERROR_WARNING;
The procedure for handling state changes is incorrect. I'll fix it in
the next patch.
(e.g.)
switch (status) {
case NCT6694_CAN_EVT_STS_BUS_OFF):
new_state = CAN_STATE_BUS_OFFF;
break;
...
}
> > +
> > + /* state hasn't changed */
> > + if (new_state == priv->can.state)
> > + return;
> > +
> > + skb = alloc_can_err_skb(ndev, &cf);
> > +
> > + tx_state = bec.txerr >= bec.rxerr ? new_state : 0;
> > + rx_state = bec.txerr <= bec.rxerr ? new_state : 0;
> > + can_change_state(ndev, cf, tx_state, rx_state);
> > +
> > + if (new_state == CAN_STATE_BUS_OFF) {
> > + can_bus_off(ndev);
> > + } else if (skb) {
> > + cf->can_id |= CAN_ERR_CNT;
> > + cf->data[6] = bec.txerr;
> > + cf->data[7] = bec.rxerr;
> > + }
> > +
> > + nct6694_can_rx_offload(&priv->offload, skb);
> > +}
> > +
> > +static void nct6694_handle_bus_err(struct net_device *ndev, u8 bus_err)
> > +{
> > + struct nct6694_can_priv *priv = netdev_priv(ndev);
> > + struct can_frame *cf;
> > + struct sk_buff *skb;
> > +
> > + if (bus_err == NCT6694_CAN_EVT_ERR_NO_ERROR)
> > + return;
> > +
> > + priv->can.can_stats.bus_error++;
> > +
> > + skb = alloc_can_err_skb(ndev, &cf);
> > + if (skb)
> > + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> > +
> > + switch (bus_err) {
> > + case NCT6694_CAN_EVT_ERR_CRC_ERROR:
> > + netdev_dbg(ndev, "CRC error\n");
> > + ndev->stats.rx_errors++;
> > + if (skb)
> > + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
> > + break;
> > +
> > + case NCT6694_CAN_EVT_ERR_STUFF_ERROR:
> > + netdev_dbg(ndev, "Stuff error\n");
> > + ndev->stats.rx_errors++;
> > + if (skb)
> > + cf->data[2] |= CAN_ERR_PROT_STUFF;
> > + break;
> > +
> > + case NCT6694_CAN_EVT_ERR_ACK_ERROR:
> > + netdev_dbg(ndev, "Ack error\n");
> > + ndev->stats.tx_errors++;
> > + if (skb) {
> > + cf->can_id |= CAN_ERR_ACK;
> > + cf->data[2] |= CAN_ERR_PROT_TX;
> > + }
> > + break;
> > +
> > + case NCT6694_CAN_EVT_ERR_FORM_ERROR:
> > + netdev_dbg(ndev, "Form error\n");
> > + ndev->stats.rx_errors++;
> > + if (skb)
> > + cf->data[2] |= CAN_ERR_PROT_FORM;
> > + break;
> > +
> > + case NCT6694_CAN_EVT_ERR_BIT_ERROR:
> > + netdev_dbg(ndev, "Bit error\n");
> > + ndev->stats.tx_errors++;
> > + if (skb)
> > + cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT;
> > + break;
> > +
> > + default:
> > + break;
> > + }
>
> Aren't you missing something here? You are populating a can frame but
> you are returning without using it.
>
Sorry for forgetting to process rx offload function, I'll add
nct6694_can_rx_offload() here in the v5.
> > +}
> > +
...
> > +static void nct6694_can_tx(struct net_device *ndev)
> > +{
> > + struct nct6694_can_priv *priv = netdev_priv(ndev);
> > + struct nct6694_can_frame *frame = &priv->tx->frame;
> > + struct net_device_stats *stats = &ndev->stats;
> > + struct sk_buff *skb = priv->tx_skb;
> > + struct canfd_frame *cfd;
> > + struct can_frame *cf;
> > + u32 txid;
> > + int err;
> > +
> > + memset(frame, 0, sizeof(*frame));
> > +
> > + if (priv->can_idx == 0)
> > + frame->tag = NCT6694_CAN_FRAME_TAG_CAN0;
> > + else
> > + frame->tag = NCT6694_CAN_FRAME_TAG_CAN1;
> > +
> > + if (can_is_canfd_skb(skb)) {
> > + cfd = (struct canfd_frame *)priv->tx_skb->data;
> > +
> > + if (cfd->flags & CANFD_BRS)
> > + frame->flag |= NCT6694_CAN_FRAME_FLAG_BRS;
> > +
> > + if (cfd->can_id & CAN_EFF_FLAG) {
> > + txid = cfd->can_id & CAN_EFF_MASK;
> > + frame->flag |= NCT6694_CAN_FRAME_FLAG_EFF;
> > + } else {
> > + txid = cfd->can_id & CAN_SFF_MASK;
> > + }
> > + frame->flag |= NCT6694_CAN_FRAME_FLAG_FD;
> > + frame->id = cpu_to_le32(txid);
> > + frame->length = cfd->len;
> > +
> > + memcpy(frame->data, cfd->data, cfd->len);
> > + } else {
> > + cf = (struct can_frame *)priv->tx_skb->data;
> > +
> > + if (cf->can_id & CAN_RTR_FLAG)
> > + frame->flag |= NCT6694_CAN_FRAME_FLAG_RTR;
> > +
> > + if (cf->can_id & CAN_EFF_FLAG) {
> > + txid = cf->can_id & CAN_EFF_MASK;
> > + frame->flag |= NCT6694_CAN_FRAME_FLAG_EFF;
> > + } else {
> > + txid = cf->can_id & CAN_SFF_MASK;
> > + }
> > + frame->id = cpu_to_le32(txid);
> > + frame->length = cf->len;
> > +
> > + memcpy(frame->data, cf->data, cf->len);
>
> Don't copy the payload if the frame is a remote frame.
>
Fix it in the v5.
> > + }
> ^^^^^^^^
>
> Bad indentation. Did you run script/checkpatch.pl before sending?
>
I already ran the script, but I'm not sure why it didn't report this error.
I'll fix it in the next patch.
> > + err = nct6694_write_msg(priv->nct6694, NCT6694_CAN_MOD,
> > + NCT6694_CAN_DELIVER(1),
> > + sizeof(*frame),
> > + frame);
> > + if (err) {
> > + netdev_err(ndev, "%s: Tx FIFO full!\n", __func__);
> > + can_free_echo_skb(ndev, 0, NULL);
> > + stats->tx_dropped++;
> > + stats->tx_errors++;
> > + netif_wake_queue(ndev);
> > + }
> > +}
> > +
...
> > +static int nct6694_can_set_mode(struct net_device *ndev, enum can_mode mode)
> > +{
> > + switch (mode) {
> > + case CAN_MODE_START:
> > + nct6694_can_clean(ndev);
> > + nct6694_can_start(ndev);
> > + netif_wake_queue(ndev);
> > + break;
>
> Nitpick: here, directly return 0...
>
> > + default:
> > + return -EOPNOTSUPP;
> > + }
> > +
> > + return 0;
>
> ... and then remove that line.
>
Fix it in v5.
> > +}
> > +
Best regards,
Ming
Powered by blists - more mailing lists