summaryrefslogtreecommitdiff
path: root/drivers/net/can/flexcan/flexcan-ethtool.c
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2022-01-04 18:28:00 +0300
committerMarc Kleine-Budde <mkl@pengutronix.de>2022-01-08 23:22:26 +0300
commit1c45f5778a3be5a67e8b318ab83664014ffa1f3e (patch)
treed5e02608a80420e0cc53339e40934297fe175c16 /drivers/net/can/flexcan/flexcan-ethtool.c
parentc5c88591040ee7d84d037328eed9019d3ffab821 (diff)
downloadlinux-1c45f5778a3be5a67e8b318ab83664014ffa1f3e.tar.xz
can: flexcan: add ethtool support to change rx-rtr setting during runtime
This patch adds a private flag to the flexcan driver to switch the "rx-rtr" setting on and off. "rx-rtr" on - Receive RTR frames. (default) The CAN controller can and will receive RTR frames. On some IP cores the controller cannot receive RTR frames in the more performant "RX mailbox" mode and will use "RX FIFO" mode instead. "rx-rtr" off - Waive ability to receive RTR frames. (not supported on all IP cores) This mode activates the "RX mailbox mode" for better performance, on some IP cores RTR frames cannot be received anymore. The "RX FIFO" mode uses a FIFO with a depth of 6 CAN frames. The "RX mailbox" mode uses up to 62 mailboxes. Link: https://lore.kernel.org/all/20220107193105.1699523-6-mkl@pengutronix.de Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com> Co-developed-by: Dario Binacchi <dario.binacchi@amarulasolutions.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/flexcan/flexcan-ethtool.c')
-rw-r--r--drivers/net/can/flexcan/flexcan-ethtool.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/net/can/flexcan/flexcan-ethtool.c b/drivers/net/can/flexcan/flexcan-ethtool.c
new file mode 100644
index 000000000000..d01347fbfaa9
--- /dev/null
+++ b/drivers/net/can/flexcan/flexcan-ethtool.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2022 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
+ * Copyright (c) 2022 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ */
+
+#include <linux/can/dev.h>
+#include <linux/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#include "flexcan.h"
+
+static const char flexcan_priv_flags_strings[][ETH_GSTRING_LEN] = {
+#define FLEXCAN_PRIV_FLAGS_RX_RTR BIT(0)
+ "rx-rtr",
+};
+
+static void
+flexcan_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+ switch (stringset) {
+ case ETH_SS_PRIV_FLAGS:
+ memcpy(data, flexcan_priv_flags_strings,
+ sizeof(flexcan_priv_flags_strings));
+ }
+}
+
+static u32 flexcan_get_priv_flags(struct net_device *ndev)
+{
+ const struct flexcan_priv *priv = netdev_priv(ndev);
+ u32 priv_flags = 0;
+
+ if (flexcan_active_rx_rtr(priv))
+ priv_flags |= FLEXCAN_PRIV_FLAGS_RX_RTR;
+
+ return priv_flags;
+}
+
+static int flexcan_set_priv_flags(struct net_device *ndev, u32 priv_flags)
+{
+ struct flexcan_priv *priv = netdev_priv(ndev);
+ u32 quirks = priv->devtype_data.quirks;
+
+ if (priv_flags & FLEXCAN_PRIV_FLAGS_RX_RTR) {
+ if (flexcan_supports_rx_mailbox_rtr(priv))
+ quirks |= FLEXCAN_QUIRK_USE_RX_MAILBOX;
+ else if (flexcan_supports_rx_fifo(priv))
+ quirks &= ~FLEXCAN_QUIRK_USE_RX_MAILBOX;
+ else
+ quirks |= FLEXCAN_QUIRK_USE_RX_MAILBOX;
+ } else {
+ if (flexcan_supports_rx_mailbox(priv))
+ quirks |= FLEXCAN_QUIRK_USE_RX_MAILBOX;
+ else
+ quirks &= ~FLEXCAN_QUIRK_USE_RX_MAILBOX;
+ }
+
+ if (quirks != priv->devtype_data.quirks && netif_running(ndev))
+ return -EBUSY;
+
+ priv->devtype_data.quirks = quirks;
+
+ if (!(priv_flags & FLEXCAN_PRIV_FLAGS_RX_RTR) &&
+ !flexcan_active_rx_rtr(priv))
+ netdev_info(ndev,
+ "Activating RX mailbox mode, cannot receive RTR frames.\n");
+
+ return 0;
+}
+
+static int flexcan_get_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_PRIV_FLAGS:
+ return ARRAY_SIZE(flexcan_priv_flags_strings);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct ethtool_ops flexcan_ethtool_ops = {
+ .get_strings = flexcan_get_strings,
+ .get_priv_flags = flexcan_get_priv_flags,
+ .set_priv_flags = flexcan_set_priv_flags,
+ .get_sset_count = flexcan_get_sset_count,
+};
+
+void flexcan_set_ethtool_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &flexcan_ethtool_ops;
+}