1 // SPDX-License-Identifier: GPL-2.0
3 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
5 // Copyright (c) 2021, 2022 Pengutronix,
6 // Marc Kleine-Budde <kernel@pengutronix.de>
9 #include <linux/ethtool.h>
11 #include "mcp251xfd.h"
12 #include "mcp251xfd-ram.h"
15 mcp251xfd_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
)
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
;
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
;
28 ring
->rx_pending
= priv
->rx_obj_num
;
29 ring
->tx_pending
= priv
->tx
->obj_num
;
33 mcp251xfd_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
)
38 struct mcp251xfd_priv
*priv
= netdev_priv(ndev
);
39 const bool fd_mode
= mcp251xfd_is_fd_mode(priv
);
40 struct can_ram_layout layout
;
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
) &&
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
;
56 static 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
)
61 struct mcp251xfd_priv
*priv
= netdev_priv(ndev
);
62 u32 rx_max_frames
, tx_max_frames
;
64 /* The ethtool doc says:
65 * To disable coalescing, set usecs = 0 and max_frames = 1.
67 if (priv
->rx_obj_num_coalesce_irq
== 0)
70 rx_max_frames
= priv
->rx_obj_num_coalesce_irq
;
72 ec
->rx_max_coalesced_frames_irq
= rx_max_frames
;
73 ec
->rx_coalesce_usecs_irq
= priv
->rx_coalesce_usecs_irq
;
75 if (priv
->tx_obj_num_coalesce_irq
== 0)
78 tx_max_frames
= priv
->tx_obj_num_coalesce_irq
;
80 ec
->tx_max_coalesced_frames_irq
= tx_max_frames
;
81 ec
->tx_coalesce_usecs_irq
= priv
->tx_coalesce_usecs_irq
;
86 static 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
)
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
,
97 struct can_ram_layout layout
;
99 can_ram_get_layout(&layout
, &mcp251xfd_ram_config
, &ring
, ec
, fd_mode
);
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
) &&
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
;
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
;
119 static 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
,
131 void mcp251xfd_ethtool_init(struct mcp251xfd_priv
*priv
)
133 struct can_ram_layout layout
;
135 priv
->ndev
->ethtool_ops
= &mcp251xfd_ethtool_ops
;
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
;
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;