Message ID | 20240509171736.2048414-11-christoph.fritz@hexdev.de (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | LIN Bus support for Linux | expand |
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@hexdev.de> > --- > 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 >
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"); + return -EINVAL; + } + ret = ldev->ldev_ops->update_lin_mode(ldev, lm); + if (ret) { + netdev_err(ndev, "Failed to set lin mode: %d\n", ret); + 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"); + 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
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@hexdev.de> --- 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(-)