All of lore.kernel.org
 help / color / mirror / Atom feed
From: Akshay Bhat <akshay.bhat-jEh4hwF5bVhBDgjK7y7TUQ@public.gmane.org>
To: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>,
	mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org
Cc: linux-can-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Akshay Bhat <nodeax-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: Re: [PATCH v2 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver
Date: Mon, 13 Mar 2017 11:38:12 -0400	[thread overview]
Message-ID: <b3ebb569-b50c-39ad-dec5-0059fbfba8fb@timesys.com> (raw)
In-Reply-To: <234d9e75-0083-b8b4-c781-add653fdb550-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

Hi Wolfgang,

On 03/09/2017 12:36 PM, Wolfgang Grandegger wrote:
> Hello,
> 
> doing a quick review... I realized a few issues...
> 
> Am 17.01.2017 um 20:22 schrieb Akshay Bhat:
>> +static u8 hi3110_read(struct spi_device *spi, u8 command)
>> +{
>> +    struct hi3110_priv *priv = spi_get_drvdata(spi);
>> +    u8 val = 0;
>> +
>> +    priv->spi_tx_buf[0] = command;
>> +    hi3110_spi_trans(spi, 2);
>> +    val = priv->spi_rx_buf[1];
>> +    dev_dbg(&spi->dev, "hi3110_read: %02X, %02X\n", command, val);
> 
> This produces a lot of output which is not useful for the normal user.
> 

Fixed in v3 patch.

>> +static void hi3110_write(struct spi_device *spi, u8 reg, u8 val)
>> +{
>> +    struct hi3110_priv *priv = spi_get_drvdata(spi);
>> +
>> +    priv->spi_tx_buf[0] = reg;
>> +    priv->spi_tx_buf[1] = val;
>> +    dev_dbg(&spi->dev, "hi3110_write: %02X, %02X\n", reg, val);
> 
> Ditto.
> 

Fixed in v3 patch.


>> +
>> +static void hi3110_hw_rx(struct spi_device *spi)
>> +{
>> +    struct hi3110_priv *priv = spi_get_drvdata(spi);
>> +    struct sk_buff *skb;
>> +    struct can_frame *frame;
>> +    u8 buf[HI3110_RX_BUF_LEN - 1];
>> +
>> +    skb = alloc_can_skb(priv->net, &frame);
>> +    if (!skb) {
>> +        dev_err(&spi->dev, "cannot allocate RX skb\n");
> 
> Please return silenty! Otherwise it will make the situation worse.
> 

Fixed in v3 patch.

>> +
>> +    /* Data length */
>> +    frame->can_dlc = get_can_dlc(buf[HI3110_FIFO_WOTIME_DLC_OFF] &
>> 0x0F);
>> +    memcpy(frame->data, buf + HI3110_FIFO_WOTIME_DAT_OFF,
>> frame->can_dlc);
> 
> No data bytes should not be copied for RTR messages.
> 

Fixed in v3 patch.

>> +
>> +    if (priv->tx_skb || priv->tx_len) {
>> +        dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
> 
> s/warn/err/? This should never happen; IIUC.
> 

Fixed in v3 patch.

>> +        return NETDEV_TX_BUSY;
>> +    }
>> +
>> +    if (can_dropped_invalid_skb(net, skb))
>> +        return NETDEV_TX_OK;
>> +
>> +    netif_stop_queue(net);
> 
> The driver transfers the packets in sequence. Any chance to queue them?
> At least there is a TX FIFO for 8 messages. That's bad for RT but would
> increase the throughput.
> 

I initially did not use the TX FIFO for the reason you mentioned above.
Queuing should be possible but since it requires lot more additional
logic, I can work on it a later time.


>> +
>> +    if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
>> +        /* Put device into loopback mode */
>> +        hi3110_write(spi, HI3110_WRITE_CTRL0,
>> +                 HI3110_CTRL0_LOOPBACK_MODE);
>> +    } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
>> +        /* Put device into listen-only mode */
>> +        hi3110_write(spi, HI3110_WRITE_CTRL0,
>> +                 HI3110_CTRL0_MONITOR_MODE);
>> +    } else {
>> +        /* Put device into normal mode */
>> +        hi3110_write(spi, HI3110_WRITE_CTRL0,
>> +                 HI3110_CTRL0_NORMAL_MODE);
> 
> "mode = x" and just one write is more compact.
> 

Fixed in v3 patch.

>> +
>> +        /* Wait for the device to enter normal mode */
>> +        mdelay(HI3110_OST_DELAY_MS);
>> +        reg = hi3110_read(spi, HI3110_READ_CTRL0);
>> +        if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_NORMAL_MODE)
>> +            return -EBUSY;
> 
> Is this not necesary for listen or loopbcak only mode?
> 

It is necessary, fixed in v3 patch.

>> +
>> +static void hi3110_error_skb(struct net_device *net, int can_id,
>> +                 int data1, int data2)
>> +{
>> +    struct sk_buff *skb;
>> +    struct can_frame *frame;
>> +
>> +    skb = alloc_can_err_skb(net, &frame);
>> +    if (skb) {
>> +        frame->can_id |= can_id;
>> +        frame->data[1] = data1;
>> +        frame->data[2] = data2;
>> +        netif_rx_ni(skb);
>> +    } else {
>> +        netdev_err(net, "cannot allocate error skb\n");
> 
> Please remove the error message. Not a good at low memory situations.
> 

Fixed in v3 patch.

>> +        /* Check for protocol errors */
>> +        if (eflag & HI3110_ERR_PROTOCOL_MASK) {
>> +            can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
>> +            priv->can.can_stats.bus_error++;
>> +            priv->net->stats.rx_errors++;
>> +            if (eflag & HI3110_ERR_BITERR)
>> +                data2 |= CAN_ERR_PROT_BIT;
>> +            else if (eflag & HI3110_ERR_FRMERR)
>> +                data2 |= CAN_ERR_PROT_FORM;
>> +            else if (eflag & HI3110_ERR_STUFERR)
>> +                data2 |= CAN_ERR_PROT_STUFF;
>> +            else
>> +                data2 |= CAN_ERR_PROT_UNSPEC;
> 
> And what about the ACK and CRC error defines at the beginning?
> It's also comon to use netdev_dbg() on error interrupts.
> 

Good catch, I missed it. Fixed in v3 patch.

>> +        }
> 
> Bus error reporting can flood the system with interrupts. Any chance to
> implement CAN_CTRLMODE_BERR_REPORTING. I think the bus error interrupt
> can be enabled/disabled.
> 

Thanks, was not aware of this feature. Added it in v3 patch.

>> +        /* Update can state statistics */
>> +        switch (priv->can.state) {
>> +        case CAN_STATE_ERROR_ACTIVE:
>> +            if (new_state >= CAN_STATE_ERROR_WARNING &&
>> +                new_state <= CAN_STATE_BUS_OFF)
>> +                priv->can.can_stats.error_warning++;
>> +        /* fallthrough */
>> +        case CAN_STATE_ERROR_WARNING:
>> +            if (new_state >= CAN_STATE_ERROR_PASSIVE &&
>> +                new_state <= CAN_STATE_BUS_OFF)
>> +                priv->can.can_stats.error_passive++;
>> +            break;
>> +        default:
>> +            break;
>> +        }
>> +        priv->can.state = new_state;
>> +
>> +        if (intf & HI3110_INT_BUSERR) {
>> +            /* Note: HI3110 Does report overflow errors */
>> +            hi3110_error_skb(net, can_id, data1, data2);
>> +        }
> 
> Usually the bus error counts are filled in the error message frame as
> well. It the counts are available, I would also be nice to have the
> "do_get_berr_counter" callback as well.
> 

Added it in v3 patch.

>> +static int hi3110_open(struct net_device *net)
>> +{
>> +    struct hi3110_priv *priv = netdev_priv(net);
>> +    struct spi_device *spi = priv->spi;
>> +    unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
>> +    int ret;
>> +
>> +    ret = open_candev(net);
>> +    if (ret) {
>> +        dev_err(&spi->dev, "unable to set initial baudrate!\n");
> 
> open_candev() does already print an error message.
>

Fixed in v3 patch.


> A few other things to check:
> 
> Run "cangen" and monitor the message with "candump -e any,0:0,#FFFFFFF".
> Then 1) disconnect the cable or 2) short-circuit CAN low and high at the
> connector. You should see error messages. After reconnection or removing
> the short-circuit (and bus-off recovery) the state should go back to
> "active".
>

With the above sequence, candump reports "ERRORFRAME" with
protocol-violation{{}{acknowledge-slot}}, bus-error. On re-connecting
the cable the can state goes back to ACTIVE and I see the messages that
were in the queue being sent.

> Run "canfdtest" to check for out-of-order messages. I do not expect
> problems with your driver, though.
>

Ran canfdtest for 100k loop (@1M can bit rate), did not see any issues.

Thanks for your valuable suggests and tests :)
Akshay.

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

WARNING: multiple messages have this Message-ID (diff)
From: Akshay Bhat <akshay.bhat@timesys.com>
To: Wolfgang Grandegger <wg@grandegger.com>, mkl@pengutronix.de
Cc: linux-can@vger.kernel.org, netdev@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Akshay Bhat <nodeax@gmail.com>
Subject: Re: [PATCH v2 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver
Date: Mon, 13 Mar 2017 11:38:12 -0400	[thread overview]
Message-ID: <b3ebb569-b50c-39ad-dec5-0059fbfba8fb@timesys.com> (raw)
In-Reply-To: <234d9e75-0083-b8b4-c781-add653fdb550@grandegger.com>

Hi Wolfgang,

On 03/09/2017 12:36 PM, Wolfgang Grandegger wrote:
> Hello,
> 
> doing a quick review... I realized a few issues...
> 
> Am 17.01.2017 um 20:22 schrieb Akshay Bhat:
>> +static u8 hi3110_read(struct spi_device *spi, u8 command)
>> +{
>> +    struct hi3110_priv *priv = spi_get_drvdata(spi);
>> +    u8 val = 0;
>> +
>> +    priv->spi_tx_buf[0] = command;
>> +    hi3110_spi_trans(spi, 2);
>> +    val = priv->spi_rx_buf[1];
>> +    dev_dbg(&spi->dev, "hi3110_read: %02X, %02X\n", command, val);
> 
> This produces a lot of output which is not useful for the normal user.
> 

Fixed in v3 patch.

>> +static void hi3110_write(struct spi_device *spi, u8 reg, u8 val)
>> +{
>> +    struct hi3110_priv *priv = spi_get_drvdata(spi);
>> +
>> +    priv->spi_tx_buf[0] = reg;
>> +    priv->spi_tx_buf[1] = val;
>> +    dev_dbg(&spi->dev, "hi3110_write: %02X, %02X\n", reg, val);
> 
> Ditto.
> 

Fixed in v3 patch.


>> +
>> +static void hi3110_hw_rx(struct spi_device *spi)
>> +{
>> +    struct hi3110_priv *priv = spi_get_drvdata(spi);
>> +    struct sk_buff *skb;
>> +    struct can_frame *frame;
>> +    u8 buf[HI3110_RX_BUF_LEN - 1];
>> +
>> +    skb = alloc_can_skb(priv->net, &frame);
>> +    if (!skb) {
>> +        dev_err(&spi->dev, "cannot allocate RX skb\n");
> 
> Please return silenty! Otherwise it will make the situation worse.
> 

Fixed in v3 patch.

>> +
>> +    /* Data length */
>> +    frame->can_dlc = get_can_dlc(buf[HI3110_FIFO_WOTIME_DLC_OFF] &
>> 0x0F);
>> +    memcpy(frame->data, buf + HI3110_FIFO_WOTIME_DAT_OFF,
>> frame->can_dlc);
> 
> No data bytes should not be copied for RTR messages.
> 

Fixed in v3 patch.

>> +
>> +    if (priv->tx_skb || priv->tx_len) {
>> +        dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
> 
> s/warn/err/? This should never happen; IIUC.
> 

Fixed in v3 patch.

>> +        return NETDEV_TX_BUSY;
>> +    }
>> +
>> +    if (can_dropped_invalid_skb(net, skb))
>> +        return NETDEV_TX_OK;
>> +
>> +    netif_stop_queue(net);
> 
> The driver transfers the packets in sequence. Any chance to queue them?
> At least there is a TX FIFO for 8 messages. That's bad for RT but would
> increase the throughput.
> 

I initially did not use the TX FIFO for the reason you mentioned above.
Queuing should be possible but since it requires lot more additional
logic, I can work on it a later time.


>> +
>> +    if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
>> +        /* Put device into loopback mode */
>> +        hi3110_write(spi, HI3110_WRITE_CTRL0,
>> +                 HI3110_CTRL0_LOOPBACK_MODE);
>> +    } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
>> +        /* Put device into listen-only mode */
>> +        hi3110_write(spi, HI3110_WRITE_CTRL0,
>> +                 HI3110_CTRL0_MONITOR_MODE);
>> +    } else {
>> +        /* Put device into normal mode */
>> +        hi3110_write(spi, HI3110_WRITE_CTRL0,
>> +                 HI3110_CTRL0_NORMAL_MODE);
> 
> "mode = x" and just one write is more compact.
> 

Fixed in v3 patch.

>> +
>> +        /* Wait for the device to enter normal mode */
>> +        mdelay(HI3110_OST_DELAY_MS);
>> +        reg = hi3110_read(spi, HI3110_READ_CTRL0);
>> +        if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_NORMAL_MODE)
>> +            return -EBUSY;
> 
> Is this not necesary for listen or loopbcak only mode?
> 

It is necessary, fixed in v3 patch.

>> +
>> +static void hi3110_error_skb(struct net_device *net, int can_id,
>> +                 int data1, int data2)
>> +{
>> +    struct sk_buff *skb;
>> +    struct can_frame *frame;
>> +
>> +    skb = alloc_can_err_skb(net, &frame);
>> +    if (skb) {
>> +        frame->can_id |= can_id;
>> +        frame->data[1] = data1;
>> +        frame->data[2] = data2;
>> +        netif_rx_ni(skb);
>> +    } else {
>> +        netdev_err(net, "cannot allocate error skb\n");
> 
> Please remove the error message. Not a good at low memory situations.
> 

Fixed in v3 patch.

>> +        /* Check for protocol errors */
>> +        if (eflag & HI3110_ERR_PROTOCOL_MASK) {
>> +            can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
>> +            priv->can.can_stats.bus_error++;
>> +            priv->net->stats.rx_errors++;
>> +            if (eflag & HI3110_ERR_BITERR)
>> +                data2 |= CAN_ERR_PROT_BIT;
>> +            else if (eflag & HI3110_ERR_FRMERR)
>> +                data2 |= CAN_ERR_PROT_FORM;
>> +            else if (eflag & HI3110_ERR_STUFERR)
>> +                data2 |= CAN_ERR_PROT_STUFF;
>> +            else
>> +                data2 |= CAN_ERR_PROT_UNSPEC;
> 
> And what about the ACK and CRC error defines at the beginning?
> It's also comon to use netdev_dbg() on error interrupts.
> 

Good catch, I missed it. Fixed in v3 patch.

>> +        }
> 
> Bus error reporting can flood the system with interrupts. Any chance to
> implement CAN_CTRLMODE_BERR_REPORTING. I think the bus error interrupt
> can be enabled/disabled.
> 

Thanks, was not aware of this feature. Added it in v3 patch.

>> +        /* Update can state statistics */
>> +        switch (priv->can.state) {
>> +        case CAN_STATE_ERROR_ACTIVE:
>> +            if (new_state >= CAN_STATE_ERROR_WARNING &&
>> +                new_state <= CAN_STATE_BUS_OFF)
>> +                priv->can.can_stats.error_warning++;
>> +        /* fallthrough */
>> +        case CAN_STATE_ERROR_WARNING:
>> +            if (new_state >= CAN_STATE_ERROR_PASSIVE &&
>> +                new_state <= CAN_STATE_BUS_OFF)
>> +                priv->can.can_stats.error_passive++;
>> +            break;
>> +        default:
>> +            break;
>> +        }
>> +        priv->can.state = new_state;
>> +
>> +        if (intf & HI3110_INT_BUSERR) {
>> +            /* Note: HI3110 Does report overflow errors */
>> +            hi3110_error_skb(net, can_id, data1, data2);
>> +        }
> 
> Usually the bus error counts are filled in the error message frame as
> well. It the counts are available, I would also be nice to have the
> "do_get_berr_counter" callback as well.
> 

Added it in v3 patch.

>> +static int hi3110_open(struct net_device *net)
>> +{
>> +    struct hi3110_priv *priv = netdev_priv(net);
>> +    struct spi_device *spi = priv->spi;
>> +    unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
>> +    int ret;
>> +
>> +    ret = open_candev(net);
>> +    if (ret) {
>> +        dev_err(&spi->dev, "unable to set initial baudrate!\n");
> 
> open_candev() does already print an error message.
>

Fixed in v3 patch.


> A few other things to check:
> 
> Run "cangen" and monitor the message with "candump -e any,0:0,#FFFFFFF".
> Then 1) disconnect the cable or 2) short-circuit CAN low and high at the
> connector. You should see error messages. After reconnection or removing
> the short-circuit (and bus-off recovery) the state should go back to
> "active".
>

With the above sequence, candump reports "ERRORFRAME" with
protocol-violation{{}{acknowledge-slot}}, bus-error. On re-connecting
the cable the can state goes back to ACTIVE and I see the messages that
were in the queue being sent.

> Run "canfdtest" to check for out-of-order messages. I do not expect
> problems with your driver, though.
>

Ran canfdtest for 100k loop (@1M can bit rate), did not see any issues.

Thanks for your valuable suggests and tests :)
Akshay.

  parent reply	other threads:[~2017-03-13 15:38 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-17 19:22 [PATCH v2 1/2] can: holt_hi311x: document device tree bindings Akshay Bhat
2017-01-17 19:22 ` [PATCH v2 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver Akshay Bhat
2017-03-07 15:31   ` Akshay Bhat
2017-03-09  9:59     ` Wolfgang Grandegger
     [not found]       ` <6df4a9ae-eaba-6f3f-9c23-ae269548b005-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2017-03-09 12:34         ` Akshay Bhat
2017-03-09 12:34           ` Akshay Bhat
2017-03-09 14:45           ` Wolfgang Grandegger
2017-03-09 15:28             ` Akshay Bhat
2017-03-09 17:36   ` Wolfgang Grandegger
     [not found]     ` <234d9e75-0083-b8b4-c781-add653fdb550-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2017-03-13 15:38       ` Akshay Bhat [this message]
2017-03-13 15:38         ` Akshay Bhat
     [not found]         ` <b3ebb569-b50c-39ad-dec5-0059fbfba8fb-jEh4hwF5bVhBDgjK7y7TUQ@public.gmane.org>
2017-03-14 12:11           ` Wolfgang Grandegger
2017-03-14 12:11             ` Wolfgang Grandegger
2017-03-14 16:20             ` Akshay Bhat
2017-03-14 18:08               ` Wolfgang Grandegger
2017-03-14 21:23                 ` Wolfgang Grandegger
     [not found]                 ` <41439729-42d0-d883-2801-2d3607f2aeab-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2017-03-15  4:44                   ` Akshay Bhat
2017-03-15  4:44                     ` Akshay Bhat
2017-03-15  7:19                     ` Wolfgang Grandegger
2017-03-15  9:42                     ` Wolfgang Grandegger
     [not found]                       ` <3dba0948-ffcb-8e80-fb32-62bb0aca6627-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2017-03-16 17:06                         ` Akshay Bhat
2017-03-16 17:06                           ` Akshay Bhat
2017-03-16 20:02                           ` Wolfgang Grandegger
2017-03-16 22:29                             ` Akshay Bhat
2017-03-17  7:39                               ` Wolfgang Grandegger
2017-03-17  8:17                                 ` Wolfgang Grandegger
2017-03-17 16:00                                 ` Akshay Bhat
2017-03-17 17:04                                   ` Wolfgang Grandegger
     [not found]                                     ` <7730cff6-6e85-c98d-0315-bd3888d3aeb1-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2017-03-17 18:28                                       ` Akshay Bhat
2017-03-17 18:28                                         ` Akshay Bhat
     [not found]                                         ` <ff5d44d1-3bfe-8dae-2aaa-561ab0cb989c-jEh4hwF5bVhBDgjK7y7TUQ@public.gmane.org>
2017-03-18 12:30                                           ` Wolfgang Grandegger
2017-03-18 12:30                                             ` Wolfgang Grandegger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b3ebb569-b50c-39ad-dec5-0059fbfba8fb@timesys.com \
    --to=akshay.bhat-jeh4hwf5bvhbdgjk7y7tuq@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-can-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
    --cc=netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=nodeax-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.