linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 --]

  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).