Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
   1// SPDX-License-Identifier: GPL-2.0
   2/* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver ethtool ops
   3 *
   4 * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
   5 *
   6 */
   7
   8#include <linux/net_tstamp.h>
   9#include <linux/phylink.h>
  10#include <linux/platform_device.h>
  11#include <linux/pm_runtime.h>
  12
  13#include "am65-cpsw-nuss.h"
  14#include "am65-cpsw-qos.h"
  15#include "cpsw_ale.h"
  16#include "am65-cpts.h"
  17
  18#define AM65_CPSW_REGDUMP_VER 0x1
  19
  20enum {
  21	AM65_CPSW_REGDUMP_MOD_NUSS = 1,
  22	AM65_CPSW_REGDUMP_MOD_RGMII_STATUS = 2,
  23	AM65_CPSW_REGDUMP_MOD_MDIO = 3,
  24	AM65_CPSW_REGDUMP_MOD_CPSW = 4,
  25	AM65_CPSW_REGDUMP_MOD_CPSW_P0 = 5,
  26	AM65_CPSW_REGDUMP_MOD_CPSW_P1 = 6,
  27	AM65_CPSW_REGDUMP_MOD_CPSW_CPTS = 7,
  28	AM65_CPSW_REGDUMP_MOD_CPSW_ALE = 8,
  29	AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL = 9,
  30	AM65_CPSW_REGDUMP_MOD_LAST,
  31};
  32
  33/**
  34 * struct am65_cpsw_regdump_hdr - regdump record header
  35 *
  36 * @module_id: CPSW module ID
  37 * @len: CPSW module registers space length in u32
  38 */
  39
  40struct am65_cpsw_regdump_hdr {
  41	u32 module_id;
  42	u32 len;
  43};
  44
  45/**
  46 * struct am65_cpsw_regdump_item - regdump module description
  47 *
  48 * @hdr: CPSW module header
  49 * @start_ofs: CPSW module registers start addr
  50 * @end_ofs: CPSW module registers end addr
  51 *
  52 * Registers dump provided in the format:
  53 *  u32 : module ID
  54 *  u32 : dump length
  55 *  u32[..len]: registers values
  56 */
  57struct am65_cpsw_regdump_item {
  58	struct am65_cpsw_regdump_hdr hdr;
  59	u32 start_ofs;
  60	u32 end_ofs;
  61};
  62
  63#define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
  64	.hdr.module_id = (mod), \
  65	.hdr.len = (end + 4 - start) * 2 + \
  66		   sizeof(struct am65_cpsw_regdump_hdr), \
  67	.start_ofs = (start), \
  68	.end_ofs = end, \
  69}
  70
  71static const struct am65_cpsw_regdump_item am65_cpsw_regdump[] = {
  72	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS, 0x0, 0x1c),
  73	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS, 0x30, 0x4c),
  74	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO, 0xf00, 0xffc),
  75	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW, 0x20000, 0x2011c),
  76	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0, 0x21000, 0x21320),
  77	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1, 0x22000, 0x223a4),
  78	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS,
  79			      0x3d000, 0x3d048),
  80	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE, 0x3e000, 0x3e13c),
  81	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL, 0, 0),
  82};
  83
  84struct am65_cpsw_stats_regs {
  85	u32	rx_good_frames;
  86	u32	rx_broadcast_frames;
  87	u32	rx_multicast_frames;
  88	u32	rx_pause_frames;		/* slave */
  89	u32	rx_crc_errors;
  90	u32	rx_align_code_errors;		/* slave */
  91	u32	rx_oversized_frames;
  92	u32	rx_jabber_frames;		/* slave */
  93	u32	rx_undersized_frames;
  94	u32	rx_fragments;			/* slave */
  95	u32	ale_drop;
  96	u32	ale_overrun_drop;
  97	u32	rx_octets;
  98	u32	tx_good_frames;
  99	u32	tx_broadcast_frames;
 100	u32	tx_multicast_frames;
 101	u32	tx_pause_frames;		/* slave */
 102	u32	tx_deferred_frames;		/* slave */
 103	u32	tx_collision_frames;		/* slave */
 104	u32	tx_single_coll_frames;		/* slave */
 105	u32	tx_mult_coll_frames;		/* slave */
 106	u32	tx_excessive_collisions;	/* slave */
 107	u32	tx_late_collisions;		/* slave */
 108	u32	rx_ipg_error;			/* slave 10G only */
 109	u32	tx_carrier_sense_errors;	/* slave */
 110	u32	tx_octets;
 111	u32	tx_64B_frames;
 112	u32	tx_65_to_127B_frames;
 113	u32	tx_128_to_255B_frames;
 114	u32	tx_256_to_511B_frames;
 115	u32	tx_512_to_1023B_frames;
 116	u32	tx_1024B_frames;
 117	u32	net_octets;
 118	u32	rx_bottom_fifo_drop;
 119	u32	rx_port_mask_drop;
 120	u32	rx_top_fifo_drop;
 121	u32	ale_rate_limit_drop;
 122	u32	ale_vid_ingress_drop;
 123	u32	ale_da_eq_sa_drop;
 124	u32	ale_block_drop;			/* K3 */
 125	u32	ale_secure_drop;		/* K3 */
 126	u32	ale_auth_drop;			/* K3 */
 127	u32	ale_unknown_ucast;
 128	u32	ale_unknown_ucast_bytes;
 129	u32	ale_unknown_mcast;
 130	u32	ale_unknown_mcast_bytes;
 131	u32	ale_unknown_bcast;
 132	u32	ale_unknown_bcast_bytes;
 133	u32	ale_pol_match;
 134	u32	ale_pol_match_red;
 135	u32	ale_pol_match_yellow;
 136	u32	ale_mcast_sa_drop;		/* K3 */
 137	u32	ale_dual_vlan_drop;		/* K3 */
 138	u32	ale_len_err_drop;		/* K3 */
 139	u32	ale_ip_next_hdr_drop;		/* K3 */
 140	u32	ale_ipv4_frag_drop;		/* K3 */
 141	u32	__rsvd_1[24];
 142	u32	iet_rx_assembly_err;		/* K3 slave */
 143	u32	iet_rx_assembly_ok;		/* K3 slave */
 144	u32	iet_rx_smd_err;			/* K3 slave */
 145	u32	iet_rx_frag;			/* K3 slave */
 146	u32	iet_tx_hold;			/* K3 slave */
 147	u32	iet_tx_frag;			/* K3 slave */
 148	u32	__rsvd_2[9];
 149	u32	tx_mem_protect_err;
 150	/* following NU only */
 151	u32	tx_pri0;
 152	u32	tx_pri1;
 153	u32	tx_pri2;
 154	u32	tx_pri3;
 155	u32	tx_pri4;
 156	u32	tx_pri5;
 157	u32	tx_pri6;
 158	u32	tx_pri7;
 159	u32	tx_pri0_bcnt;
 160	u32	tx_pri1_bcnt;
 161	u32	tx_pri2_bcnt;
 162	u32	tx_pri3_bcnt;
 163	u32	tx_pri4_bcnt;
 164	u32	tx_pri5_bcnt;
 165	u32	tx_pri6_bcnt;
 166	u32	tx_pri7_bcnt;
 167	u32	tx_pri0_drop;
 168	u32	tx_pri1_drop;
 169	u32	tx_pri2_drop;
 170	u32	tx_pri3_drop;
 171	u32	tx_pri4_drop;
 172	u32	tx_pri5_drop;
 173	u32	tx_pri6_drop;
 174	u32	tx_pri7_drop;
 175	u32	tx_pri0_drop_bcnt;
 176	u32	tx_pri1_drop_bcnt;
 177	u32	tx_pri2_drop_bcnt;
 178	u32	tx_pri3_drop_bcnt;
 179	u32	tx_pri4_drop_bcnt;
 180	u32	tx_pri5_drop_bcnt;
 181	u32	tx_pri6_drop_bcnt;
 182	u32	tx_pri7_drop_bcnt;
 183};
 184
 185struct am65_cpsw_ethtool_stat {
 186	char desc[ETH_GSTRING_LEN];
 187	int offset;
 188};
 189
 190#define AM65_CPSW_STATS(prefix, field)			\
 191{							\
 192	#prefix#field,					\
 193	offsetof(struct am65_cpsw_stats_regs, field)	\
 194}
 195
 196static const struct am65_cpsw_ethtool_stat am65_host_stats[] = {
 197	AM65_CPSW_STATS(p0_, rx_good_frames),
 198	AM65_CPSW_STATS(p0_, rx_broadcast_frames),
 199	AM65_CPSW_STATS(p0_, rx_multicast_frames),
 200	AM65_CPSW_STATS(p0_, rx_crc_errors),
 201	AM65_CPSW_STATS(p0_, rx_oversized_frames),
 202	AM65_CPSW_STATS(p0_, rx_undersized_frames),
 203	AM65_CPSW_STATS(p0_, ale_drop),
 204	AM65_CPSW_STATS(p0_, ale_overrun_drop),
 205	AM65_CPSW_STATS(p0_, rx_octets),
 206	AM65_CPSW_STATS(p0_, tx_good_frames),
 207	AM65_CPSW_STATS(p0_, tx_broadcast_frames),
 208	AM65_CPSW_STATS(p0_, tx_multicast_frames),
 209	AM65_CPSW_STATS(p0_, tx_octets),
 210	AM65_CPSW_STATS(p0_, tx_64B_frames),
 211	AM65_CPSW_STATS(p0_, tx_65_to_127B_frames),
 212	AM65_CPSW_STATS(p0_, tx_128_to_255B_frames),
 213	AM65_CPSW_STATS(p0_, tx_256_to_511B_frames),
 214	AM65_CPSW_STATS(p0_, tx_512_to_1023B_frames),
 215	AM65_CPSW_STATS(p0_, tx_1024B_frames),
 216	AM65_CPSW_STATS(p0_, net_octets),
 217	AM65_CPSW_STATS(p0_, rx_bottom_fifo_drop),
 218	AM65_CPSW_STATS(p0_, rx_port_mask_drop),
 219	AM65_CPSW_STATS(p0_, rx_top_fifo_drop),
 220	AM65_CPSW_STATS(p0_, ale_rate_limit_drop),
 221	AM65_CPSW_STATS(p0_, ale_vid_ingress_drop),
 222	AM65_CPSW_STATS(p0_, ale_da_eq_sa_drop),
 223	AM65_CPSW_STATS(p0_, ale_block_drop),
 224	AM65_CPSW_STATS(p0_, ale_secure_drop),
 225	AM65_CPSW_STATS(p0_, ale_auth_drop),
 226	AM65_CPSW_STATS(p0_, ale_unknown_ucast),
 227	AM65_CPSW_STATS(p0_, ale_unknown_ucast_bytes),
 228	AM65_CPSW_STATS(p0_, ale_unknown_mcast),
 229	AM65_CPSW_STATS(p0_, ale_unknown_mcast_bytes),
 230	AM65_CPSW_STATS(p0_, ale_unknown_bcast),
 231	AM65_CPSW_STATS(p0_, ale_unknown_bcast_bytes),
 232	AM65_CPSW_STATS(p0_, ale_pol_match),
 233	AM65_CPSW_STATS(p0_, ale_pol_match_red),
 234	AM65_CPSW_STATS(p0_, ale_pol_match_yellow),
 235	AM65_CPSW_STATS(p0_, ale_mcast_sa_drop),
 236	AM65_CPSW_STATS(p0_, ale_dual_vlan_drop),
 237	AM65_CPSW_STATS(p0_, ale_len_err_drop),
 238	AM65_CPSW_STATS(p0_, ale_ip_next_hdr_drop),
 239	AM65_CPSW_STATS(p0_, ale_ipv4_frag_drop),
 240	AM65_CPSW_STATS(p0_, tx_mem_protect_err),
 241	AM65_CPSW_STATS(p0_, tx_pri0),
 242	AM65_CPSW_STATS(p0_, tx_pri1),
 243	AM65_CPSW_STATS(p0_, tx_pri2),
 244	AM65_CPSW_STATS(p0_, tx_pri3),
 245	AM65_CPSW_STATS(p0_, tx_pri4),
 246	AM65_CPSW_STATS(p0_, tx_pri5),
 247	AM65_CPSW_STATS(p0_, tx_pri6),
 248	AM65_CPSW_STATS(p0_, tx_pri7),
 249	AM65_CPSW_STATS(p0_, tx_pri0_bcnt),
 250	AM65_CPSW_STATS(p0_, tx_pri1_bcnt),
 251	AM65_CPSW_STATS(p0_, tx_pri2_bcnt),
 252	AM65_CPSW_STATS(p0_, tx_pri3_bcnt),
 253	AM65_CPSW_STATS(p0_, tx_pri4_bcnt),
 254	AM65_CPSW_STATS(p0_, tx_pri5_bcnt),
 255	AM65_CPSW_STATS(p0_, tx_pri6_bcnt),
 256	AM65_CPSW_STATS(p0_, tx_pri7_bcnt),
 257	AM65_CPSW_STATS(p0_, tx_pri0_drop),
 258	AM65_CPSW_STATS(p0_, tx_pri1_drop),
 259	AM65_CPSW_STATS(p0_, tx_pri2_drop),
 260	AM65_CPSW_STATS(p0_, tx_pri3_drop),
 261	AM65_CPSW_STATS(p0_, tx_pri4_drop),
 262	AM65_CPSW_STATS(p0_, tx_pri5_drop),
 263	AM65_CPSW_STATS(p0_, tx_pri6_drop),
 264	AM65_CPSW_STATS(p0_, tx_pri7_drop),
 265	AM65_CPSW_STATS(p0_, tx_pri0_drop_bcnt),
 266	AM65_CPSW_STATS(p0_, tx_pri1_drop_bcnt),
 267	AM65_CPSW_STATS(p0_, tx_pri2_drop_bcnt),
 268	AM65_CPSW_STATS(p0_, tx_pri3_drop_bcnt),
 269	AM65_CPSW_STATS(p0_, tx_pri4_drop_bcnt),
 270	AM65_CPSW_STATS(p0_, tx_pri5_drop_bcnt),
 271	AM65_CPSW_STATS(p0_, tx_pri6_drop_bcnt),
 272	AM65_CPSW_STATS(p0_, tx_pri7_drop_bcnt),
 273};
 274
 275static const struct am65_cpsw_ethtool_stat am65_slave_stats[] = {
 276	AM65_CPSW_STATS(, rx_good_frames),
 277	AM65_CPSW_STATS(, rx_broadcast_frames),
 278	AM65_CPSW_STATS(, rx_multicast_frames),
 279	AM65_CPSW_STATS(, rx_pause_frames),
 280	AM65_CPSW_STATS(, rx_crc_errors),
 281	AM65_CPSW_STATS(, rx_align_code_errors),
 282	AM65_CPSW_STATS(, rx_oversized_frames),
 283	AM65_CPSW_STATS(, rx_jabber_frames),
 284	AM65_CPSW_STATS(, rx_undersized_frames),
 285	AM65_CPSW_STATS(, rx_fragments),
 286	AM65_CPSW_STATS(, ale_drop),
 287	AM65_CPSW_STATS(, ale_overrun_drop),
 288	AM65_CPSW_STATS(, rx_octets),
 289	AM65_CPSW_STATS(, tx_good_frames),
 290	AM65_CPSW_STATS(, tx_broadcast_frames),
 291	AM65_CPSW_STATS(, tx_multicast_frames),
 292	AM65_CPSW_STATS(, tx_pause_frames),
 293	AM65_CPSW_STATS(, tx_deferred_frames),
 294	AM65_CPSW_STATS(, tx_collision_frames),
 295	AM65_CPSW_STATS(, tx_single_coll_frames),
 296	AM65_CPSW_STATS(, tx_mult_coll_frames),
 297	AM65_CPSW_STATS(, tx_excessive_collisions),
 298	AM65_CPSW_STATS(, tx_late_collisions),
 299	AM65_CPSW_STATS(, rx_ipg_error),
 300	AM65_CPSW_STATS(, tx_carrier_sense_errors),
 301	AM65_CPSW_STATS(, tx_octets),
 302	AM65_CPSW_STATS(, tx_64B_frames),
 303	AM65_CPSW_STATS(, tx_65_to_127B_frames),
 304	AM65_CPSW_STATS(, tx_128_to_255B_frames),
 305	AM65_CPSW_STATS(, tx_256_to_511B_frames),
 306	AM65_CPSW_STATS(, tx_512_to_1023B_frames),
 307	AM65_CPSW_STATS(, tx_1024B_frames),
 308	AM65_CPSW_STATS(, net_octets),
 309	AM65_CPSW_STATS(, rx_bottom_fifo_drop),
 310	AM65_CPSW_STATS(, rx_port_mask_drop),
 311	AM65_CPSW_STATS(, rx_top_fifo_drop),
 312	AM65_CPSW_STATS(, ale_rate_limit_drop),
 313	AM65_CPSW_STATS(, ale_vid_ingress_drop),
 314	AM65_CPSW_STATS(, ale_da_eq_sa_drop),
 315	AM65_CPSW_STATS(, ale_block_drop),
 316	AM65_CPSW_STATS(, ale_secure_drop),
 317	AM65_CPSW_STATS(, ale_auth_drop),
 318	AM65_CPSW_STATS(, ale_unknown_ucast),
 319	AM65_CPSW_STATS(, ale_unknown_ucast_bytes),
 320	AM65_CPSW_STATS(, ale_unknown_mcast),
 321	AM65_CPSW_STATS(, ale_unknown_mcast_bytes),
 322	AM65_CPSW_STATS(, ale_unknown_bcast),
 323	AM65_CPSW_STATS(, ale_unknown_bcast_bytes),
 324	AM65_CPSW_STATS(, ale_pol_match),
 325	AM65_CPSW_STATS(, ale_pol_match_red),
 326	AM65_CPSW_STATS(, ale_pol_match_yellow),
 327	AM65_CPSW_STATS(, ale_mcast_sa_drop),
 328	AM65_CPSW_STATS(, ale_dual_vlan_drop),
 329	AM65_CPSW_STATS(, ale_len_err_drop),
 330	AM65_CPSW_STATS(, ale_ip_next_hdr_drop),
 331	AM65_CPSW_STATS(, ale_ipv4_frag_drop),
 332	AM65_CPSW_STATS(, iet_rx_assembly_err),
 333	AM65_CPSW_STATS(, iet_rx_assembly_ok),
 334	AM65_CPSW_STATS(, iet_rx_smd_err),
 335	AM65_CPSW_STATS(, iet_rx_frag),
 336	AM65_CPSW_STATS(, iet_tx_hold),
 337	AM65_CPSW_STATS(, iet_tx_frag),
 338	AM65_CPSW_STATS(, tx_mem_protect_err),
 339	AM65_CPSW_STATS(, tx_pri0),
 340	AM65_CPSW_STATS(, tx_pri1),
 341	AM65_CPSW_STATS(, tx_pri2),
 342	AM65_CPSW_STATS(, tx_pri3),
 343	AM65_CPSW_STATS(, tx_pri4),
 344	AM65_CPSW_STATS(, tx_pri5),
 345	AM65_CPSW_STATS(, tx_pri6),
 346	AM65_CPSW_STATS(, tx_pri7),
 347	AM65_CPSW_STATS(, tx_pri0_bcnt),
 348	AM65_CPSW_STATS(, tx_pri1_bcnt),
 349	AM65_CPSW_STATS(, tx_pri2_bcnt),
 350	AM65_CPSW_STATS(, tx_pri3_bcnt),
 351	AM65_CPSW_STATS(, tx_pri4_bcnt),
 352	AM65_CPSW_STATS(, tx_pri5_bcnt),
 353	AM65_CPSW_STATS(, tx_pri6_bcnt),
 354	AM65_CPSW_STATS(, tx_pri7_bcnt),
 355	AM65_CPSW_STATS(, tx_pri0_drop),
 356	AM65_CPSW_STATS(, tx_pri1_drop),
 357	AM65_CPSW_STATS(, tx_pri2_drop),
 358	AM65_CPSW_STATS(, tx_pri3_drop),
 359	AM65_CPSW_STATS(, tx_pri4_drop),
 360	AM65_CPSW_STATS(, tx_pri5_drop),
 361	AM65_CPSW_STATS(, tx_pri6_drop),
 362	AM65_CPSW_STATS(, tx_pri7_drop),
 363	AM65_CPSW_STATS(, tx_pri0_drop_bcnt),
 364	AM65_CPSW_STATS(, tx_pri1_drop_bcnt),
 365	AM65_CPSW_STATS(, tx_pri2_drop_bcnt),
 366	AM65_CPSW_STATS(, tx_pri3_drop_bcnt),
 367	AM65_CPSW_STATS(, tx_pri4_drop_bcnt),
 368	AM65_CPSW_STATS(, tx_pri5_drop_bcnt),
 369	AM65_CPSW_STATS(, tx_pri6_drop_bcnt),
 370	AM65_CPSW_STATS(, tx_pri7_drop_bcnt),
 371};
 372
 373/* Ethtool priv_flags */
 374static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
 375#define	AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN	BIT(0)
 376	"p0-rx-ptype-rrobin",
 377};
 378
 379static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
 380{
 381	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 382	int ret;
 383
 384	ret = pm_runtime_resume_and_get(common->dev);
 385	if (ret < 0)
 386		dev_err(common->dev, "ethtool begin failed %d\n", ret);
 387
 388	return ret;
 389}
 390
 391static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
 392{
 393	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 394	int ret;
 395
 396	ret = pm_runtime_put(common->dev);
 397	if (ret < 0 && ret != -EBUSY)
 398		dev_err(common->dev, "ethtool complete failed %d\n", ret);
 399}
 400
 401static void am65_cpsw_get_drvinfo(struct net_device *ndev,
 402				  struct ethtool_drvinfo *info)
 403{
 404	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 405
 406	strscpy(info->driver, dev_driver_string(common->dev),
 407		sizeof(info->driver));
 408	strscpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
 409}
 410
 411static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
 412{
 413	struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
 414
 415	return priv->msg_enable;
 416}
 417
 418static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
 419{
 420	struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
 421
 422	priv->msg_enable = value;
 423}
 424
 425static void am65_cpsw_get_channels(struct net_device *ndev,
 426				   struct ethtool_channels *ch)
 427{
 428	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 429
 430	ch->max_rx = AM65_CPSW_MAX_QUEUES;
 431	ch->max_tx = AM65_CPSW_MAX_QUEUES;
 432	ch->rx_count = common->rx_ch_num_flows;
 433	ch->tx_count = common->tx_ch_num;
 434}
 435
 436static int am65_cpsw_set_channels(struct net_device *ndev,
 437				  struct ethtool_channels *chs)
 438{
 439	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 440
 441	if (!chs->rx_count || !chs->tx_count)
 442		return -EINVAL;
 443
 444	/* Check if interface is up. Can change the num queues when
 445	 * the interface is down.
 446	 */
 447	if (common->usage_count)
 448		return -EBUSY;
 449
 450	return am65_cpsw_nuss_update_tx_rx_chns(common, chs->tx_count,
 451						chs->rx_count);
 452}
 453
 454static void
 455am65_cpsw_get_ringparam(struct net_device *ndev,
 456			struct ethtool_ringparam *ering,
 457			struct kernel_ethtool_ringparam *kernel_ering,
 458			struct netlink_ext_ack *extack)
 459{
 460	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 461
 462	/* not supported */
 463	ering->tx_pending = common->tx_chns[0].descs_num;
 464	ering->rx_pending = common->rx_chns.descs_num;
 465}
 466
 467static void am65_cpsw_get_pauseparam(struct net_device *ndev,
 468				     struct ethtool_pauseparam *pause)
 469{
 470	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 471
 472	phylink_ethtool_get_pauseparam(salve->phylink, pause);
 473}
 474
 475static int am65_cpsw_set_pauseparam(struct net_device *ndev,
 476				    struct ethtool_pauseparam *pause)
 477{
 478	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 479
 480	return phylink_ethtool_set_pauseparam(salve->phylink, pause);
 481}
 482
 483static void am65_cpsw_get_wol(struct net_device *ndev,
 484			      struct ethtool_wolinfo *wol)
 485{
 486	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 487
 488	phylink_ethtool_get_wol(salve->phylink, wol);
 489}
 490
 491static int am65_cpsw_set_wol(struct net_device *ndev,
 492			     struct ethtool_wolinfo *wol)
 493{
 494	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 495
 496	return phylink_ethtool_set_wol(salve->phylink, wol);
 497}
 498
 499static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
 500					struct ethtool_link_ksettings *ecmd)
 501{
 502	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 503
 504	return phylink_ethtool_ksettings_get(salve->phylink, ecmd);
 505}
 506
 507static int
 508am65_cpsw_set_link_ksettings(struct net_device *ndev,
 509			     const struct ethtool_link_ksettings *ecmd)
 510{
 511	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 512
 513	return phylink_ethtool_ksettings_set(salve->phylink, ecmd);
 514}
 515
 516static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
 517{
 518	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 519
 520	return phylink_ethtool_get_eee(salve->phylink, edata);
 521}
 522
 523static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
 524{
 525	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 526
 527	return phylink_ethtool_set_eee(salve->phylink, edata);
 528}
 529
 530static int am65_cpsw_nway_reset(struct net_device *ndev)
 531{
 532	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 533
 534	return phylink_ethtool_nway_reset(salve->phylink);
 535}
 536
 537static int am65_cpsw_get_regs_len(struct net_device *ndev)
 538{
 539	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 540	u32 ale_entries, i, regdump_len = 0;
 541
 542	ale_entries = cpsw_ale_get_num_entries(common->ale);
 543	for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
 544		if (am65_cpsw_regdump[i].hdr.module_id ==
 545		    AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
 546			regdump_len += sizeof(struct am65_cpsw_regdump_hdr);
 547			regdump_len += ale_entries *
 548				       ALE_ENTRY_WORDS * sizeof(u32);
 549			continue;
 550		}
 551		regdump_len += am65_cpsw_regdump[i].hdr.len;
 552	}
 553
 554	return regdump_len;
 555}
 556
 557static void am65_cpsw_get_regs(struct net_device *ndev,
 558			       struct ethtool_regs *regs, void *p)
 559{
 560	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 561	u32 ale_entries, i, j, pos, *reg = p;
 562
 563	/* update CPSW IP version */
 564	regs->version = AM65_CPSW_REGDUMP_VER;
 565	ale_entries = cpsw_ale_get_num_entries(common->ale);
 566
 567	pos = 0;
 568	for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
 569		reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
 570
 571		if (am65_cpsw_regdump[i].hdr.module_id ==
 572		    AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
 573			u32 ale_tbl_len = ale_entries *
 574					  ALE_ENTRY_WORDS * sizeof(u32) +
 575					  sizeof(struct am65_cpsw_regdump_hdr);
 576			reg[pos++] = ale_tbl_len;
 577			cpsw_ale_dump(common->ale, &reg[pos]);
 578			pos += ale_tbl_len;
 579			continue;
 580		}
 581
 582		reg[pos++] = am65_cpsw_regdump[i].hdr.len;
 583
 584		j = am65_cpsw_regdump[i].start_ofs;
 585		do {
 586			reg[pos++] = j;
 587			reg[pos++] = readl_relaxed(common->ss_base + j);
 588			j += sizeof(u32);
 589		} while (j <= am65_cpsw_regdump[i].end_ofs);
 590	}
 591}
 592
 593static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
 594{
 595	switch (sset) {
 596	case ETH_SS_STATS:
 597		return ARRAY_SIZE(am65_host_stats) +
 598		       ARRAY_SIZE(am65_slave_stats);
 599	case ETH_SS_PRIV_FLAGS:
 600		return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
 601	default:
 602		return -EOPNOTSUPP;
 603	}
 604}
 605
 606static void am65_cpsw_get_strings(struct net_device *ndev,
 607				  u32 stringset, u8 *data)
 608{
 609	const struct am65_cpsw_ethtool_stat *hw_stats;
 610	u32 i, num_stats;
 611	u8 *p = data;
 612
 613	switch (stringset) {
 614	case ETH_SS_STATS:
 615		num_stats = ARRAY_SIZE(am65_host_stats);
 616		hw_stats = am65_host_stats;
 617		for (i = 0; i < num_stats; i++) {
 618			memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
 619			p += ETH_GSTRING_LEN;
 620		}
 621
 622		num_stats = ARRAY_SIZE(am65_slave_stats);
 623		hw_stats = am65_slave_stats;
 624		for (i = 0; i < num_stats; i++) {
 625			memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
 626			p += ETH_GSTRING_LEN;
 627		}
 628		break;
 629	case ETH_SS_PRIV_FLAGS:
 630		num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
 631
 632		for (i = 0; i < num_stats; i++) {
 633			memcpy(p, am65_cpsw_ethtool_priv_flags[i],
 634			       ETH_GSTRING_LEN);
 635			p += ETH_GSTRING_LEN;
 636		}
 637		break;
 638	}
 639}
 640
 641static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
 642					struct ethtool_stats *stats, u64 *data)
 643{
 644	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 645	const struct am65_cpsw_ethtool_stat *hw_stats;
 646	struct am65_cpsw_host *host_p;
 647	struct am65_cpsw_port *port;
 648	u32 i, num_stats;
 649
 650	host_p = am65_common_get_host(common);
 651	port = am65_ndev_to_port(ndev);
 652	num_stats = ARRAY_SIZE(am65_host_stats);
 653	hw_stats = am65_host_stats;
 654	for (i = 0; i < num_stats; i++)
 655		*data++ = readl_relaxed(host_p->stat_base +
 656					hw_stats[i].offset);
 657
 658	num_stats = ARRAY_SIZE(am65_slave_stats);
 659	hw_stats = am65_slave_stats;
 660	for (i = 0; i < num_stats; i++)
 661		*data++ = readl_relaxed(port->stat_base +
 662					hw_stats[i].offset);
 663}
 664
 665static void am65_cpsw_get_eth_mac_stats(struct net_device *ndev,
 666					struct ethtool_eth_mac_stats *s)
 667{
 668	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 669	struct am65_cpsw_stats_regs __iomem *stats;
 670
 671	stats = port->stat_base;
 672
 673	if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE)
 674		return;
 675
 676	s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames);
 677	s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames);
 678	s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames);
 679	s->FramesReceivedOK = readl_relaxed(&stats->rx_good_frames);
 680	s->FrameCheckSequenceErrors = readl_relaxed(&stats->rx_crc_errors);
 681	s->AlignmentErrors = readl_relaxed(&stats->rx_align_code_errors);
 682	s->OctetsTransmittedOK = readl_relaxed(&stats->tx_octets);
 683	s->FramesWithDeferredXmissions = readl_relaxed(&stats->tx_deferred_frames);
 684	s->LateCollisions = readl_relaxed(&stats->tx_late_collisions);
 685	s->CarrierSenseErrors = readl_relaxed(&stats->tx_carrier_sense_errors);
 686	s->OctetsReceivedOK = readl_relaxed(&stats->rx_octets);
 687	s->MulticastFramesXmittedOK = readl_relaxed(&stats->tx_multicast_frames);
 688	s->BroadcastFramesXmittedOK = readl_relaxed(&stats->tx_broadcast_frames);
 689	s->MulticastFramesReceivedOK = readl_relaxed(&stats->rx_multicast_frames);
 690	s->BroadcastFramesReceivedOK = readl_relaxed(&stats->rx_broadcast_frames);
 691};
 692
 693static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
 694					 struct kernel_ethtool_ts_info *info)
 695{
 696	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 697	unsigned int ptp_v2_filter;
 698
 699	ptp_v2_filter = BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT)	 |
 700			BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC)	 |
 701			BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
 702			BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT)	 |
 703			BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC)	 |
 704			BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
 705			BIT(HWTSTAMP_FILTER_PTP_V2_EVENT)	 |
 706			BIT(HWTSTAMP_FILTER_PTP_V2_SYNC)	 |
 707			BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);
 708
 709	if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
 710		return ethtool_op_get_ts_info(ndev, info);
 711
 712	info->so_timestamping =
 713		SOF_TIMESTAMPING_TX_HARDWARE |
 714		SOF_TIMESTAMPING_TX_SOFTWARE |
 715		SOF_TIMESTAMPING_RX_HARDWARE |
 716		SOF_TIMESTAMPING_RAW_HARDWARE;
 717	info->phc_index = am65_cpts_phc_index(common->cpts);
 718	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
 719	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | ptp_v2_filter;
 720	return 0;
 721}
 722
 723static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
 724{
 725	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 726	u32 priv_flags = 0;
 727
 728	if (common->pf_p0_rx_ptype_rrobin)
 729		priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
 730
 731	return priv_flags;
 732}
 733
 734static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
 735{
 736	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 737	int rrobin;
 738
 739	rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
 740
 741	if (common->usage_count)
 742		return -EBUSY;
 743
 744	if (common->est_enabled && rrobin) {
 745		netdev_err(ndev,
 746			   "p0-rx-ptype-rrobin flag conflicts with QOS\n");
 747		return -EINVAL;
 748	}
 749
 750	common->pf_p0_rx_ptype_rrobin = rrobin;
 751
 752	return 0;
 753}
 754
 755static void am65_cpsw_port_iet_rx_enable(struct am65_cpsw_port *port, bool enable)
 756{
 757	u32 val;
 758
 759	val = readl(port->port_base + AM65_CPSW_PN_REG_CTL);
 760	if (enable)
 761		val |= AM65_CPSW_PN_CTL_IET_PORT_EN;
 762	else
 763		val &= ~AM65_CPSW_PN_CTL_IET_PORT_EN;
 764
 765	writel(val, port->port_base + AM65_CPSW_PN_REG_CTL);
 766	am65_cpsw_iet_common_enable(port->common);
 767}
 768
 769static void am65_cpsw_port_iet_tx_enable(struct am65_cpsw_port *port, bool enable)
 770{
 771	u32 val;
 772
 773	val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 774	if (enable)
 775		val |= AM65_CPSW_PN_IET_MAC_PENABLE;
 776	else
 777		val &= ~AM65_CPSW_PN_IET_MAC_PENABLE;
 778
 779	writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 780}
 781
 782static int am65_cpsw_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
 783{
 784	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 785	struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev);
 786	u32 port_ctrl, iet_ctrl, iet_status;
 787	u32 add_frag_size;
 788
 789	if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS))
 790		return -EOPNOTSUPP;
 791
 792	mutex_lock(&priv->mm_lock);
 793
 794	iet_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 795	port_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_CTL);
 796
 797	state->tx_enabled = !!(iet_ctrl & AM65_CPSW_PN_IET_MAC_PENABLE);
 798	state->pmac_enabled = !!(port_ctrl & AM65_CPSW_PN_CTL_IET_PORT_EN);
 799
 800	iet_status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS);
 801
 802	if (iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY)
 803		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
 804	else if (iet_status & AM65_CPSW_PN_MAC_VERIFIED)
 805		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
 806	else if (iet_status & AM65_CPSW_PN_MAC_VERIFY_FAIL)
 807		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
 808	else
 809		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
 810
 811	add_frag_size = AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(iet_ctrl);
 812	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size);
 813
 814	/* Errata i2208: RX min fragment size cannot be less than 124 */
 815	state->rx_min_frag_size = 124;
 816
 817	/* FPE active if common tx_enabled and verification success or disabled (forced) */
 818	state->tx_active = state->tx_enabled &&
 819			   (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
 820			    state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
 821	state->verify_enabled = !(iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY);
 822
 823	state->verify_time = port->qos.iet.verify_time_ms;
 824
 825	/* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime
 826	 * variable has a range between 1 and 128 ms inclusive. Limit to that.
 827	 */
 828	state->max_verify_time = 128;
 829
 830	mutex_unlock(&priv->mm_lock);
 831
 832	return 0;
 833}
 834
 835static int am65_cpsw_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 836			    struct netlink_ext_ack *extack)
 837{
 838	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 839	struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev);
 840	struct am65_cpsw_iet *iet = &port->qos.iet;
 841	u32 val, add_frag_size;
 842	int err;
 843
 844	if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS))
 845		return -EOPNOTSUPP;
 846
 847	err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, &add_frag_size, extack);
 848	if (err)
 849		return err;
 850
 851	mutex_lock(&priv->mm_lock);
 852
 853	if (cfg->pmac_enabled) {
 854		/* change TX & RX FIFO MAX_BLKS as per TRM recommendation */
 855		if (!iet->original_max_blks)
 856			iet->original_max_blks = readl(port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
 857
 858		writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET,
 859		       port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
 860	} else if (iet->original_max_blks) {
 861		/* restore RX & TX FIFO MAX_BLKS */
 862		writel(iet->original_max_blks,
 863		       port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
 864	}
 865
 866	am65_cpsw_port_iet_rx_enable(port, cfg->pmac_enabled);
 867	am65_cpsw_port_iet_tx_enable(port, cfg->tx_enabled);
 868
 869	val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 870	if (cfg->verify_enabled) {
 871		val &= ~AM65_CPSW_PN_IET_MAC_DISABLEVERIFY;
 872		/* Reset Verify state machine. Verification won't start here.
 873		 * Verification will be done once link-up.
 874		 */
 875		val |= AM65_CPSW_PN_IET_MAC_LINKFAIL;
 876	} else {
 877		val |= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY;
 878		/* Clear LINKFAIL to allow verify/response packets */
 879		val &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL;
 880	}
 881
 882	val &= ~AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK;
 883	val |= AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(add_frag_size);
 884	writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 885
 886	/* verify_timeout_count can only be set at valid link */
 887	port->qos.iet.verify_time_ms = cfg->verify_time;
 888
 889	/* enable/disable preemption based on link status */
 890	am65_cpsw_iet_commit_preemptible_tcs(port);
 891
 892	mutex_unlock(&priv->mm_lock);
 893
 894	return 0;
 895}
 896
 897static void am65_cpsw_get_mm_stats(struct net_device *ndev,
 898				   struct ethtool_mm_stats *s)
 899{
 900	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 901	void __iomem *base = port->stat_base;
 902
 903	s->MACMergeFrameAssOkCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK);
 904	s->MACMergeFrameAssErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR);
 905	s->MACMergeFrameSmdErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_SMD_ERROR);
 906	/* CPSW Functional Spec states:
 907	 * "The IET stat aMACMergeFragCountRx is derived by adding the
 908	 *  Receive Assembly Error count to this value. i.e. AM65_CPSW_STATN_IET_RX_FRAG"
 909	 */
 910	s->MACMergeFragCountRx = readl(base + AM65_CPSW_STATN_IET_RX_FRAG) + s->MACMergeFrameAssErrorCount;
 911	s->MACMergeFragCountTx = readl(base + AM65_CPSW_STATN_IET_TX_FRAG);
 912	s->MACMergeHoldCount = readl(base + AM65_CPSW_STATN_IET_TX_HOLD);
 913}
 914
 915static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue,
 916					    struct ethtool_coalesce *coal)
 917{
 918	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 919	struct am65_cpsw_rx_flow *rx_flow;
 920	struct am65_cpsw_tx_chn *tx_chn;
 921
 922	if (queue >= AM65_CPSW_MAX_QUEUES)
 923		return -EINVAL;
 924
 925	tx_chn = &common->tx_chns[queue];
 926	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;
 927
 928	rx_flow = &common->rx_chns.flows[queue];
 929	coal->rx_coalesce_usecs = rx_flow->rx_pace_timeout / 1000;
 930
 931	return 0;
 932}
 933
 934static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
 935				  struct kernel_ethtool_coalesce *kernel_coal,
 936				  struct netlink_ext_ack *extack)
 937{
 938	return am65_cpsw_get_per_queue_coalesce(ndev, 0, coal);
 939}
 940
 941static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
 942					    struct ethtool_coalesce *coal)
 943{
 944	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 945	struct am65_cpsw_rx_flow *rx_flow;
 946	struct am65_cpsw_tx_chn *tx_chn;
 947
 948	if (queue >= AM65_CPSW_MAX_QUEUES)
 949		return -EINVAL;
 950
 951	tx_chn = &common->tx_chns[queue];
 952	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20)
 953		return -EINVAL;
 954
 955	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
 956
 957	rx_flow = &common->rx_chns.flows[queue];
 958	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20)
 959		return -EINVAL;
 960
 961	rx_flow->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;
 962
 963	return 0;
 964}
 965
 966static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
 967				  struct kernel_ethtool_coalesce *kernel_coal,
 968				  struct netlink_ext_ack *extack)
 969{
 970	return am65_cpsw_set_per_queue_coalesce(ndev, 0, coal);
 971}
 972
 973const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
 974	.begin			= am65_cpsw_ethtool_op_begin,
 975	.complete		= am65_cpsw_ethtool_op_complete,
 976	.get_drvinfo		= am65_cpsw_get_drvinfo,
 977	.get_msglevel		= am65_cpsw_get_msglevel,
 978	.set_msglevel		= am65_cpsw_set_msglevel,
 979	.get_channels		= am65_cpsw_get_channels,
 980	.set_channels		= am65_cpsw_set_channels,
 981	.get_ringparam		= am65_cpsw_get_ringparam,
 982	.get_regs_len		= am65_cpsw_get_regs_len,
 983	.get_regs		= am65_cpsw_get_regs,
 984	.get_sset_count		= am65_cpsw_get_sset_count,
 985	.get_strings		= am65_cpsw_get_strings,
 986	.get_ethtool_stats	= am65_cpsw_get_ethtool_stats,
 987	.get_eth_mac_stats	= am65_cpsw_get_eth_mac_stats,
 988	.get_ts_info		= am65_cpsw_get_ethtool_ts_info,
 989	.get_priv_flags		= am65_cpsw_get_ethtool_priv_flags,
 990	.set_priv_flags		= am65_cpsw_set_ethtool_priv_flags,
 991	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
 992	.get_coalesce           = am65_cpsw_get_coalesce,
 993	.set_coalesce           = am65_cpsw_set_coalesce,
 994	.get_per_queue_coalesce = am65_cpsw_get_per_queue_coalesce,
 995	.set_per_queue_coalesce = am65_cpsw_set_per_queue_coalesce,
 996
 997	.get_link		= ethtool_op_get_link,
 998	.get_link_ksettings	= am65_cpsw_get_link_ksettings,
 999	.set_link_ksettings	= am65_cpsw_set_link_ksettings,
1000	.get_pauseparam		= am65_cpsw_get_pauseparam,
1001	.set_pauseparam		= am65_cpsw_set_pauseparam,
1002	.get_wol		= am65_cpsw_get_wol,
1003	.set_wol		= am65_cpsw_set_wol,
1004	.get_eee		= am65_cpsw_get_eee,
1005	.set_eee		= am65_cpsw_set_eee,
1006	.nway_reset		= am65_cpsw_nway_reset,
1007	.get_mm			= am65_cpsw_get_mm,
1008	.set_mm			= am65_cpsw_set_mm,
1009	.get_mm_stats		= am65_cpsw_get_mm_stats,
1010};