diff options
-rw-r--r-- | drivers/net/can/dev.c | 6 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 25 | ||||
-rw-r--r-- | include/linux/can/dev.h | 2 | ||||
-rw-r--r-- | include/linux/can/netlink.h | 18 |
4 files changed, 44 insertions, 7 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); |
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index c8c660a79f90..6e5a7f00223d 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h | |||
@@ -47,6 +47,8 @@ struct can_priv { | |||
47 | int (*do_set_mode)(struct net_device *dev, enum can_mode mode); | 47 | int (*do_set_mode)(struct net_device *dev, enum can_mode mode); |
48 | int (*do_get_state)(const struct net_device *dev, | 48 | int (*do_get_state)(const struct net_device *dev, |
49 | enum can_state *state); | 49 | enum can_state *state); |
50 | int (*do_get_berr_counter)(const struct net_device *dev, | ||
51 | struct can_berr_counter *bec); | ||
50 | 52 | ||
51 | unsigned int echo_skb_max; | 53 | unsigned int echo_skb_max; |
52 | struct sk_buff **echo_skb; | 54 | struct sk_buff **echo_skb; |
diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h index c818335fbb13..3250de935e1a 100644 --- a/include/linux/can/netlink.h +++ b/include/linux/can/netlink.h | |||
@@ -70,6 +70,14 @@ enum can_state { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * CAN bus error counters | ||
74 | */ | ||
75 | struct can_berr_counter { | ||
76 | __u16 txerr; | ||
77 | __u16 rxerr; | ||
78 | }; | ||
79 | |||
80 | /* | ||
73 | * CAN controller mode | 81 | * CAN controller mode |
74 | */ | 82 | */ |
75 | struct can_ctrlmode { | 83 | struct can_ctrlmode { |
@@ -77,10 +85,11 @@ struct can_ctrlmode { | |||
77 | __u32 flags; | 85 | __u32 flags; |
78 | }; | 86 | }; |
79 | 87 | ||
80 | #define CAN_CTRLMODE_LOOPBACK 0x1 /* Loopback mode */ | 88 | #define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ |
81 | #define CAN_CTRLMODE_LISTENONLY 0x2 /* Listen-only mode */ | 89 | #define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ |
82 | #define CAN_CTRLMODE_3_SAMPLES 0x4 /* Triple sampling mode */ | 90 | #define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ |
83 | #define CAN_CTRLMODE_ONE_SHOT 0x8 /* One-Shot mode */ | 91 | #define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ |
92 | #define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ | ||
84 | 93 | ||
85 | /* | 94 | /* |
86 | * CAN device statistics | 95 | * CAN device statistics |
@@ -106,6 +115,7 @@ enum { | |||
106 | IFLA_CAN_CTRLMODE, | 115 | IFLA_CAN_CTRLMODE, |
107 | IFLA_CAN_RESTART_MS, | 116 | IFLA_CAN_RESTART_MS, |
108 | IFLA_CAN_RESTART, | 117 | IFLA_CAN_RESTART, |
118 | IFLA_CAN_BERR_COUNTER, | ||
109 | __IFLA_CAN_MAX | 119 | __IFLA_CAN_MAX |
110 | }; | 120 | }; |
111 | 121 | ||