aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/sja1000/sja1000.c
diff options
context:
space:
mode:
authorAndri Yngvason <andri.yngvason@marel.com>2014-12-03 12:54:13 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-12-07 15:22:09 -0500
commit215db1856e8313ef8a1d9b64346dc261570012a6 (patch)
tree3cfd225b9f481867b9661f1edd35582e1746f14f /drivers/net/can/sja1000/sja1000.c
parentbac78aabcfece0c493b2ad824c68fbdc20448cbc (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/sja1000/sja1000.c')
-rw-r--r--drivers/net/can/sja1000/sja1000.c51
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