On Thu, 9 May 2024, Christoph Fritz wrote: > A LIN node can work as commander or responder, so introduce a new > control mode (CAN_CTRLMODE_LIN_COMMANDER) for configuration. > > This enables e.g. the userland tool ip from iproute2 to turn on > commander mode when the device is being brought up. > > Signed-off-by: Christoph Fritz <christoph.fritz@xxxxxxxxx> > --- > drivers/net/can/lin.c | 40 +++++++++++++++++++++++++++++++- > include/net/lin.h | 7 ++++++ > include/uapi/linux/can/netlink.h | 1 + > 3 files changed, 47 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/can/lin.c b/drivers/net/can/lin.c > index f77abd7d7d21c..03ddf5d5a31b8 100644 > --- a/drivers/net/can/lin.c > +++ b/drivers/net/can/lin.c > @@ -262,11 +262,40 @@ static netdev_tx_t lin_start_xmit(struct sk_buff *skb, > return NETDEV_TX_OK; > } > > +static int lin_update_mode(struct net_device *ndev) > +{ > + struct lin_device *ldev = netdev_priv(ndev); > + u32 ctrlmode = ldev->can.ctrlmode; > + enum lin_mode lm; > + int ret = 0; > + > + lm = (ctrlmode & CAN_CTRLMODE_LIN_COMMANDER) ? LINBUS_COMMANDER : > + LINBUS_RESPONDER; > + if (ldev->lmode != lm) { > + if (!ldev->ldev_ops->update_lin_mode) { > + netdev_err(ndev, "setting lin mode unsupported\n"); In user visible messages, it would be best to use the expected capitalization, which I suppose is LIN given you use capitals in the commit message yourself? > + return -EINVAL; > + } > + ret = ldev->ldev_ops->update_lin_mode(ldev, lm); > + if (ret) { > + netdev_err(ndev, "Failed to set lin mode: %d\n", ret); Ditto. There might be other cases in any of the patches, please check. > + return ret; > + } > + ldev->lmode = lm; > + } > + > + return ret; > +} > + > static int lin_open(struct net_device *ndev) > { > struct lin_device *ldev = netdev_priv(ndev); > int ret; > > + ret = lin_update_mode(ndev); > + if (ret) > + return ret; > + > ldev->tx_busy = false; > > ret = open_candev(ndev); > @@ -443,7 +472,7 @@ struct lin_device *register_lin(struct device *dev, > ndev->sysfs_groups[0] = &lin_sysfs_group; > ldev->can.bittiming.bitrate = LIN_DEFAULT_BAUDRATE; > ldev->can.ctrlmode = CAN_CTRLMODE_LIN; > - ldev->can.ctrlmode_supported = 0; > + ldev->can.ctrlmode_supported = CAN_CTRLMODE_LIN_COMMANDER; > ldev->can.bitrate_const = lin_bitrate; > ldev->can.bitrate_const_cnt = ARRAY_SIZE(lin_bitrate); > ldev->can.do_set_bittiming = lin_set_bittiming; > @@ -458,6 +487,15 @@ struct lin_device *register_lin(struct device *dev, > goto exit_candev; > } > > + ldev->lmode = LINBUS_RESPONDER; > + if (ldev->ldev_ops->update_lin_mode) { > + ret = ldev->ldev_ops->update_lin_mode(ldev, ldev->lmode); > + if (ret) { > + netdev_err(ndev, "updating lin mode failed\n"); Ditto. > + goto exit_candev; > + } > + } > + > ret = register_candev(ndev); > if (ret) > goto exit_candev; > diff --git a/include/net/lin.h b/include/net/lin.h > index 31bb0feefd188..63ac870a0ab6f 100644 > --- a/include/net/lin.h > +++ b/include/net/lin.h > @@ -36,6 +36,11 @@ struct lin_attr { > struct lin_device *ldev; > }; > > +enum lin_mode { > + LINBUS_RESPONDER = 0, > + LINBUS_COMMANDER, > +}; > + > struct lin_device { > struct can_priv can; /* must be the first member */ > struct net_device *ndev; > @@ -45,6 +50,7 @@ struct lin_device { > struct work_struct tx_work; > bool tx_busy; > struct sk_buff *tx_skb; > + enum lin_mode lmode; > }; > > enum lin_checksum_mode { > @@ -71,6 +77,7 @@ struct lin_device_ops { > int (*ldo_open)(struct lin_device *ldev); > int (*ldo_stop)(struct lin_device *ldev); > int (*ldo_tx)(struct lin_device *ldev, const struct lin_frame *frame); > + int (*update_lin_mode)(struct lin_device *ldev, enum lin_mode lm); > int (*update_bitrate)(struct lin_device *ldev, u16 bitrate); > int (*update_responder_answer)(struct lin_device *ldev, > const struct lin_responder_answer *answ); > diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h > index a37f56d86c5f2..cc390f6444d59 100644 > --- a/include/uapi/linux/can/netlink.h > +++ b/include/uapi/linux/can/netlink.h > @@ -104,6 +104,7 @@ struct can_ctrlmode { > #define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */ > #define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */ > #define CAN_CTRLMODE_LIN BIT(11) /* LIN bus mode */ > +#define CAN_CTRLMODE_LIN_COMMANDER BIT(12) /* LIN bus specific commander mode */ > > /* > * CAN device statistics > -- i.