On Wed. 4 Oct. 2023, 18:24, Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> wrote: > Some CAN controllers do not have a register that contains the current > CAN state, but only a register that contains the error counters. > > Introduce a new function can_state_get_by_berr_counter() that returns > the current TX and RX state depending on the provided CAN bit error > counters. > > Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> > --- > drivers/net/can/dev/dev.c | 22 ++++++++++++++++++++++ > include/linux/can/dev.h | 4 ++++ > 2 files changed, 26 insertions(+) > > diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c > index 7f9334a8af50..6242424fadbc 100644 > --- a/drivers/net/can/dev/dev.c > +++ b/drivers/net/can/dev/dev.c > @@ -90,6 +90,28 @@ const char *can_get_state_str(const enum can_state state) > } > EXPORT_SYMBOL_GPL(can_get_state_str); > > +static enum can_state can_state_err_to_state(u16 err) > +{ > + if (err < 96) > + return CAN_STATE_ERROR_ACTIVE; > + if (err < 128) > + return CAN_STATE_ERROR_WARNING; > + if (err < 256) > + return CAN_STATE_ERROR_PASSIVE; Please use the macros from include/uapi/linux/can/error.h. https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/can/error.h#L130 > + return CAN_STATE_BUS_OFF; > +} > + > +void can_state_get_by_berr_counter(const struct net_device *dev, > + const struct can_berr_counter *bec, > + enum can_state *tx_state, > + enum can_state *rx_state) > +{ > + *tx_state = can_state_err_to_state(bec->txerr); > + *rx_state = can_state_err_to_state(bec->rxerr); > +} > +EXPORT_SYMBOL_GPL(can_state_get_by_berr_counter); > + > void can_change_state(struct net_device *dev, struct can_frame *cf, > enum can_state tx_state, enum can_state rx_state) > { > diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h > index 982ba245eb41..1b92aed49363 100644 > --- a/include/linux/can/dev.h > +++ b/include/linux/can/dev.h > @@ -195,6 +195,10 @@ int can_restart_now(struct net_device *dev); > void can_bus_off(struct net_device *dev); > > const char *can_get_state_str(const enum can_state state); > +void can_state_get_by_berr_counter(const struct net_device *dev, > + const struct can_berr_counter *bec, > + enum can_state *tx_state, > + enum can_state *rx_state); > void can_change_state(struct net_device *dev, struct can_frame *cf, > enum can_state tx_state, enum can_state rx_state);