netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] Fix SJA1000 command register writes on SMP systems
@ 2010-05-17 20:17 Oliver Hartkopp
  2010-05-18  5:34 ` David Miller
  0 siblings, 1 reply; 3+ messages in thread
From: Oliver Hartkopp @ 2010-05-17 20:17 UTC (permalink / raw)
  To: David Miller
  Cc: SocketCAN Core Mailing List, Linux Netdev List, Wolfgang Grandegger

The SJA1000 command register is concurrently written in the rx-path to free
the receive buffer _and_ in the tx-path to start the transmission.

The SJA1000 data sheet, 6.4.4 COMMAND REGISTER (CMR) states:
"Between two commands at least one internal clock cycle is needed in
order to proceed. The internal clock is half of the external oscillator
frequency."

On SMP systems this leads to a write stall in the tx-path, which can be
solved by adding some locking for the command register in the SMP case.
In this special case we also read the status register to settle the command
register write.

Thanks to Klaus Hitschler for the original fix and detailed problem
description.

This patch applies on net-2.6 and (with some offsets) on net-next-2.6 .

Signed-off-by: Oliver Hartkopp <socketcan-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>
Acked-by: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>

---

diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 145b1a7..2760085 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -84,6 +84,27 @@ static struct can_bittiming_const sja1000_bittiming_const = {
 	.brp_inc = 1,
 };
 +static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
+{
+	/* the command register needs some locking on SMP systems */
+
+#ifdef CONFIG_SMP
+
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->cmdreg_lock, flags);
+	priv->write_reg(priv, REG_CMR, val);
+	priv->read_reg(priv, REG_SR);
+	spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
+
+#else
+
+	/* write to the command register without locking */
+	priv->write_reg(priv, REG_CMR, val);
+
+#endif
+}
+
 static int sja1000_probe_chip(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
@@ -297,7 +318,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
  	can_put_echo_skb(skb, dev, 0);
 -	priv->write_reg(priv, REG_CMR, CMD_TR);
+	sja1000_write_cmdreg(priv, CMD_TR);
  	return NETDEV_TX_OK;
 }
@@ -346,7 +367,7 @@ static void sja1000_rx(struct net_device *dev)
 	cf->can_id = id;
  	/* release receive buffer */
-	priv->write_reg(priv, REG_CMR, CMD_RRB);
+	sja1000_write_cmdreg(priv, CMD_RRB);
  	netif_rx(skb);
 @@ -374,7 +395,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
 		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
 		stats->rx_over_errors++;
 		stats->rx_errors++;
-		priv->write_reg(priv, REG_CMR, CMD_CDO);	/* clear bit */
+		sja1000_write_cmdreg(priv, CMD_CDO);	/* clear bit */
 	}
  	if (isrc & IRQ_EI) {
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 97a622b..4527d95 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -168,6 +168,10 @@ struct sja1000_priv {
 	void __iomem *reg_base;	 /* ioremap'ed address to registers */
 	unsigned long irq_flags; /* for request_irq() */
 +#ifdef CONFIG_SMP
+	spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
+#endif
+
 	u16 flags;		/* custom mode flags */
 	u8 ocr;			/* output control register */
 	u8 cdr;			/* clock divider register */

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] Fix SJA1000 command register writes on SMP systems
  2010-05-17 20:17 [PATCH v2] Fix SJA1000 command register writes on SMP systems Oliver Hartkopp
@ 2010-05-18  5:34 ` David Miller
       [not found]   ` <20100517.223415.184853371.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: David Miller @ 2010-05-18  5:34 UTC (permalink / raw)
  To: socketcan; +Cc: wg, netdev, socketcan-core

From: Oliver Hartkopp <socketcan@hartkopp.net>
Date: Mon, 17 May 2010 22:17:40 +0200

> diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
> index 145b1a7..2760085 100644
> --- a/drivers/net/can/sja1000/sja1000.c
> +++ b/drivers/net/can/sja1000/sja1000.c
> @@ -84,6 +84,27 @@ static struct can_bittiming_const sja1000_bittiming_const = {
>  	.brp_inc = 1,
>  };
>  +static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
> +{
> +	/* the command register needs some locking on SMP systems */
> +
> +#ifdef CONFIG_SMP

Something is adding spurious leading spaces to lines in your patch.

Also, please don't SMP conditionalize this code.  It makes it such that
lock debugging et al. can't be used to check this code on uniprocessor.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] Fix SJA1000 command register writes on SMP systems
       [not found]   ` <20100517.223415.184853371.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
@ 2010-05-18 18:56     ` Oliver Hartkopp
  0 siblings, 0 replies; 3+ messages in thread
From: Oliver Hartkopp @ 2010-05-18 18:56 UTC (permalink / raw)
  To: David Miller
  Cc: socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, wg-5Yr1BZd7O62+XT7JhA+gdA

On 18.05.2010 07:34, David Miller wrote:
> From: Oliver Hartkopp <socketcan-fJ+pQTUTwRTk1uMJSBkQmQ@public.gmane.org>
> Date: Mon, 17 May 2010 22:17:40 +0200
> 
>> diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
>> index 145b1a7..2760085 100644
>> --- a/drivers/net/can/sja1000/sja1000.c
>> +++ b/drivers/net/can/sja1000/sja1000.c
>> @@ -84,6 +84,27 @@ static struct can_bittiming_const sja1000_bittiming_const = {
>>  	.brp_inc = 1,
>>  };
>>  +static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
>> +{
>> +	/* the command register needs some locking on SMP systems */
>> +
>> +#ifdef CONFIG_SMP
> 
> Something is adding spurious leading spaces to lines in your patch.

Sorry. This was probably due to the v2 resend. Will fix.

> Also, please don't SMP conditionalize this code.  It makes it such that
> lock debugging et al. can't be used to check this code on uniprocessor.

Ok.

Will send an updated v3 patch shortly.

Thanks,
Oliver

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-05-18 18:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-17 20:17 [PATCH v2] Fix SJA1000 command register writes on SMP systems Oliver Hartkopp
2010-05-18  5:34 ` David Miller
     [not found]   ` <20100517.223415.184853371.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
2010-05-18 18:56     ` Oliver Hartkopp

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