diff options
author | Andri Yngvason <andri.yngvason@marel.com> | 2014-12-03 12:54:13 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2014-12-07 15:22:09 -0500 |
commit | 215db1856e8313ef8a1d9b64346dc261570012a6 (patch) | |
tree | 3cfd225b9f481867b9661f1edd35582e1746f14f /drivers/net/can | |
parent | bac78aabcfece0c493b2ad824c68fbdc20448cbc (diff) |
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>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 51 |
1 files changed, 23 insertions, 28 deletions
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index b27ac6074afb..32bd7f451aa4 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c | |||
@@ -392,12 +392,20 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) | |||
392 | struct can_frame *cf; | 392 | struct can_frame *cf; |
393 | struct sk_buff *skb; | 393 | struct sk_buff *skb; |
394 | enum can_state state = priv->can.state; | 394 | enum can_state state = priv->can.state; |
395 | enum can_state rx_state, tx_state; | ||
396 | unsigned int rxerr, txerr; | ||
395 | uint8_t ecc, alc; | 397 | uint8_t ecc, alc; |
396 | 398 | ||
397 | skb = alloc_can_err_skb(dev, &cf); | 399 | skb = alloc_can_err_skb(dev, &cf); |
398 | if (skb == NULL) | 400 | if (skb == NULL) |
399 | return -ENOMEM; | 401 | return -ENOMEM; |
400 | 402 | ||
403 | txerr = priv->read_reg(priv, SJA1000_TXERR); | ||
404 | rxerr = priv->read_reg(priv, SJA1000_RXERR); | ||
405 | |||
406 | cf->data[6] = txerr; | ||
407 | cf->data[7] = rxerr; | ||
408 | |||
401 | if (isrc & IRQ_DOI) { | 409 | if (isrc & IRQ_DOI) { |
402 | /* data overrun interrupt */ | 410 | /* data overrun interrupt */ |
403 | netdev_dbg(dev, "data overrun interrupt\n"); | 411 | 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) | |||
412 | /* error warning interrupt */ | 420 | /* error warning interrupt */ |
413 | netdev_dbg(dev, "error warning interrupt\n"); | 421 | netdev_dbg(dev, "error warning interrupt\n"); |
414 | 422 | ||
415 | if (status & SR_BS) { | 423 | if (status & SR_BS) |
416 | state = CAN_STATE_BUS_OFF; | 424 | state = CAN_STATE_BUS_OFF; |
417 | cf->can_id |= CAN_ERR_BUSOFF; | 425 | else if (status & SR_ES) |
418 | can_bus_off(dev); | ||
419 | } else if (status & SR_ES) { | ||
420 | state = CAN_STATE_ERROR_WARNING; | 426 | state = CAN_STATE_ERROR_WARNING; |
421 | } else | 427 | else |
422 | state = CAN_STATE_ERROR_ACTIVE; | 428 | state = CAN_STATE_ERROR_ACTIVE; |
423 | } | 429 | } |
424 | if (isrc & IRQ_BEI) { | 430 | if (isrc & IRQ_BEI) { |
@@ -452,10 +458,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) | |||
452 | if (isrc & IRQ_EPI) { | 458 | if (isrc & IRQ_EPI) { |
453 | /* error passive interrupt */ | 459 | /* error passive interrupt */ |
454 | netdev_dbg(dev, "error passive interrupt\n"); | 460 | netdev_dbg(dev, "error passive interrupt\n"); |
455 | if (status & SR_ES) | 461 | |
456 | state = CAN_STATE_ERROR_PASSIVE; | 462 | if (state == CAN_STATE_ERROR_PASSIVE) |
463 | state = CAN_STATE_ERROR_WARNING; | ||
457 | else | 464 | else |
458 | state = CAN_STATE_ERROR_ACTIVE; | 465 | state = CAN_STATE_ERROR_PASSIVE; |
459 | } | 466 | } |
460 | if (isrc & IRQ_ALI) { | 467 | if (isrc & IRQ_ALI) { |
461 | /* arbitration lost interrupt */ | 468 | /* arbitration lost interrupt */ |
@@ -467,27 +474,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) | |||
467 | cf->data[0] = alc & 0x1f; | 474 | cf->data[0] = alc & 0x1f; |
468 | } | 475 | } |
469 | 476 | ||
470 | if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || | 477 | if (state != priv->can.state) { |
471 | state == CAN_STATE_ERROR_PASSIVE)) { | 478 | tx_state = txerr >= rxerr ? state : 0; |
472 | uint8_t rxerr = priv->read_reg(priv, SJA1000_RXERR); | 479 | rx_state = txerr <= rxerr ? state : 0; |
473 | uint8_t txerr = priv->read_reg(priv, SJA1000_TXERR); | ||
474 | cf->can_id |= CAN_ERR_CRTL; | ||
475 | if (state == CAN_STATE_ERROR_WARNING) { | ||
476 | priv->can.can_stats.error_warning++; | ||
477 | cf->data[1] = (txerr > rxerr) ? | ||
478 | CAN_ERR_CRTL_TX_WARNING : | ||
479 | CAN_ERR_CRTL_RX_WARNING; | ||
480 | } else { | ||
481 | priv->can.can_stats.error_passive++; | ||
482 | cf->data[1] = (txerr > rxerr) ? | ||
483 | CAN_ERR_CRTL_TX_PASSIVE : | ||
484 | CAN_ERR_CRTL_RX_PASSIVE; | ||
485 | } | ||
486 | cf->data[6] = txerr; | ||
487 | cf->data[7] = rxerr; | ||
488 | } | ||
489 | 480 | ||
490 | priv->can.state = state; | 481 | can_change_state(dev, cf, tx_state, rx_state); |
482 | |||
483 | if(state == CAN_STATE_BUS_OFF) | ||
484 | can_bus_off(dev); | ||
485 | } | ||
491 | 486 | ||
492 | netif_rx(skb); | 487 | netif_rx(skb); |
493 | 488 | ||