diff options
author | Wolfgang Grandegger <wg@grandegger.com> | 2010-02-22 17:21:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-26 04:48:49 -0500 |
commit | 52c793f24054f5dc30d228e37e0e19cc8313f086 (patch) | |
tree | b7ebb686f5c2b0d58d05e42cc9d452adf651a83b /drivers/net/can | |
parent | 78ca90ea995cb86c72cde9308276d2a701bd3c40 (diff) |
can: netlink support for bus-error reporting and counters
This patch makes the bus-error reporting configurable and allows to
retrieve the CAN TX and RX bus error counters via netlink interface.
I have added support for the SJA1000. The TX and RX bus error counters
are also copied to the data fields 6..7 of error messages when state
changes are reported.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/dev.c | 6 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 25 |
2 files changed, 28 insertions, 3 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index f08f1202ff00..904aa369f80e 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -574,6 +574,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { | |||
574 | [IFLA_CAN_BITTIMING_CONST] | 574 | [IFLA_CAN_BITTIMING_CONST] |
575 | = { .len = sizeof(struct can_bittiming_const) }, | 575 | = { .len = sizeof(struct can_bittiming_const) }, |
576 | [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, | 576 | [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, |
577 | [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) }, | ||
577 | }; | 578 | }; |
578 | 579 | ||
579 | static int can_changelink(struct net_device *dev, | 580 | static int can_changelink(struct net_device *dev, |
@@ -649,6 +650,8 @@ static size_t can_get_size(const struct net_device *dev) | |||
649 | size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ | 650 | size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ |
650 | size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ | 651 | size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ |
651 | size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ | 652 | size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ |
653 | if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ | ||
654 | size += sizeof(struct can_berr_counter); | ||
652 | if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ | 655 | if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ |
653 | size += sizeof(struct can_bittiming_const); | 656 | size += sizeof(struct can_bittiming_const); |
654 | 657 | ||
@@ -659,6 +662,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
659 | { | 662 | { |
660 | struct can_priv *priv = netdev_priv(dev); | 663 | struct can_priv *priv = netdev_priv(dev); |
661 | struct can_ctrlmode cm = {.flags = priv->ctrlmode}; | 664 | struct can_ctrlmode cm = {.flags = priv->ctrlmode}; |
665 | struct can_berr_counter bec; | ||
662 | enum can_state state = priv->state; | 666 | enum can_state state = priv->state; |
663 | 667 | ||
664 | if (priv->do_get_state) | 668 | if (priv->do_get_state) |
@@ -669,6 +673,8 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
669 | NLA_PUT(skb, IFLA_CAN_BITTIMING, | 673 | NLA_PUT(skb, IFLA_CAN_BITTIMING, |
670 | sizeof(priv->bittiming), &priv->bittiming); | 674 | sizeof(priv->bittiming), &priv->bittiming); |
671 | NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock); | 675 | NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock); |
676 | if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec)) | ||
677 | NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec); | ||
672 | if (priv->bittiming_const) | 678 | if (priv->bittiming_const) |
673 | NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST, | 679 | NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST, |
674 | sizeof(*priv->bittiming_const), priv->bittiming_const); | 680 | sizeof(*priv->bittiming_const), priv->bittiming_const); |
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index ace103a44833..145b1a731a53 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c | |||
@@ -130,8 +130,12 @@ static void set_normal_mode(struct net_device *dev) | |||
130 | /* check reset bit */ | 130 | /* check reset bit */ |
131 | if ((status & MOD_RM) == 0) { | 131 | if ((status & MOD_RM) == 0) { |
132 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | 132 | priv->can.state = CAN_STATE_ERROR_ACTIVE; |
133 | /* enable all interrupts */ | 133 | /* enable interrupts */ |
134 | priv->write_reg(priv, REG_IER, IRQ_ALL); | 134 | if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) |
135 | priv->write_reg(priv, REG_IER, IRQ_ALL); | ||
136 | else | ||
137 | priv->write_reg(priv, REG_IER, | ||
138 | IRQ_ALL & ~IRQ_BEI); | ||
135 | return; | 139 | return; |
136 | } | 140 | } |
137 | 141 | ||
@@ -203,6 +207,17 @@ static int sja1000_set_bittiming(struct net_device *dev) | |||
203 | return 0; | 207 | return 0; |
204 | } | 208 | } |
205 | 209 | ||
210 | static int sja1000_get_berr_counter(const struct net_device *dev, | ||
211 | struct can_berr_counter *bec) | ||
212 | { | ||
213 | struct sja1000_priv *priv = netdev_priv(dev); | ||
214 | |||
215 | bec->txerr = priv->read_reg(priv, REG_TXERR); | ||
216 | bec->rxerr = priv->read_reg(priv, REG_RXERR); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
206 | /* | 221 | /* |
207 | * initialize SJA1000 chip: | 222 | * initialize SJA1000 chip: |
208 | * - reset chip | 223 | * - reset chip |
@@ -437,6 +452,8 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) | |||
437 | CAN_ERR_CRTL_TX_PASSIVE : | 452 | CAN_ERR_CRTL_TX_PASSIVE : |
438 | CAN_ERR_CRTL_RX_PASSIVE; | 453 | CAN_ERR_CRTL_RX_PASSIVE; |
439 | } | 454 | } |
455 | cf->data[6] = txerr; | ||
456 | cf->data[7] = rxerr; | ||
440 | } | 457 | } |
441 | 458 | ||
442 | priv->can.state = state; | 459 | priv->can.state = state; |
@@ -567,7 +584,9 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) | |||
567 | priv->can.bittiming_const = &sja1000_bittiming_const; | 584 | priv->can.bittiming_const = &sja1000_bittiming_const; |
568 | priv->can.do_set_bittiming = sja1000_set_bittiming; | 585 | priv->can.do_set_bittiming = sja1000_set_bittiming; |
569 | priv->can.do_set_mode = sja1000_set_mode; | 586 | priv->can.do_set_mode = sja1000_set_mode; |
570 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; | 587 | priv->can.do_get_berr_counter = sja1000_get_berr_counter; |
588 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | | ||
589 | CAN_CTRLMODE_BERR_REPORTING; | ||
571 | 590 | ||
572 | if (sizeof_priv) | 591 | if (sizeof_priv) |
573 | priv->priv = (void *)priv + sizeof(struct sja1000_priv); | 592 | priv->priv = (void *)priv + sizeof(struct sja1000_priv); |