aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/sja1000
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can/sja1000')
-rw-r--r--drivers/net/can/sja1000/sja1000.c20
-rw-r--r--drivers/net/can/sja1000/sja1000.h1
2 files changed, 18 insertions, 3 deletions
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 24b58619f7c1..85f7cbfe8e5f 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -83,6 +83,20 @@ static struct can_bittiming_const sja1000_bittiming_const = {
83 .brp_inc = 1, 83 .brp_inc = 1,
84}; 84};
85 85
86static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
87{
88 unsigned long flags;
89
90 /*
91 * The command register needs some locking and time to settle
92 * the write_reg() operation - especially on SMP systems.
93 */
94 spin_lock_irqsave(&priv->cmdreg_lock, flags);
95 priv->write_reg(priv, REG_CMR, val);
96 priv->read_reg(priv, REG_SR);
97 spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
98}
99
86static int sja1000_probe_chip(struct net_device *dev) 100static int sja1000_probe_chip(struct net_device *dev)
87{ 101{
88 struct sja1000_priv *priv = netdev_priv(dev); 102 struct sja1000_priv *priv = netdev_priv(dev);
@@ -294,7 +308,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
294 308
295 can_put_echo_skb(skb, dev, 0); 309 can_put_echo_skb(skb, dev, 0);
296 310
297 priv->write_reg(priv, REG_CMR, CMD_TR); 311 sja1000_write_cmdreg(priv, CMD_TR);
298 312
299 return NETDEV_TX_OK; 313 return NETDEV_TX_OK;
300} 314}
@@ -343,7 +357,7 @@ static void sja1000_rx(struct net_device *dev)
343 cf->can_id = id; 357 cf->can_id = id;
344 358
345 /* release receive buffer */ 359 /* release receive buffer */
346 priv->write_reg(priv, REG_CMR, CMD_RRB); 360 sja1000_write_cmdreg(priv, CMD_RRB);
347 361
348 netif_rx(skb); 362 netif_rx(skb);
349 363
@@ -371,7 +385,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
371 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 385 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
372 stats->rx_over_errors++; 386 stats->rx_over_errors++;
373 stats->rx_errors++; 387 stats->rx_errors++;
374 priv->write_reg(priv, REG_CMR, CMD_CDO); /* clear bit */ 388 sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
375 } 389 }
376 390
377 if (isrc & IRQ_EI) { 391 if (isrc & IRQ_EI) {
diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h
index 97a622b9302f..de8e778f6832 100644
--- a/drivers/net/can/sja1000/sja1000.h
+++ b/drivers/net/can/sja1000/sja1000.h
@@ -167,6 +167,7 @@ struct sja1000_priv {
167 167
168 void __iomem *reg_base; /* ioremap'ed address to registers */ 168 void __iomem *reg_base; /* ioremap'ed address to registers */
169 unsigned long irq_flags; /* for request_irq() */ 169 unsigned long irq_flags; /* for request_irq() */
170 spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
170 171
171 u16 flags; /* custom mode flags */ 172 u16 flags; /* custom mode flags */
172 u8 ocr; /* output control register */ 173 u8 ocr; /* output control register */