On 05/30/2011 03:33 PM, Marc Kleine-Budde wrote: > On 05/30/2011 03:30 PM, Wolfgang Grandegger wrote: >> Hi Marc, >> >> On 05/30/2011 03:05 PM, Marc Kleine-Budde wrote: >>> Hello Wolfgang, >>> >>> I'm doing some work on the at91 driver, especially the error management, >>> to support the upcoming 5sereis. Do you have any patches or remarks for >>> the driver, the patches don't even need to apply any more or must be >>> tested, I just need some input cause I have to restructure the error >>> handling anyway. >> >> Well, I have a almost (half?) complete patch series to consolidate the >> error handling of the mainline Socket-CAN device drivers but real >> bussiness does keep me fully loaded already since a while, >> unfortunately. I will dig for it later today or tomorrow. More soon... > > Just send me the at91 bit (as soon as possible :P, please). As it turns > out they changed some bits to clear on read in the new CAN hardware.
Attached is the patch series I'm speaking about. I think there is no special fix for the AT91. The series tries to make the error handling consistent for all drivers as discussed some time ago. Wolfgang.
>From 0d36e12c4c76a2074d34bc9b0f8c176c997b62e2 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger <[email protected]> Date: Wed, 23 Mar 2011 17:34:46 +0100 Subject: [PATCH 1/3] can: consolidate handling of bus error counters This patch improves and corrects the handling of bus error TX and RX counters: - Fill the data[6..7] fields of all error message with the TX and RX error counter values in the common function alloc_can_err_skb(). - Add missing do_get_berr_counter callbacks for the ti_hecc and bfin_can driver. - A few other minor fixes, e.g. make sure to fill data[6..7] for all error messages. Signed-off-by: Wolfgang Grandegger <[email protected]> CC: Marc Kleine-Budde <[email protected]> CC: Barry Song <[email protected]> CC: Anant Gole <[email protected]> --- drivers/net/can/at91_can.c | 7 ++----- drivers/net/can/bfin_can.c | 22 ++++++++++++++++------ drivers/net/can/dev.c | 8 ++++++++ drivers/net/can/flexcan.c | 7 ++----- drivers/net/can/pch_can.c | 14 +++++--------- drivers/net/can/sja1000/sja1000.c | 8 ++------ drivers/net/can/ti_hecc.c | 20 ++++++++++++++++---- drivers/net/can/usb/ems_usb.c | 7 ++++--- drivers/net/can/usb/esd_usb2.c | 5 +++-- 9 files changed, 58 insertions(+), 40 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 57d2ffb..f18cba7 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -803,9 +803,6 @@ static void at91_irq_err_state(struct net_device *dev, { struct at91_priv *priv = netdev_priv(dev); u32 reg_idr = 0, reg_ier = 0; - struct can_berr_counter bec; - - at91_get_berr_counter(dev, &bec); switch (priv->can.state) { case CAN_STATE_ERROR_ACTIVE: @@ -820,7 +817,7 @@ static void at91_irq_err_state(struct net_device *dev, priv->can.can_stats.error_warning++; cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (bec.txerr > bec.rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } @@ -836,7 +833,7 @@ static void at91_irq_err_state(struct net_device *dev, priv->can.can_stats.error_passive++; cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (bec.txerr > bec.rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index b6e890d..9c3e78e 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -224,6 +224,19 @@ static int bfin_can_set_mode(struct net_device *dev, enum can_mode mode) return 0; } +static int bfin_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + struct bfin_can_priv *priv = netdev_priv(dev); + struct bfin_can_regs __iomem *reg = priv->membase; + u16 cec = bfin_read16(®->cec); + + bec->txerr = cec & 0xff; + bec->rxerr = (cec >> 8) & 0xff; + + return 0; +} + static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bfin_can_priv *priv = netdev_priv(dev); @@ -368,19 +381,15 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || state == CAN_STATE_ERROR_PASSIVE)) { - u16 cec = bfin_read16(®->cec); - u8 rxerr = cec; - u8 txerr = cec >> 8; - cf->can_id |= CAN_ERR_CRTL; if (state == CAN_STATE_ERROR_WARNING) { priv->can.can_stats.error_warning++; - cf->data[1] = (txerr > rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } else { priv->can.can_stats.error_passive++; - cf->data[1] = (txerr > rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } @@ -517,6 +526,7 @@ struct net_device *alloc_bfin_candev(void) priv->dev = dev; priv->can.bittiming_const = &bfin_can_bittiming_const; priv->can.do_set_bittiming = bfin_can_set_bittiming; + priv->can.do_get_berr_counter = bfin_get_berr_counter; priv->can.do_set_mode = bfin_can_set_mode; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index d0f8c7e..e2f8e04 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -465,6 +465,7 @@ EXPORT_SYMBOL_GPL(alloc_can_skb); struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf) { + struct can_priv *priv = netdev_priv(dev); struct sk_buff *skb; skb = alloc_can_skb(dev, cf); @@ -473,6 +474,13 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf) (*cf)->can_id = CAN_ERR_FLAG; (*cf)->can_dlc = CAN_ERR_DLC; + if (priv->do_get_berr_counter) { + struct can_berr_counter bec; + + priv->do_get_berr_counter(dev, &bec); + (*cf)->data[6] = bec.txerr; + (*cf)->data[7] = bec.rxerr; + } return skb; } diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index d499056..731764f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -356,9 +356,6 @@ static void do_state(struct net_device *dev, struct can_frame *cf, enum can_state new_state) { struct flexcan_priv *priv = netdev_priv(dev); - struct can_berr_counter bec; - - flexcan_get_berr_counter(dev, &bec); switch (priv->can.state) { case CAN_STATE_ERROR_ACTIVE: @@ -373,7 +370,7 @@ static void do_state(struct net_device *dev, priv->can.can_stats.error_warning++; cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (bec.txerr > bec.rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } @@ -389,7 +386,7 @@ static void do_state(struct net_device *dev, priv->can.can_stats.error_passive++; cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (bec.txerr > bec.rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index e54712b..042ecff 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -493,7 +493,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) struct sk_buff *skb; struct pch_can_priv *priv = netdev_priv(ndev); struct can_frame *cf; - u32 errc, lec; + u32 lec; struct net_device_stats *stats = &(priv->ndev->stats); enum can_state state = priv->can.state; @@ -509,15 +509,14 @@ static void pch_can_error(struct net_device *ndev, u32 status) can_bus_off(ndev); } - errc = ioread32(&priv->regs->errc); /* Warning interrupt. */ if (status & PCH_EWARN) { state = CAN_STATE_ERROR_WARNING; priv->can.can_stats.error_warning++; cf->can_id |= CAN_ERR_CRTL; - if (((errc & PCH_REC) >> 8) > 96) + if (cf->data[7] > 96) cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; - if ((errc & PCH_TEC) > 96) + if (cf->data[6] > 96) cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; netdev_dbg(ndev, "%s -> Error Counter is more than 96.\n", __func__); @@ -527,9 +526,9 @@ static void pch_can_error(struct net_device *ndev, u32 status) priv->can.can_stats.error_passive++; state = CAN_STATE_ERROR_PASSIVE; cf->can_id |= CAN_ERR_CRTL; - if (((errc & PCH_REC) >> 8) > 127) + if (cf->data[7] > 127) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; - if ((errc & PCH_TEC) > 127) + if (cf->data[7] > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; netdev_dbg(ndev, "%s -> CAN controller is ERROR PASSIVE .\n", __func__); @@ -568,9 +567,6 @@ static void pch_can_error(struct net_device *ndev, u32 status) break; } - cf->data[6] = errc & PCH_TEC; - cf->data[7] = (errc & PCH_REC) >> 8; - priv->can.state = state; netif_receive_skb(skb); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 0a8de01..1e6b3dd 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -449,22 +449,18 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || state == CAN_STATE_ERROR_PASSIVE)) { - uint8_t rxerr = priv->read_reg(priv, REG_RXERR); - uint8_t txerr = priv->read_reg(priv, REG_TXERR); cf->can_id |= CAN_ERR_CRTL; if (state == CAN_STATE_ERROR_WARNING) { priv->can.can_stats.error_warning++; - cf->data[1] = (txerr > rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } else { priv->can.can_stats.error_passive++; - cf->data[1] = (txerr > rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } - cf->data[6] = txerr; - cf->data[7] = rxerr; } priv->can.state = state; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 4d07f1e..d16dd00 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -457,6 +457,17 @@ static int ti_hecc_do_set_mode(struct net_device *ndev, enum can_mode mode) return ret; } +static int ti_hecc_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + struct ti_hecc_priv *priv = netdev_priv(dev); + + bec->txerr = hecc_read(priv, HECC_CANTEC); + bec->rxerr = hecc_read(priv, HECC_CANREC); + + return 0; +} + /* * ti_hecc_xmit: HECC Transmit * @@ -677,9 +688,9 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, priv->can.state = CAN_STATE_ERROR_WARNING; ++priv->can.can_stats.error_warning; cf->can_id |= CAN_ERR_CRTL; - if (hecc_read(priv, HECC_CANTEC) > 96) + if (cf->data[6] > 96) cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; - if (hecc_read(priv, HECC_CANREC) > 96) + if (cf->data[7] > 96) cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; } hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW); @@ -692,9 +703,9 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, priv->can.state = CAN_STATE_ERROR_PASSIVE; ++priv->can.can_stats.error_passive; cf->can_id |= CAN_ERR_CRTL; - if (hecc_read(priv, HECC_CANTEC) > 127) + if (cf->data[6] > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; - if (hecc_read(priv, HECC_CANREC) > 127) + if (cf->data[7] > 127) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; } hecc_set_bit(priv, HECC_CANES, HECC_CANES_EP); @@ -921,6 +932,7 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->can.bittiming_const = &ti_hecc_bittiming_const; priv->can.do_set_mode = ti_hecc_do_set_mode; priv->can.do_get_state = ti_hecc_get_state; + priv->can.do_get_berr_counter = ti_hecc_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; ndev->irq = irq->start; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index e75f1a8..d195386 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -344,6 +344,9 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) if (skb == NULL) return; + cf->data[6] = msg->msg.error.cc.regs.sja1000.txerr; + cf->data[7] = msg->msg.error.cc.regs.sja1000.rxerr; + if (msg->type == CPC_MSG_TYPE_CAN_STATE) { u8 state = msg->msg.can_state; @@ -361,8 +364,6 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) } } else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) { u8 ecc = msg->msg.error.cc.regs.sja1000.ecc; - u8 txerr = msg->msg.error.cc.regs.sja1000.txerr; - u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr; /* bus error interrupt */ dev->can.can_stats.bus_error++; @@ -392,7 +393,7 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) if (dev->can.state == CAN_STATE_ERROR_WARNING || dev->can.state == CAN_STATE_ERROR_PASSIVE) { - cf->data[1] = (txerr > rxerr) ? + cf->data[1] = (cf->data[6] > cf->data[7]) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } } else if (msg->type == CPC_MSG_TYPE_OVERRUN) { diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index dc53c83..4787274 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -294,10 +294,11 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } - cf->data[6] = txerr; - cf->data[7] = rxerr; } + cf->data[6] = txerr; + cf->data[7] = rxerr; + netif_rx(skb); priv->bec.txerr = txerr; -- 1.7.2.3
>From 51619f3b1e59b48f5ba97247df94d32aa68c9477 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger <[email protected]> Date: Wed, 23 Mar 2011 17:41:43 +0100 Subject: [PATCH 2/3] can: ti_hecc: fix 'data' is used uninitialized in ti_hecc_xmit() Signed-off-by: Wolfgang Grandegger <[email protected]> --- drivers/net/can/ti_hecc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index d16dd00..871ad92 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -514,9 +514,9 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) spin_unlock_irqrestore(&priv->mbx_lock, flags); /* Prepare mailbox for transmission */ + data = get_tx_head_prio(priv) << 8; if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */ data |= HECC_CANMCF_RTR; - data |= get_tx_head_prio(priv) << 8; hecc_write_mbx(priv, mbxno, HECC_CANMCF, data); if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */ -- 1.7.2.3
>From 7e2b48d9e870b71b80ba8626b4b52a2c41567b0c Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger <[email protected]> Date: Wed, 23 Mar 2011 18:22:45 +0100 Subject: [PATCH 3/3] can: consolidate CAN error message handling Signed-off-by: Wolfgang Grandegger <[email protected]> --- drivers/net/can/at91_can.c | 19 +++++------- drivers/net/can/bfin_can.c | 23 +++++++++++--- drivers/net/can/c_can/c_can.c | 7 +--- drivers/net/can/flexcan.c | 28 +++++++----------- drivers/net/can/janz-ican3.c | 22 +++++++++++++- drivers/net/can/pch_can.c | 57 ++++++++++++++++++------------------- drivers/net/can/sja1000/sja1000.c | 23 +++++++++++++-- drivers/net/can/ti_hecc.c | 11 ++++-- include/linux/can/error.h | 8 +++-- 9 files changed, 119 insertions(+), 79 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index f18cba7..67e1bf5 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -649,20 +649,19 @@ static void at91_poll_err_frame(struct net_device *dev, { struct at91_priv *priv = netdev_priv(dev); + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + /* CRC error */ if (reg_sr & AT91_IRQ_CERR) { netdev_dbg(dev, "CERR irq\n"); dev->stats.rx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + cf->data[2] |= CAN_ERR_PROT_CRC; } /* Stuffing Error */ if (reg_sr & AT91_IRQ_SERR) { netdev_dbg(dev, "SERR irq\n"); dev->stats.rx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_STUFF; } @@ -670,15 +669,13 @@ static void at91_poll_err_frame(struct net_device *dev, if (reg_sr & AT91_IRQ_AERR) { netdev_dbg(dev, "AERR irq\n"); dev->stats.tx_errors++; - cf->can_id |= CAN_ERR_ACK; + cf->data[2] |= CAN_ERR_PROT_ACK; } /* Form error */ if (reg_sr & AT91_IRQ_FERR) { netdev_dbg(dev, "FERR irq\n"); dev->stats.rx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_FORM; } @@ -686,10 +683,10 @@ static void at91_poll_err_frame(struct net_device *dev, if (reg_sr & AT91_IRQ_BERR) { netdev_dbg(dev, "BERR irq\n"); dev->stats.tx_errors++; - priv->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_BIT; } + + priv->can.can_stats.bus_error++; } static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr) @@ -868,8 +865,8 @@ static void at91_irq_err_state(struct net_device *dev, * the "fallthrough" */ netdev_dbg(dev, "Error Active\n"); - cf->can_id |= CAN_ERR_PROT; - cf->data[2] = CAN_ERR_PROT_ACTIVE; + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_ACTIVE; case CAN_STATE_ERROR_WARNING: /* fallthrough */ reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF; reg_ier = AT91_IRQ_ERRP; diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 9c3e78e..f4ce17b 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -400,14 +400,27 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - if (status & BEF) + cf->data[2] |= CAN_ERR_PROT_UNSPEC; + if (status & BEF) { cf->data[2] |= CAN_ERR_PROT_BIT; - else if (status & FER) + stats->tx_errors++; + } + if (status & FER) { cf->data[2] |= CAN_ERR_PROT_FORM; - else if (status & SER) + stats->rx_errors++; + } + if (status & SER) { cf->data[2] |= CAN_ERR_PROT_STUFF; - else - cf->data[2] |= CAN_ERR_PROT_UNSPEC; + stats->rx_errors++; + } + if (status & ACKE) { + cf->data[2] |= CAN_ERR_PROT_ACK; + stats->tx_errors++; + } + if (status & CRCE) { + cf->data[2] |= CAN_ERR_PROT_CRC; + stats->rx_errors++; + } } priv->can.state = state; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 1405078..119e352 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -906,7 +906,6 @@ static int c_can_handle_bus_err(struct net_device *dev, priv->can.can_stats.bus_error++; stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - cf->data[2] |= CAN_ERR_PROT_UNSPEC; switch (lec_type) { case LEC_STUFF_ERROR: @@ -919,8 +918,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | - CAN_ERR_PROT_LOC_ACK_DEL); + cf->data[2] |= CAN_ERR_PROT_ACK; break; case LEC_BIT1_ERROR: netdev_dbg(dev, "bit1 error\n"); @@ -932,8 +930,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | - CAN_ERR_PROT_LOC_CRC_DEL); + cf->data[2] |= CAN_ERR_PROT_CRC; break; default: break; diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 731764f..1d67410 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -290,48 +290,42 @@ static void do_bus_err(struct net_device *dev, struct can_frame *cf, u32 reg_esr) { struct flexcan_priv *priv = netdev_priv(dev); - int rx_errors = 0, tx_errors = 0; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + cf->data[2] |= CAN_ERR_PROT_UNSPEC; if (reg_esr & FLEXCAN_ESR_BIT1_ERR) { dev_dbg(dev->dev.parent, "BIT1_ERR irq\n"); cf->data[2] |= CAN_ERR_PROT_BIT1; - tx_errors = 1; + dev->stats.tx_errors++; } if (reg_esr & FLEXCAN_ESR_BIT0_ERR) { dev_dbg(dev->dev.parent, "BIT0_ERR irq\n"); cf->data[2] |= CAN_ERR_PROT_BIT0; - tx_errors = 1; + dev->stats.tx_errors++; } if (reg_esr & FLEXCAN_ESR_ACK_ERR) { dev_dbg(dev->dev.parent, "ACK_ERR irq\n"); - cf->can_id |= CAN_ERR_ACK; - cf->data[3] |= CAN_ERR_PROT_LOC_ACK; - tx_errors = 1; + cf->data[2] |= CAN_ERR_PROT_ACK; + dev->stats.tx_errors++; } if (reg_esr & FLEXCAN_ESR_CRC_ERR) { dev_dbg(dev->dev.parent, "CRC_ERR irq\n"); - cf->data[2] |= CAN_ERR_PROT_BIT; - cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; - rx_errors = 1; + cf->data[2] |= CAN_ERR_PROT_CRC; + dev->stats.rx_errors++; } if (reg_esr & FLEXCAN_ESR_FRM_ERR) { dev_dbg(dev->dev.parent, "FRM_ERR irq\n"); cf->data[2] |= CAN_ERR_PROT_FORM; - rx_errors = 1; + dev->stats.rx_errors++; } if (reg_esr & FLEXCAN_ESR_STF_ERR) { dev_dbg(dev->dev.parent, "STF_ERR irq\n"); cf->data[2] |= CAN_ERR_PROT_STUFF; - rx_errors = 1; + dev->stats.rx_errors++; } priv->can.can_stats.bus_error++; - if (rx_errors) - dev->stats.rx_errors++; - if (tx_errors) - dev->stats.tx_errors++; } static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr) @@ -403,8 +397,8 @@ static void do_state(struct net_device *dev, switch (new_state) { case CAN_STATE_ERROR_ACTIVE: dev_dbg(dev->dev.parent, "Error Active\n"); - cf->can_id |= CAN_ERR_PROT; - cf->data[2] = CAN_ERR_PROT_ACTIVE; + cf->can_id |= CAN_ERR_CRTL; + cf->data[2] = CAN_ERR_CRTL_ACTIVE; break; case CAN_STATE_BUS_OFF: cf->can_id |= CAN_ERR_BUSOFF; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 366f5cc..99a1bc8 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -983,7 +983,6 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) dev_dbg(mod->dev, "bus error interrupt\n"); mod->can.can_stats.bus_error++; - stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; switch (ecc & ECC_MASK) { @@ -999,11 +998,30 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) default: cf->data[2] |= CAN_ERR_PROT_UNSPEC; cf->data[3] = ecc & ECC_SEG; + switch (cf->data[3]) { + case CAN_ERR_PROT_LOC_ACK: + case CAN_ERR_PROT_LOC_ACK_DEL: + cf->data[2] |= CAN_ERR_PROT_ACK; + break; + case CAN_ERR_PROT_LOC_CRC_SEQ: + case CAN_ERR_PROT_LOC_CRC_DEL: + cf->data[2] |= CAN_ERR_PROT_CRC; + break; + default: + cf->data[2] |= CAN_ERR_PROT_UNSPEC; + break; + } break; } - if ((ecc & ECC_DIR) == 0) + /* Error occured during transmission? */ + if ((ecc & ECC_DIR) == 0) { cf->data[2] |= CAN_ERR_PROT_TX; + stats->tx_errors++; + + } else { + stats->rx_errors++; + } cf->data[6] = txerr; cf->data[7] = rxerr; diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 042ecff..bf4d74a 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -535,36 +535,35 @@ static void pch_can_error(struct net_device *ndev, u32 status) } lec = status & PCH_LEC_ALL; - switch (lec) { - case PCH_STUF_ERR: - cf->data[2] |= CAN_ERR_PROT_STUFF; + if (lec) { priv->can.can_stats.bus_error++; - stats->rx_errors++; - break; - case PCH_FORM_ERR: - cf->data[2] |= CAN_ERR_PROT_FORM; - priv->can.can_stats.bus_error++; - stats->rx_errors++; - break; - case PCH_ACK_ERR: - cf->can_id |= CAN_ERR_ACK; - priv->can.can_stats.bus_error++; - stats->rx_errors++; - break; - case PCH_BIT1_ERR: - case PCH_BIT0_ERR: - cf->data[2] |= CAN_ERR_PROT_BIT; - priv->can.can_stats.bus_error++; - stats->rx_errors++; - break; - case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | - CAN_ERR_PROT_LOC_CRC_DEL; - priv->can.can_stats.bus_error++; - stats->rx_errors++; - break; - case PCH_LEC_ALL: /* Written by CPU. No error status */ - break; + cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; + + switch (lec) { + case PCH_STUF_ERR: + cf->data[2] |= CAN_ERR_PROT_STUFF; + stats->rx_errors++; + break; + case PCH_FORM_ERR: + cf->data[2] |= CAN_ERR_PROT_FORM; + stats->rx_errors++; + break; + case PCH_ACK_ERR: + cf->data[2] |= CAN_ERR_PROT_ACK; + stats->tx_errors++; + break; + case PCH_BIT1_ERR: + case PCH_BIT0_ERR: + cf->data[2] |= CAN_ERR_PROT_BIT; + stats->rx_errors++; + break; + case PCH_CRC_ERR: + cf->data[2] |= CAN_ERR_PROT_CRC; + stats->rx_errors++; + break; + case PCH_LEC_ALL: /* Written by CPU. No error status */ + break; + } } priv->can.state = state; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 1e6b3dd..f171e2d 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -404,7 +404,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) if (isrc & IRQ_BEI) { /* bus error interrupt */ priv->can.can_stats.bus_error++; - stats->rx_errors++; ecc = priv->read_reg(priv, REG_ECC); @@ -421,13 +420,31 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) cf->data[2] |= CAN_ERR_PROT_STUFF; break; default: - cf->data[2] |= CAN_ERR_PROT_UNSPEC; cf->data[3] = ecc & ECC_SEG; + switch (cf->data[3]) { + case CAN_ERR_PROT_LOC_ACK: + case CAN_ERR_PROT_LOC_ACK_DEL: + cf->data[2] |= CAN_ERR_PROT_ACK; + break; + case CAN_ERR_PROT_LOC_CRC_SEQ: + case CAN_ERR_PROT_LOC_CRC_DEL: + cf->data[2] |= CAN_ERR_PROT_CRC; + break; + default: + cf->data[2] |= CAN_ERR_PROT_UNSPEC; + break; + } break; } + /* Error occured during transmission? */ - if ((ecc & ECC_DIR) == 0) + if ((ecc & ECC_DIR) == 0) { cf->data[2] |= CAN_ERR_PROT_TX; + stats->tx_errors++; + + } else { + stats->rx_errors++; + } } if (isrc & IRQ_EPI) { /* error passive interrupt */ diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 871ad92..762ff7f 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -734,24 +734,27 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, if (err_status & HECC_CANES_FE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_FE); cf->data[2] |= CAN_ERR_PROT_FORM; + stats->rx_errors++; } if (err_status & HECC_CANES_BE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_BE); cf->data[2] |= CAN_ERR_PROT_BIT; + stats->tx_errors++; } if (err_status & HECC_CANES_SE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_SE); cf->data[2] |= CAN_ERR_PROT_STUFF; + stats->rx_errors++; } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | - CAN_ERR_PROT_LOC_CRC_DEL; + cf->data[2] |= CAN_ERR_PROT_CRC; + stats->rx_errors++; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | - CAN_ERR_PROT_LOC_ACK_DEL; + cf->data[2] |= CAN_ERR_PROT_ACK; + stats->tx_errors++; } } diff --git a/include/linux/can/error.h b/include/linux/can/error.h index d4127fd..b74e85a 100644 --- a/include/linux/can/error.h +++ b/include/linux/can/error.h @@ -14,6 +14,8 @@ #ifndef CAN_ERROR_H #define CAN_ERROR_H +#define CAN_ERR_VERSION 1 + #define CAN_ERR_DLC 8 /* dlc for error frames */ /* error class (mask) in can_id */ @@ -22,7 +24,6 @@ #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */ #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */ #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */ -#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */ #define CAN_ERR_BUSOFF 0x00000040U /* bus off */ #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */ #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */ @@ -41,6 +42,7 @@ #define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */ /* (at least one error counter exceeds */ /* the protocol-defined level of 127) */ +#define CAN_ERR_CRTL_ACTIVE 0x40 /* active error announcement */ /* error in CAN protocol (type) / data[2] */ #define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */ @@ -49,8 +51,8 @@ #define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */ #define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */ #define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */ -#define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */ -#define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */ +#define CAN_ERR_PROT_CRC 0x20 /* CRC error */ +#define CAN_ERR_PROT_ACK 0x40 /* received no ACK on transmission */ #define CAN_ERR_PROT_TX 0x80 /* error occured on transmission */ /* error in CAN protocol (location) / data[3] */ -- 1.7.2.3
_______________________________________________ Socketcan-core mailing list [email protected] https://lists.berlios.de/mailman/listinfo/socketcan-core
