diff options
Diffstat (limited to 'drivers/net/can/sja1000')
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 20 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000.h | 1 |
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 | ||
86 | static 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 | |||
86 | static int sja1000_probe_chip(struct net_device *dev) | 100 | static 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 */ |