diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2022-01-04 18:28:00 +0300 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2022-01-08 23:22:26 +0300 |
commit | 1c45f5778a3be5a67e8b318ab83664014ffa1f3e (patch) | |
tree | d5e02608a80420e0cc53339e40934297fe175c16 /drivers/net/can/flexcan/flexcan-ethtool.c | |
parent | c5c88591040ee7d84d037328eed9019d3ffab821 (diff) | |
download | linux-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.c | 93 |
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; +} |