can: sja1000: Consolidate and unify state change handling

Replacing error state change handling with the new mechanism.

Signed-off-by: Andri Yngvason <andri.yngvason@marel.com>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Andri Yngvason 2014-12-03 17:54:13 +00:00 committed by Marc Kleine-Budde
parent bac78aabcf
commit 215db1856e

View file

@ -392,12 +392,20 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
struct can_frame *cf; struct can_frame *cf;
struct sk_buff *skb; struct sk_buff *skb;
enum can_state state = priv->can.state; enum can_state state = priv->can.state;
enum can_state rx_state, tx_state;
unsigned int rxerr, txerr;
uint8_t ecc, alc; uint8_t ecc, alc;
skb = alloc_can_err_skb(dev, &cf); skb = alloc_can_err_skb(dev, &cf);
if (skb == NULL) if (skb == NULL)
return -ENOMEM; return -ENOMEM;
txerr = priv->read_reg(priv, SJA1000_TXERR);
rxerr = priv->read_reg(priv, SJA1000_RXERR);
cf->data[6] = txerr;
cf->data[7] = rxerr;
if (isrc & IRQ_DOI) { if (isrc & IRQ_DOI) {
/* data overrun interrupt */ /* data overrun interrupt */
netdev_dbg(dev, "data overrun interrupt\n"); netdev_dbg(dev, "data overrun interrupt\n");
@ -412,13 +420,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
/* error warning interrupt */ /* error warning interrupt */
netdev_dbg(dev, "error warning interrupt\n"); netdev_dbg(dev, "error warning interrupt\n");
if (status & SR_BS) { if (status & SR_BS)
state = CAN_STATE_BUS_OFF; state = CAN_STATE_BUS_OFF;
cf->can_id |= CAN_ERR_BUSOFF; else if (status & SR_ES)
can_bus_off(dev);
} else if (status & SR_ES) {
state = CAN_STATE_ERROR_WARNING; state = CAN_STATE_ERROR_WARNING;
} else else
state = CAN_STATE_ERROR_ACTIVE; state = CAN_STATE_ERROR_ACTIVE;
} }
if (isrc & IRQ_BEI) { if (isrc & IRQ_BEI) {
@ -452,10 +458,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
if (isrc & IRQ_EPI) { if (isrc & IRQ_EPI) {
/* error passive interrupt */ /* error passive interrupt */
netdev_dbg(dev, "error passive interrupt\n"); netdev_dbg(dev, "error passive interrupt\n");
if (status & SR_ES)
state = CAN_STATE_ERROR_PASSIVE; if (state == CAN_STATE_ERROR_PASSIVE)
state = CAN_STATE_ERROR_WARNING;
else else
state = CAN_STATE_ERROR_ACTIVE; state = CAN_STATE_ERROR_PASSIVE;
} }
if (isrc & IRQ_ALI) { if (isrc & IRQ_ALI) {
/* arbitration lost interrupt */ /* arbitration lost interrupt */
@ -467,27 +474,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
cf->data[0] = alc & 0x1f; cf->data[0] = alc & 0x1f;
} }
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || if (state != priv->can.state) {
state == CAN_STATE_ERROR_PASSIVE)) { tx_state = txerr >= rxerr ? state : 0;
uint8_t rxerr = priv->read_reg(priv, SJA1000_RXERR); rx_state = txerr <= rxerr ? state : 0;
uint8_t txerr = priv->read_reg(priv, SJA1000_TXERR);
cf->can_id |= CAN_ERR_CRTL;
if (state == CAN_STATE_ERROR_WARNING) {
priv->can.can_stats.error_warning++;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
} else {
priv->can.can_stats.error_passive++;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE :
CAN_ERR_CRTL_RX_PASSIVE;
}
cf->data[6] = txerr;
cf->data[7] = rxerr;
}
priv->can.state = state; can_change_state(dev, cf, tx_state, rx_state);
if(state == CAN_STATE_BUS_OFF)
can_bus_off(dev);
}
netif_rx(skb); netif_rx(skb);