From: Andri Yngvason <andri.yngvason@marel.com>
To: Stephane Grosjean <s.grosjean@peak-system.com>,
Wolfgang Grandegger <wg@grandegger.com>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>,
"linux-can@vger.kernel.org" <linux-can@vger.kernel.org>
Subject: Re: Fwd: [PATCH v4] can/peak_usb: add support for PEAK new CANFD USB adapters
Date: Wed, 14 Jan 2015 13:00:16 +0000 [thread overview]
Message-ID: <20150114130016.26007.31476@shannon> (raw)
In-Reply-To: <54B65B9E.1000608@peak-system.com>
Quoting Stephane Grosjean (2015-01-14 12:05:50)
> Hi Wolfgang and Andri,
>
> So, Marc told me to start a discussion around the handling of the status
> information this CANFD driver is able to receive from the hardware.
> This, how to proceed next, please? FYI, everything is located in
> "pcan_usb_fd_decode_status()" below...
>
Hi Stephane,
A lot of the state-transition logic is the same between platforms, but because
everyone implements their own logic, things don't behave exactly the same way
between platforms (as they should).
See:
http://article.gmane.org/gmane.linux.can/7162
http://article.gmane.org/gmane.linux.can/7163
http://article.gmane.org/gmane.linux.can/7164
...
> +
> +/* handle uCAN status message */
> +static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if,
> + struct pucan_msg *rx_msg)
> +{
> + struct pucan_status_msg *st = (struct pucan_status_msg *)rx_msg;
> + struct peak_usb_device *dev = usb_if->dev[PUCAN_STMSG_CHANNEL(st)];
> + struct pcan_usb_fd_device *pdev =
> + container_of(dev, struct pcan_usb_fd_device, dev);
> + enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
> + struct net_device *netdev = dev->netdev;
> + struct can_frame *cf;
> + struct sk_buff *skb;
> +
> + /* nothing should be sent while in BUS_OFF state */
> + if (dev->can.state == CAN_STATE_BUS_OFF)
> + return 0;
> +
> + if (PUCAN_STMSG_BUSOFF(st)) {
> + new_state = CAN_STATE_BUS_OFF;
> + } else if (PUCAN_STMSG_PASSIVE(st)) {
> + new_state = CAN_STATE_ERROR_PASSIVE;
> + } else if (PUCAN_STMSG_WARNING(st)) {
> + new_state = CAN_STATE_ERROR_WARNING;
> + } else {
> + /* no error bit (so, no error skb, back to active state) */
> + dev->can.state = CAN_STATE_ERROR_ACTIVE;
> + pdev->tx_error_counter = 0;
> + pdev->rx_error_counter = 0;
> + return 0;
> + }
> +
> + /* donot post any error if current state didn't change */
> + if (dev->can.state == new_state)
> + return 0;
> +
> + /* allocate an skb to store the error frame */
> + skb = alloc_can_err_skb(netdev, &cf);
> + if (!skb)
> + return -ENOMEM;
> +
You can replace this:
> + switch (new_state) {
> + case CAN_STATE_BUS_OFF:
> + cf->can_id |= CAN_ERR_BUSOFF;
> + can_bus_off(netdev);
> + break;
> +
> + case CAN_STATE_ERROR_PASSIVE:
> + cf->can_id |= CAN_ERR_CRTL;
> + if (pdev->rx_error_counter > 127)
> + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> + if (pdev->tx_error_counter > 127)
> + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> +
> + dev->can.can_stats.error_passive++;
> + break;
> +
> + case CAN_STATE_ERROR_WARNING:
> + cf->can_id |= CAN_ERR_CRTL;
> + if (pdev->rx_error_counter > 96)
> + cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
> + if (pdev->tx_error_counter > 96)
> + cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
> +
> + dev->can.can_stats.error_warning++;
> + break;
> +
> + default:
> + /* default case never happens, only for warnings */
> + new_state = CAN_STATE_ERROR_ACTIVE;
> +
> + case CAN_STATE_ERROR_ACTIVE: /* fallthrough */
> + pdev->tx_error_counter = 0;
> + pdev->rx_error_counter = 0;
> + break;
> + }
> +
> + dev->can.state = new_state;
With something like this:
if(state != dev->can.state) {
tx_state = get_state_from_counter(pdev->rx_error_counter);
rx_state = get_state_from_counter(pdev->tx_error_counter);
can_change_state(dev, cf, tx_state, rx_state);
if(state == CAN_STATE_BUS_OFF)
can_bus_off(dev);
}
> +
> + peak_usb_netif_rx(skb, &usb_if->time_ref,
> + le32_to_cpu(st->ts_low), le32_to_cpu(st->ts_high));
> +
> + netdev->stats.rx_packets++;
> + netdev->stats.rx_bytes += cf->can_dlc;
> +
> + return 0;
> +}
> +
You can test the state transitions by disconnecting and connecting the can-bus
and verify that the state goes active -> warning -> passive when you disconnect
then passive -> warning -> active when you connect the bus again.
This shows how I tested my code: http://article.gmane.org/gmane.linux.can/7164
Best regards,
Andri
prev parent reply other threads:[~2015-01-14 13:00 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-06 10:00 [PATCH v4] can/peak_usb: add support for PEAK new CANFD USB adapters Stephane Grosjean
2015-01-07 17:03 ` Marc Kleine-Budde
2015-01-07 17:37 ` Oliver Hartkopp
2015-01-07 18:37 ` iproute2 fd-non-iso PoC - was " Oliver Hartkopp
2015-01-08 9:04 ` Marc Kleine-Budde
2015-01-08 9:09 ` Marc Kleine-Budde
2015-01-13 13:18 ` Stephane Grosjean
2015-01-13 13:29 ` Marc Kleine-Budde
2015-01-13 13:32 ` Marc Kleine-Budde
2015-01-14 10:50 ` Stephane Grosjean
2015-01-14 10:51 ` Marc Kleine-Budde
2015-01-14 10:56 ` Stephane Grosjean
2015-01-14 11:07 ` Marc Kleine-Budde
2015-01-14 18:55 ` Oliver Hartkopp
2015-01-14 20:57 ` Marc Kleine-Budde
2015-01-15 15:49 ` Marc Kleine-Budde
2015-01-14 12:05 ` Fwd: " Stephane Grosjean
2015-01-14 13:00 ` Andri Yngvason [this message]
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=20150114130016.26007.31476@shannon \
--to=andri.yngvason@marel.com \
--cc=linux-can@vger.kernel.org \
--cc=s.grosjean@peak-system.com \
--cc=socketcan@hartkopp.net \
--cc=wg@grandegger.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox