All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfgang Grandegger <wg@grandegger.com>
To: Marc Kleine-Budde <mkl@pengutronix.de>
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:26:37 +0100	[thread overview]
Message-ID: <50C1B64D.8030209@grandegger.com> (raw)
In-Reply-To: <50C12B77.1060501@pengutronix.de>

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.

Wolfgang.

  reply	other threads:[~2012-12-07  9:26 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 [this message]
2012-12-07  9:55                   ` Marc Kleine-Budde
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=50C1B64D.8030209@grandegger.com \
    --to=wg@grandegger.com \
    --cc=alexander.stein@systec-electronic.com \
    --cc=bhupesh.sharma@st.com \
    --cc=linux-can@vger.kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=tomoya.rohm@gmail.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 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.