Thread (9 messages) 9 messages, 4 authors, 2022-08-31

Re: [RFC PATCH v2 4/4] can: bxcan: add support for ST bxCAN controller

From: Vincent Mailhol <hidden>
Date: 2022-08-26 21:57:02
Also in: linux-can, lkml

On Sat. 20 Aug. 2022 à 17:32, Dario Binacchi
[off-list ref] a écrit :
Add support for the basic extended CAN controller (bxCAN) found in many
low- to middle-end STM32 SoCs. It supports the Basic Extended CAN
protocol versions 2.0A and B with a maximum bit rate of 1 Mbit/s.

The controller supports two channels (CAN1 as master and CAN2 as slave)
and the driver can enable either or both of the channels. They share
some of the required logic (e. g. clocks and filters), and that means
you cannot use the slave CAN without enabling some hardware resources
managed by the master CAN.

Each channel has 3 transmit mailboxes, 2 receive FIFOs with 3 stages and
28 scalable filter banks.
It also manages 4 dedicated interrupt vectors:
- transmit interrupt
- FIFO 0 receive interrupt
- FIFO 1 receive interrupt
- status change error interrupt

Driver uses all 3 available mailboxes for transmission and FIFO 0 for
reception. Rx filter rules are configured to the minimum. They accept
all messages and assign filter 0 to CAN1 and filter 14 to CAN2 in
identifier mask mode with 32 bits width. It enables and uses transmit,
receive buffers for FIFO 0 and error and status change interrupts.

Signed-off-by: Dario Binacchi <redacted>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---
(...)
+static void bxcan_handle_state_change(struct net_device *ndev, u32 esr)
+{
+       struct bxcan_priv *priv = netdev_priv(ndev);
+       struct net_device_stats *stats = &ndev->stats;
+       enum can_state new_state = priv->can.state;
+       struct can_berr_counter bec;
+       enum can_state rx_state, tx_state;
+       struct sk_buff *skb;
+       struct can_frame *cf;
+
+       /* Early exit if no error flag is set */
+       if (!(esr & (BXCAN_ESR_EWGF | BXCAN_ESR_EPVF | BXCAN_ESR_BOFF)))
+               return;
+
+       bec.txerr = BXCAN_TEC(esr);
+       bec.rxerr = BXCAN_REC(esr);
+
+       if (esr & BXCAN_ESR_BOFF)
+               new_state = CAN_STATE_BUS_OFF;
+       else if (esr & BXCAN_ESR_EPVF)
+               new_state = CAN_STATE_ERROR_PASSIVE;
+       else if (esr & BXCAN_ESR_EWGF)
+               new_state = CAN_STATE_ERROR_WARNING;
+
+       /* state hasn't changed */
+       if (unlikely(new_state == priv->can.state))
+               return;
+
+       skb = alloc_can_err_skb(ndev, &cf);
+       if (unlikely(!skb))
+               return;
+
+       tx_state = bec.txerr >= bec.rxerr ? new_state : 0;
+       rx_state = bec.txerr <= bec.rxerr ? new_state : 0;
+       can_change_state(ndev, cf, tx_state, rx_state);
+
+       if (new_state == CAN_STATE_BUS_OFF)
+               can_bus_off(ndev);
+
+       stats->rx_bytes += cf->len;
Please do not increment the stats if the frame is remote (c.f. CAN_RTR_FLAG).
+       stats->rx_packets++;
+       netif_rx(skb);
+}

Yours sincerely,
Vincent Mailhol
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help