File Index
Files and directories
Sign in
FILE

mcp251xfd-ethtool.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c C
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
  4//
  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 void
 15mcp251xfd_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 int
 33mcp251xfd_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	else
 70		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	else
 78		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}
~/ Read-only file preview.