diff options
| -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 */ |
