lkml.org 
[lkml]   [2022]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH v3 8/9] can: slcan: add support to set bit time register (btr)
Date
It allows to set the bit time register with tunable values.
The setting can only be changed if the interface is down:

ip link set dev can0 down
ethtool --set-tunable can0 can-btr 0x31c
ip link set dev can0 up

Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

(no changes since v1)

drivers/net/can/slcan/slcan-core.c | 58 ++++++++++++++++++++-------
drivers/net/can/slcan/slcan-ethtool.c | 13 ++++++
drivers/net/can/slcan/slcan.h | 1 +
3 files changed, 58 insertions(+), 14 deletions(-)

diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
index 45e521910236..3905f21e7788 100644
--- a/drivers/net/can/slcan/slcan-core.c
+++ b/drivers/net/can/slcan/slcan-core.c
@@ -99,6 +99,7 @@ struct slcan {
#define CF_ERR_RST 0 /* Reset errors on open */
wait_queue_head_t xcmd_wait; /* Wait queue for commands */
/* transmission */
+ u32 btr; /* bit timing register */
};

static const u32 slcan_bitrate_const[] = {
@@ -128,6 +129,17 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
return 0;
}

+int slcan_set_btr(struct net_device *ndev, u32 btr)
+{
+ struct slcan *sl = netdev_priv(ndev);
+
+ if (netif_running(ndev))
+ return -EBUSY;
+
+ sl->btr = btr;
+ return 0;
+}
+
/*************************************************************************
* SLCAN ENCAPSULATION FORMAT *
*************************************************************************/
@@ -699,22 +711,40 @@ static int slcan_netdev_open(struct net_device *dev)
return err;
}

- if (sl->can.bittiming.bitrate != CAN_BITRATE_UNKNOWN) {
- for (s = 0; s < ARRAY_SIZE(slcan_bitrate_const); s++) {
- if (sl->can.bittiming.bitrate == slcan_bitrate_const[s])
- break;
+ if (sl->can.bittiming.bitrate != CAN_BITRATE_UNKNOWN || sl->btr) {
+ if (sl->can.bittiming.bitrate != CAN_BITRATE_UNKNOWN) {
+ for (s = 0; s < ARRAY_SIZE(slcan_bitrate_const); s++) {
+ if (sl->can.bittiming.bitrate ==
+ slcan_bitrate_const[s])
+ break;
+ }
+
+ /* The CAN framework has already validate the bitrate
+ * value, so we can avoid to check if `s' has been
+ * properly set.
+ */
+ snprintf(cmd, sizeof(cmd), "C\rS%d\r", s);
+ err = slcan_transmit_cmd(sl, cmd);
+ if (err) {
+ netdev_err(dev,
+ "failed to send bitrate command 'C\\rS%d\\r'\n",
+ s);
+ goto cmd_transmit_failed;
+ }
}

- /* The CAN framework has already validate the bitrate value,
- * so we can avoid to check if `s' has been properly set.
- */
- snprintf(cmd, sizeof(cmd), "C\rS%d\r", s);
- err = slcan_transmit_cmd(sl, cmd);
- if (err) {
- netdev_err(dev,
- "failed to send bitrate command 'C\\rS%d\\r'\n",
- s);
- goto cmd_transmit_failed;
+ if (sl->btr) {
+ u32 btr = sl->btr & GENMASK(15, 0);
+
+ snprintf(cmd, sizeof(cmd), "C\rs%04x\r", btr);
+ err = slcan_transmit_cmd(sl, cmd);
+ if (err) {
+ netdev_err(dev,
+ "failed to send bit timing command 'C\\rs%04x\\r'\n",
+ btr);
+ goto cmd_transmit_failed;
+ }
+
}

if (test_bit(CF_ERR_RST, &sl->cmd_flags)) {
diff --git a/drivers/net/can/slcan/slcan-ethtool.c b/drivers/net/can/slcan/slcan-ethtool.c
index bf0afdc4e49d..8e2e77bbffda 100644
--- a/drivers/net/can/slcan/slcan-ethtool.c
+++ b/drivers/net/can/slcan/slcan-ethtool.c
@@ -52,11 +52,24 @@ static int slcan_get_sset_count(struct net_device *netdev, int sset)
}
}

+static int slcan_set_tunable(struct net_device *netdev,
+ const struct ethtool_tunable *tuna,
+ const void *data)
+{
+ switch (tuna->id) {
+ case ETHTOOL_CAN_BTR:
+ return slcan_set_btr(netdev, *(u32 *)data);
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct ethtool_ops slcan_ethtool_ops = {
.get_strings = slcan_get_strings,
.get_priv_flags = slcan_get_priv_flags,
.set_priv_flags = slcan_set_priv_flags,
.get_sset_count = slcan_get_sset_count,
+ .set_tunable = slcan_set_tunable,
};

void slcan_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/can/slcan/slcan.h b/drivers/net/can/slcan/slcan.h
index d463c8d99e22..1ac412fe8c95 100644
--- a/drivers/net/can/slcan/slcan.h
+++ b/drivers/net/can/slcan/slcan.h
@@ -13,6 +13,7 @@

bool slcan_err_rst_on_open(struct net_device *ndev);
int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on);
+int slcan_set_btr(struct net_device *ndev, u32 btr);
void slcan_set_ethtool_ops(struct net_device *ndev);

#endif /* _SLCAN_H */
--
2.32.0
\
 
 \ /
  Last update: 2022-07-26 23:05    [W:0.168 / U:0.080 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site