From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Wolfgang Grandegger <wg@grandegger.com>
Cc: Alexander Stein <alexander.stein@systec-electronic.com>,
linux-can@vger.kernel.org, bhupesh.sharma@st.com,
tomoya.rohm@gmail.com
Subject: Re: [RFC v2 0/7] pch_can/c_can: fix races and add PCH support to c_can
Date: Fri, 07 Dec 2012 10:55:40 +0100 [thread overview]
Message-ID: <50C1BD1C.9090108@pengutronix.de> (raw)
In-Reply-To: <50C1B64D.8030209@grandegger.com>
[-- Attachment #1: Type: text/plain, Size: 6622 bytes --]
On 12/07/2012 10:26 AM, Wolfgang Grandegger wrote:
> On 12/07/2012 12:34 AM, Marc Kleine-Budde wrote:
>> On 12/06/2012 06:14 PM, Alexander Stein wrote:
>>>> This is a typical out-of-sequence reception with a
>>>> RX-goes-into-first-free-mailbox hardware. I've implemented the
>>>> algorithm used in the at91 and fixed the one for the ti_hecc.
>>>
>>> Marc, do you mean out-of-sequence reception with such mailbox types
>>> can happen even with the algorithm used in c_can and at91?
>>
>> It can happen, if the algorithm isn't implemented properly and adopted
>> to the needs of the hardware. On the unmodified ti_hecc we see this
>> out-of-sequence problems, too.
>
> Yep, that's the tricky part and the pch_can and c_can use a different
> approach to solve the problem. Let's concentrate on the c_can driver.
> Key-point is that the controller does put the message into the FIFO
> object with the lowest number. Here is the relevant code:
>
> /*
> * theory of operation:
> *
> * c_can core saves a received CAN message into the first free message
> * object it finds free (starting with the lowest). Bits NEWDAT and
> * INTPND are set for this message object indicating that a new message
> * has arrived. To work-around this issue, we keep two groups of message
> * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
> *
> * To ensure in-order frame reception we use the following
> * approach while re-activating a message object to receive further
> * frames:
> * - if the current message object number is lower than
> * C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing
> * the INTPND bit.
> * - if the current message object number is equal to
> * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower
> * receive message objects.
> * - if the current message object number is greater than
> * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
> * only this message object.
> */
> static int c_can_do_rx_poll(struct net_device *dev, int quota)
> {
> u32 num_rx_pkts = 0;
> unsigned int msg_obj, msg_ctrl_save;
> struct c_can_priv *priv = netdev_priv(dev);
> u32 val = c_can_read_reg32(priv, C_CAN_INTPND1_REG);
>
> for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST;
> msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0;
> val = c_can_read_reg32(priv, C_CAN_INTPND1_REG),
> msg_obj++) {
> /*
> * as interrupt pending register's bit n-1 corresponds to
> * message object n, we need to handle the same properly.
> */
> if (val & (1 << (msg_obj - 1))) {
> c_can_object_get(dev, IFACE_RX, msg_obj, IF_COMM_ALL &
> ~IF_COMM_TXRQST);
> msg_ctrl_save = priv->read_reg(priv,
> C_CAN_IFACE(MSGCTRL_REG, IFACE_RX));
>
> if (msg_ctrl_save & IF_MCONT_EOB)
> return num_rx_pkts;
>
> if (msg_ctrl_save & IF_MCONT_MSGLST) {
> c_can_handle_lost_msg_obj(dev, IFACE_RX,
> msg_obj);
> num_rx_pkts++;
> quota--;
> continue;
> }
>
> if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
> continue;
>
> /* read the data from the message object */
> c_can_read_msg_object(dev, IFACE_RX, msg_ctrl_save);
>
> if (msg_obj < C_CAN_MSG_RX_LOW_LAST)
> c_can_mark_rx_msg_obj(dev, IFACE_RX,
> msg_ctrl_save, msg_obj);
> else if (msg_obj > C_CAN_MSG_RX_LOW_LAST)
> /* activate this msg obj */
> c_can_activate_rx_msg_obj(dev, IFACE_RX,
> msg_ctrl_save, msg_obj);
> else if (msg_obj == C_CAN_MSG_RX_LOW_LAST)
> /* activate all lower message objects */
> c_can_activate_all_lower_rx_msg_obj(dev,
> IFACE_RX, msg_ctrl_save);
>
> num_rx_pkts++;
> quota--;
> }
> }
>
> return num_rx_pkts;
> }
>
>
> I see a problem if the current message object number is greater than
> C_CAN_MSG_RX_LOW_LAST, which is #8. Lets assume the FIFO filled up to
> message number #8 when we read INTPND1_REG. Before the we call
> c_can_activate_all_lower_rx_msg_obj(), another message is received
> into #9. Then we call c_can_activate_all_lower_rx_msg_obj() and shortly
> after another messages is received into #0. The next time we enter
> this function it will read first #1 and then #9, which is the wrong
> order.
This is the my reworked version of the ti_hecc poll loop.
Note: the ti_hecc fills the mailboxes from highest number to lowest, not
lowest to highest like the c_can.
> do {
It's not a for loop starting at the first mailbox. It always works on
the the next one....
> reg_rmp = hecc_read(priv, HECC_CANRMP) & priv->rx_active;
> if (!(reg_rmp & BIT(priv->rx_next))) {
> /*
> * Wrap around only if:
> * - we are in the lower group and
> * - there is a CAN frame in the first mailbox
> * of the high group.
> */
...and only wraps around to the first one under certain circumstances.
> if ((priv->rx_next <= HECC_RX_BUFFER_MBOX) &&
> (reg_rmp & BIT(HECC_RX_FIRST_MBOX)))
> priv->rx_next = HECC_RX_FIRST_MBOX;
> else
> break;
> }
> mb = priv->rx_next--;
>
> /* disable mailbox */
> priv->rx_active &= ~BIT(mb);
>
> ti_hecc_rx_pkt(priv, mb);
>
> /* enable mailboxes */
> if (mb == HECC_RX_BUFFER_MBOX) {
> hecc_write(priv, HECC_CANRMP, HECC_RX_HIGH_MBOX_MASK);
> priv->rx_active |= HECC_RX_HIGH_MBOX_MASK;
> } else if (mb == HECC_RX_FIRST_MBOX) {
> hecc_write(priv, HECC_CANRMP, HECC_RX_LOW_MBOX_MASK);
> priv->rx_active |= HECC_RX_LOW_MBOX_MASK;
> }
The enabling of the mailboxes is delayed compared to the original algorithm.
>
> received++;
> quota--;
> } while (quota);
We have at least 3 drivers with the same algorithm. I'm thinking if it
is possible to create a library helper for this.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 261 bytes --]
next prev parent reply other threads:[~2012-12-07 9:56 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-29 14:39 [RFC v2 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
2012-11-29 14:39 ` [RFC v2 1/7] pch_can: add spinlocks to protect tx objects Wolfgang Grandegger
2012-11-29 14:39 ` [RFC v2 2/7] c_can: rename callback "initram" to "init" to more general usage Wolfgang Grandegger
2012-12-03 14:20 ` Alexander Stein
2012-12-03 14:32 ` Wolfgang Grandegger
2012-11-29 14:39 ` [RFC v2 3/7] c_can: use different sets of interface registers for rx and tx Wolfgang Grandegger
2012-11-30 8:39 ` Marc Kleine-Budde
2012-11-30 9:15 ` Wolfgang Grandegger
2012-11-29 14:39 ` [RFC v2 4/7] c_can_pci: introduce board specific PCI bar Wolfgang Grandegger
2012-11-30 8:45 ` Marc Kleine-Budde
2012-11-30 9:11 ` Wolfgang Grandegger
2012-11-30 9:19 ` Marc Kleine-Budde
2012-11-29 14:39 ` [RFC v2 5/7] c_can_pci: enable PCI bus master only for MSI Wolfgang Grandegger
2012-11-30 8:54 ` Marc Kleine-Budde
2012-11-29 14:39 ` [RFC v2 6/7] c_can_pci: add support for PCH CAN on Intel EG20T PCH Wolfgang Grandegger
2012-11-29 14:39 ` [RFC v2 7/7] c_can: add spinlock to protect tx and rx objects Wolfgang Grandegger
2012-12-05 12:09 ` [RFC v2 0/7] pch_can/c_can: fix races and add PCH support to c_can Alexander Stein
2012-12-05 12:50 ` Wolfgang Grandegger
2012-12-05 14:46 ` Alexander Stein
2012-12-05 17:35 ` Wolfgang Grandegger
2012-12-05 21:52 ` Marc Kleine-Budde
2012-12-06 7:09 ` Wolfgang Grandegger
2012-12-06 8:35 ` Marc Kleine-Budde
2012-12-06 8:17 ` Wolfgang Grandegger
2012-12-06 13:38 ` Alexander Stein
2012-12-06 14:02 ` Marc Kleine-Budde
2012-12-06 14:31 ` Wolfgang Grandegger
2012-12-06 14:37 ` Marc Kleine-Budde
2012-12-06 14:56 ` Alexander Stein
2012-12-06 15:15 ` Wolfgang Grandegger
2012-12-06 15:27 ` Wolfgang Grandegger
2012-12-06 15:55 ` Alexander Stein
2012-12-06 17:14 ` Alexander Stein
2012-12-06 23:34 ` Marc Kleine-Budde
2012-12-07 9:26 ` Wolfgang Grandegger
2012-12-07 9:55 ` Marc Kleine-Budde [this message]
2012-12-07 10:00 ` Bhupesh SHARMA
2012-12-07 10:09 ` Marc Kleine-Budde
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=50C1BD1C.9090108@pengutronix.de \
--to=mkl@pengutronix.de \
--cc=alexander.stein@systec-electronic.com \
--cc=bhupesh.sharma@st.com \
--cc=linux-can@vger.kernel.org \
--cc=tomoya.rohm@gmail.com \
--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;
as well as URLs for NNTP newsgroup(s).