brintos

brintos / linux-shallow public Read only

0
0
Text · 4.4 KiB · 57eeb06 Raw
146 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// mcp251xfd - Microchip MCP251xFD Family CAN controller driver4//5// Copyright (c) 2021, 2022 Pengutronix,6//               Marc Kleine-Budde <kernel@pengutronix.de>7//8 9#include <linux/ethtool.h>10 11#include "mcp251xfd.h"12#include "mcp251xfd-ram.h"13 14static void15mcp251xfd_ring_get_ringparam(struct net_device *ndev,16			     struct ethtool_ringparam *ring,17			     struct kernel_ethtool_ringparam *kernel_ring,18			     struct netlink_ext_ack *extack)19{20	const struct mcp251xfd_priv *priv = netdev_priv(ndev);21	const bool fd_mode = mcp251xfd_is_fd_mode(priv);22	struct can_ram_layout layout;23 24	can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);25	ring->rx_max_pending = layout.max_rx;26	ring->tx_max_pending = layout.max_tx;27 28	ring->rx_pending = priv->rx_obj_num;29	ring->tx_pending = priv->tx->obj_num;30}31 32static int33mcp251xfd_ring_set_ringparam(struct net_device *ndev,34			     struct ethtool_ringparam *ring,35			     struct kernel_ethtool_ringparam *kernel_ring,36			     struct netlink_ext_ack *extack)37{38	struct mcp251xfd_priv *priv = netdev_priv(ndev);39	const bool fd_mode = mcp251xfd_is_fd_mode(priv);40	struct can_ram_layout layout;41 42	can_ram_get_layout(&layout, &mcp251xfd_ram_config, ring, NULL, fd_mode);43	if ((layout.cur_rx != priv->rx_obj_num ||44	     layout.cur_tx != priv->tx->obj_num) &&45	    netif_running(ndev))46		return -EBUSY;47 48	priv->rx_obj_num = layout.cur_rx;49	priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;50	priv->tx->obj_num = layout.cur_tx;51	priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;52 53	return 0;54}55 56static int mcp251xfd_ring_get_coalesce(struct net_device *ndev,57				       struct ethtool_coalesce *ec,58				       struct kernel_ethtool_coalesce *kec,59				       struct netlink_ext_ack *ext_ack)60{61	struct mcp251xfd_priv *priv = netdev_priv(ndev);62	u32 rx_max_frames, tx_max_frames;63 64	/* The ethtool doc says:65	 * To disable coalescing, set usecs = 0 and max_frames = 1.66	 */67	if (priv->rx_obj_num_coalesce_irq == 0)68		rx_max_frames = 1;69	else70		rx_max_frames = priv->rx_obj_num_coalesce_irq;71 72	ec->rx_max_coalesced_frames_irq = rx_max_frames;73	ec->rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq;74 75	if (priv->tx_obj_num_coalesce_irq == 0)76		tx_max_frames = 1;77	else78		tx_max_frames = priv->tx_obj_num_coalesce_irq;79 80	ec->tx_max_coalesced_frames_irq = tx_max_frames;81	ec->tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq;82 83	return 0;84}85 86static int mcp251xfd_ring_set_coalesce(struct net_device *ndev,87				       struct ethtool_coalesce *ec,88				       struct kernel_ethtool_coalesce *kec,89				       struct netlink_ext_ack *ext_ack)90{91	struct mcp251xfd_priv *priv = netdev_priv(ndev);92	const bool fd_mode = mcp251xfd_is_fd_mode(priv);93	const struct ethtool_ringparam ring = {94		.rx_pending = priv->rx_obj_num,95		.tx_pending = priv->tx->obj_num,96	};97	struct can_ram_layout layout;98 99	can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, ec, fd_mode);100 101	if ((layout.rx_coalesce != priv->rx_obj_num_coalesce_irq ||102	     ec->rx_coalesce_usecs_irq != priv->rx_coalesce_usecs_irq ||103	     layout.tx_coalesce != priv->tx_obj_num_coalesce_irq ||104	     ec->tx_coalesce_usecs_irq != priv->tx_coalesce_usecs_irq) &&105	    netif_running(ndev))106		return -EBUSY;107 108	priv->rx_obj_num = layout.cur_rx;109	priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;110	priv->rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq;111 112	priv->tx->obj_num = layout.cur_tx;113	priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;114	priv->tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq;115 116	return 0;117}118 119static const struct ethtool_ops mcp251xfd_ethtool_ops = {120	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |121		ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ |122		ETHTOOL_COALESCE_TX_USECS_IRQ |123		ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,124	.get_ringparam = mcp251xfd_ring_get_ringparam,125	.set_ringparam = mcp251xfd_ring_set_ringparam,126	.get_coalesce = mcp251xfd_ring_get_coalesce,127	.set_coalesce = mcp251xfd_ring_set_coalesce,128	.get_ts_info = can_ethtool_op_get_ts_info_hwts,129};130 131void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)132{133	struct can_ram_layout layout;134 135	priv->ndev->ethtool_ops = &mcp251xfd_ethtool_ops;136 137	can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, false);138	priv->rx_obj_num = layout.default_rx;139	priv->tx->obj_num = layout.default_tx;140 141	priv->rx_obj_num_coalesce_irq = 0;142	priv->tx_obj_num_coalesce_irq = 0;143	priv->rx_coalesce_usecs_irq = 0;144	priv->tx_coalesce_usecs_irq = 0;145}146