14de0e8efSDario Binacchi // SPDX-License-Identifier: GPL-2.0+
24de0e8efSDario Binacchi /* Copyright (c) 2022 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
34de0e8efSDario Binacchi  *
44de0e8efSDario Binacchi  */
54de0e8efSDario Binacchi 
64de0e8efSDario Binacchi #include <linux/can/dev.h>
74de0e8efSDario Binacchi #include <linux/ethtool.h>
84de0e8efSDario Binacchi #include <linux/kernel.h>
94de0e8efSDario Binacchi #include <linux/netdevice.h>
104de0e8efSDario Binacchi #include <linux/platform_device.h>
114de0e8efSDario Binacchi 
124de0e8efSDario Binacchi #include "slcan.h"
134de0e8efSDario Binacchi 
144de0e8efSDario Binacchi static const char slcan_priv_flags_strings[][ETH_GSTRING_LEN] = {
154de0e8efSDario Binacchi #define SLCAN_PRIV_FLAGS_ERR_RST_ON_OPEN BIT(0)
164de0e8efSDario Binacchi 	"err-rst-on-open",
174de0e8efSDario Binacchi };
184de0e8efSDario Binacchi 
slcan_get_strings(struct net_device * ndev,u32 stringset,u8 * data)194de0e8efSDario Binacchi static void slcan_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
204de0e8efSDario Binacchi {
214de0e8efSDario Binacchi 	switch (stringset) {
224de0e8efSDario Binacchi 	case ETH_SS_PRIV_FLAGS:
234de0e8efSDario Binacchi 		memcpy(data, slcan_priv_flags_strings,
244de0e8efSDario Binacchi 		       sizeof(slcan_priv_flags_strings));
254de0e8efSDario Binacchi 	}
264de0e8efSDario Binacchi }
274de0e8efSDario Binacchi 
slcan_get_priv_flags(struct net_device * ndev)284de0e8efSDario Binacchi static u32 slcan_get_priv_flags(struct net_device *ndev)
294de0e8efSDario Binacchi {
304de0e8efSDario Binacchi 	u32 flags = 0;
314de0e8efSDario Binacchi 
324de0e8efSDario Binacchi 	if (slcan_err_rst_on_open(ndev))
334de0e8efSDario Binacchi 		flags |= SLCAN_PRIV_FLAGS_ERR_RST_ON_OPEN;
344de0e8efSDario Binacchi 
354de0e8efSDario Binacchi 	return flags;
364de0e8efSDario Binacchi }
374de0e8efSDario Binacchi 
slcan_set_priv_flags(struct net_device * ndev,u32 flags)384de0e8efSDario Binacchi static int slcan_set_priv_flags(struct net_device *ndev, u32 flags)
394de0e8efSDario Binacchi {
404de0e8efSDario Binacchi 	bool err_rst_op_open = !!(flags & SLCAN_PRIV_FLAGS_ERR_RST_ON_OPEN);
414de0e8efSDario Binacchi 
424de0e8efSDario Binacchi 	return slcan_enable_err_rst_on_open(ndev, err_rst_op_open);
434de0e8efSDario Binacchi }
444de0e8efSDario Binacchi 
slcan_get_sset_count(struct net_device * netdev,int sset)454de0e8efSDario Binacchi static int slcan_get_sset_count(struct net_device *netdev, int sset)
464de0e8efSDario Binacchi {
474de0e8efSDario Binacchi 	switch (sset) {
484de0e8efSDario Binacchi 	case ETH_SS_PRIV_FLAGS:
494de0e8efSDario Binacchi 		return ARRAY_SIZE(slcan_priv_flags_strings);
504de0e8efSDario Binacchi 	default:
514de0e8efSDario Binacchi 		return -EOPNOTSUPP;
524de0e8efSDario Binacchi 	}
534de0e8efSDario Binacchi }
544de0e8efSDario Binacchi 
551851532fSVincent Mailhol const struct ethtool_ops slcan_ethtool_ops = {
564de0e8efSDario Binacchi 	.get_strings = slcan_get_strings,
574de0e8efSDario Binacchi 	.get_priv_flags = slcan_get_priv_flags,
584de0e8efSDario Binacchi 	.set_priv_flags = slcan_set_priv_flags,
594de0e8efSDario Binacchi 	.get_sset_count = slcan_get_sset_count,
60*409c188cSVincent Mailhol 	.get_ts_info = ethtool_op_get_ts_info,
614de0e8efSDario Binacchi };
62