diff options
Diffstat (limited to 'drivers/net/can/sja1000/sja1000.c')
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 04a3f1b756a..5e10472371e 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -95,11 +95,16 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val) spin_unlock_irqrestore(&priv->cmdreg_lock, flags); } +static int sja1000_is_absent(struct sja1000_priv *priv) +{ + return (priv->read_reg(priv, REG_MOD) == 0xFF); +} + static int sja1000_probe_chip(struct net_device *dev) { struct sja1000_priv *priv = netdev_priv(dev); - if (priv->reg_base && (priv->read_reg(priv, 0) == 0xFF)) { + if (priv->reg_base && sja1000_is_absent(priv)) { printk(KERN_INFO "%s: probing @0x%lX failed\n", DRV_NAME, dev->base_addr); return 0; @@ -128,7 +133,7 @@ static void set_reset_mode(struct net_device *dev) status = priv->read_reg(priv, REG_MOD); } - dev_err(dev->dev.parent, "setting SJA1000 into reset mode failed!\n"); + netdev_err(dev, "setting SJA1000 into reset mode failed!\n"); } static void set_normal_mode(struct net_device *dev) @@ -156,7 +161,7 @@ static void set_normal_mode(struct net_device *dev) status = priv->read_reg(priv, REG_MOD); } - dev_err(dev->dev.parent, "setting SJA1000 into normal mode failed!\n"); + netdev_err(dev, "setting SJA1000 into normal mode failed!\n"); } static void sja1000_start(struct net_device *dev) @@ -209,8 +214,7 @@ static int sja1000_set_bittiming(struct net_device *dev) if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) btr1 |= 0x80; - dev_info(dev->dev.parent, - "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1); + netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1); priv->write_reg(priv, REG_BTR0, btr0); priv->write_reg(priv, REG_BTR1, btr1); @@ -378,7 +382,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) if (isrc & IRQ_DOI) { /* data overrun interrupt */ - dev_dbg(dev->dev.parent, "data overrun interrupt\n"); + netdev_dbg(dev, "data overrun interrupt\n"); cf->can_id |= CAN_ERR_CRTL; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; stats->rx_over_errors++; @@ -388,7 +392,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) if (isrc & IRQ_EI) { /* error warning interrupt */ - dev_dbg(dev->dev.parent, "error warning interrupt\n"); + netdev_dbg(dev, "error warning interrupt\n"); if (status & SR_BS) { state = CAN_STATE_BUS_OFF; @@ -429,7 +433,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) } if (isrc & IRQ_EPI) { /* error passive interrupt */ - dev_dbg(dev->dev.parent, "error passive interrupt\n"); + netdev_dbg(dev, "error passive interrupt\n"); if (status & SR_ES) state = CAN_STATE_ERROR_PASSIVE; else @@ -437,7 +441,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) } if (isrc & IRQ_ALI) { /* arbitration lost interrupt */ - dev_dbg(dev->dev.parent, "arbitration lost interrupt\n"); + netdev_dbg(dev, "arbitration lost interrupt\n"); alc = priv->read_reg(priv, REG_ALC); priv->can.can_stats.arbitration_lost++; stats->tx_errors++; @@ -493,9 +497,12 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) { n++; status = priv->read_reg(priv, REG_SR); + /* check for absent controller due to hw unplug */ + if (status == 0xFF && sja1000_is_absent(priv)) + return IRQ_NONE; if (isrc & IRQ_WUI) - dev_warn(dev->dev.parent, "wakeup interrupt\n"); + netdev_warn(dev, "wakeup interrupt\n"); if (isrc & IRQ_TI) { /* transmission complete interrupt */ @@ -509,6 +516,9 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) while (status & SR_RBS) { sja1000_rx(dev); status = priv->read_reg(priv, REG_SR); + /* check for absent controller */ + if (status == 0xFF && sja1000_is_absent(priv)) + return IRQ_NONE; } } if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { @@ -522,7 +532,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) priv->post_irq(priv); if (n >= SJA1000_MAX_IRQ) - dev_dbg(dev->dev.parent, "%d messages handled in ISR", n); + netdev_dbg(dev, "%d messages handled in ISR", n); return (n) ? IRQ_HANDLED : IRQ_NONE; } |