Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
   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_RX_QUEUES;
 431	ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
 432	ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
 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	am65_cpsw_nuss_remove_tx_chns(common);
 451
 452	return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
 453}
 454
 455static void
 456am65_cpsw_get_ringparam(struct net_device *ndev,
 457			struct ethtool_ringparam *ering,
 458			struct kernel_ethtool_ringparam *kernel_ering,
 459			struct netlink_ext_ack *extack)
 460{
 461	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 462
 463	/* not supported */
 464	ering->tx_pending = common->tx_chns[0].descs_num;
 465	ering->rx_pending = common->rx_chns.descs_num;
 466}
 467
 468static void am65_cpsw_get_pauseparam(struct net_device *ndev,
 469				     struct ethtool_pauseparam *pause)
 470{
 471	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 472
 473	phylink_ethtool_get_pauseparam(salve->phylink, pause);
 474}
 475
 476static int am65_cpsw_set_pauseparam(struct net_device *ndev,
 477				    struct ethtool_pauseparam *pause)
 478{
 479	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 480
 481	return phylink_ethtool_set_pauseparam(salve->phylink, pause);
 482}
 483
 484static void am65_cpsw_get_wol(struct net_device *ndev,
 485			      struct ethtool_wolinfo *wol)
 486{
 487	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 488
 489	phylink_ethtool_get_wol(salve->phylink, wol);
 490}
 491
 492static int am65_cpsw_set_wol(struct net_device *ndev,
 493			     struct ethtool_wolinfo *wol)
 494{
 495	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 496
 497	return phylink_ethtool_set_wol(salve->phylink, wol);
 498}
 499
 500static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
 501					struct ethtool_link_ksettings *ecmd)
 502{
 503	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 504
 505	return phylink_ethtool_ksettings_get(salve->phylink, ecmd);
 506}
 507
 508static int
 509am65_cpsw_set_link_ksettings(struct net_device *ndev,
 510			     const struct ethtool_link_ksettings *ecmd)
 511{
 512	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 513
 514	return phylink_ethtool_ksettings_set(salve->phylink, ecmd);
 515}
 516
 517static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
 518{
 519	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 520
 521	return phylink_ethtool_get_eee(salve->phylink, edata);
 522}
 523
 524static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
 525{
 526	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 527
 528	return phylink_ethtool_set_eee(salve->phylink, edata);
 529}
 530
 531static int am65_cpsw_nway_reset(struct net_device *ndev)
 532{
 533	struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
 534
 535	return phylink_ethtool_nway_reset(salve->phylink);
 536}
 537
 538static int am65_cpsw_get_regs_len(struct net_device *ndev)
 539{
 540	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 541	u32 ale_entries, i, regdump_len = 0;
 542
 543	ale_entries = cpsw_ale_get_num_entries(common->ale);
 544	for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
 545		if (am65_cpsw_regdump[i].hdr.module_id ==
 546		    AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
 547			regdump_len += sizeof(struct am65_cpsw_regdump_hdr);
 548			regdump_len += ale_entries *
 549				       ALE_ENTRY_WORDS * sizeof(u32);
 550			continue;
 551		}
 552		regdump_len += am65_cpsw_regdump[i].hdr.len;
 553	}
 554
 555	return regdump_len;
 556}
 557
 558static void am65_cpsw_get_regs(struct net_device *ndev,
 559			       struct ethtool_regs *regs, void *p)
 560{
 561	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 562	u32 ale_entries, i, j, pos, *reg = p;
 563
 564	/* update CPSW IP version */
 565	regs->version = AM65_CPSW_REGDUMP_VER;
 566	ale_entries = cpsw_ale_get_num_entries(common->ale);
 567
 568	pos = 0;
 569	for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
 570		reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
 571
 572		if (am65_cpsw_regdump[i].hdr.module_id ==
 573		    AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
 574			u32 ale_tbl_len = ale_entries *
 575					  ALE_ENTRY_WORDS * sizeof(u32) +
 576					  sizeof(struct am65_cpsw_regdump_hdr);
 577			reg[pos++] = ale_tbl_len;
 578			cpsw_ale_dump(common->ale, &reg[pos]);
 579			pos += ale_tbl_len;
 580			continue;
 581		}
 582
 583		reg[pos++] = am65_cpsw_regdump[i].hdr.len;
 584
 585		j = am65_cpsw_regdump[i].start_ofs;
 586		do {
 587			reg[pos++] = j;
 588			reg[pos++] = readl_relaxed(common->ss_base + j);
 589			j += sizeof(u32);
 590		} while (j <= am65_cpsw_regdump[i].end_ofs);
 591	}
 592}
 593
 594static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
 595{
 596	switch (sset) {
 597	case ETH_SS_STATS:
 598		return ARRAY_SIZE(am65_host_stats) +
 599		       ARRAY_SIZE(am65_slave_stats);
 600	case ETH_SS_PRIV_FLAGS:
 601		return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
 602	default:
 603		return -EOPNOTSUPP;
 604	}
 605}
 606
 607static void am65_cpsw_get_strings(struct net_device *ndev,
 608				  u32 stringset, u8 *data)
 609{
 610	const struct am65_cpsw_ethtool_stat *hw_stats;
 611	u32 i, num_stats;
 612	u8 *p = data;
 613
 614	switch (stringset) {
 615	case ETH_SS_STATS:
 616		num_stats = ARRAY_SIZE(am65_host_stats);
 617		hw_stats = am65_host_stats;
 618		for (i = 0; i < num_stats; i++) {
 619			memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
 620			p += ETH_GSTRING_LEN;
 621		}
 622
 623		num_stats = ARRAY_SIZE(am65_slave_stats);
 624		hw_stats = am65_slave_stats;
 625		for (i = 0; i < num_stats; i++) {
 626			memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
 627			p += ETH_GSTRING_LEN;
 628		}
 629		break;
 630	case ETH_SS_PRIV_FLAGS:
 631		num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
 632
 633		for (i = 0; i < num_stats; i++) {
 634			memcpy(p, am65_cpsw_ethtool_priv_flags[i],
 635			       ETH_GSTRING_LEN);
 636			p += ETH_GSTRING_LEN;
 637		}
 638		break;
 639	}
 640}
 641
 642static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
 643					struct ethtool_stats *stats, u64 *data)
 644{
 645	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 646	const struct am65_cpsw_ethtool_stat *hw_stats;
 647	struct am65_cpsw_host *host_p;
 648	struct am65_cpsw_port *port;
 649	u32 i, num_stats;
 650
 651	host_p = am65_common_get_host(common);
 652	port = am65_ndev_to_port(ndev);
 653	num_stats = ARRAY_SIZE(am65_host_stats);
 654	hw_stats = am65_host_stats;
 655	for (i = 0; i < num_stats; i++)
 656		*data++ = readl_relaxed(host_p->stat_base +
 657					hw_stats[i].offset);
 658
 659	num_stats = ARRAY_SIZE(am65_slave_stats);
 660	hw_stats = am65_slave_stats;
 661	for (i = 0; i < num_stats; i++)
 662		*data++ = readl_relaxed(port->stat_base +
 663					hw_stats[i].offset);
 664}
 665
 666static void am65_cpsw_get_eth_mac_stats(struct net_device *ndev,
 667					struct ethtool_eth_mac_stats *s)
 668{
 669	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 670	struct am65_cpsw_stats_regs __iomem *stats;
 671
 672	stats = port->stat_base;
 673
 674	if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE)
 675		return;
 676
 677	s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames);
 678	s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames);
 679	s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames);
 680	s->FramesReceivedOK = readl_relaxed(&stats->rx_good_frames);
 681	s->FrameCheckSequenceErrors = readl_relaxed(&stats->rx_crc_errors);
 682	s->AlignmentErrors = readl_relaxed(&stats->rx_align_code_errors);
 683	s->OctetsTransmittedOK = readl_relaxed(&stats->tx_octets);
 684	s->FramesWithDeferredXmissions = readl_relaxed(&stats->tx_deferred_frames);
 685	s->LateCollisions = readl_relaxed(&stats->tx_late_collisions);
 686	s->CarrierSenseErrors = readl_relaxed(&stats->tx_carrier_sense_errors);
 687	s->OctetsReceivedOK = readl_relaxed(&stats->rx_octets);
 688	s->MulticastFramesXmittedOK = readl_relaxed(&stats->tx_multicast_frames);
 689	s->BroadcastFramesXmittedOK = readl_relaxed(&stats->tx_broadcast_frames);
 690	s->MulticastFramesReceivedOK = readl_relaxed(&stats->rx_multicast_frames);
 691	s->BroadcastFramesReceivedOK = readl_relaxed(&stats->rx_broadcast_frames);
 692};
 693
 694static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
 695					 struct ethtool_ts_info *info)
 696{
 697	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 698
 699	if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
 700		return ethtool_op_get_ts_info(ndev, info);
 701
 702	info->so_timestamping =
 703		SOF_TIMESTAMPING_TX_HARDWARE |
 704		SOF_TIMESTAMPING_TX_SOFTWARE |
 705		SOF_TIMESTAMPING_RX_HARDWARE |
 706		SOF_TIMESTAMPING_RX_SOFTWARE |
 707		SOF_TIMESTAMPING_SOFTWARE |
 708		SOF_TIMESTAMPING_RAW_HARDWARE;
 709	info->phc_index = am65_cpts_phc_index(common->cpts);
 710	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
 711	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
 712	return 0;
 713}
 714
 715static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
 716{
 717	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 718	u32 priv_flags = 0;
 719
 720	if (common->pf_p0_rx_ptype_rrobin)
 721		priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
 722
 723	return priv_flags;
 724}
 725
 726static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
 727{
 728	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 729	int rrobin;
 730
 731	rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
 732
 733	if (common->usage_count)
 734		return -EBUSY;
 735
 736	if (common->est_enabled && rrobin) {
 737		netdev_err(ndev,
 738			   "p0-rx-ptype-rrobin flag conflicts with QOS\n");
 739		return -EINVAL;
 740	}
 741
 742	common->pf_p0_rx_ptype_rrobin = rrobin;
 743
 744	return 0;
 745}
 746
 747static void am65_cpsw_port_iet_rx_enable(struct am65_cpsw_port *port, bool enable)
 748{
 749	u32 val;
 750
 751	val = readl(port->port_base + AM65_CPSW_PN_REG_CTL);
 752	if (enable)
 753		val |= AM65_CPSW_PN_CTL_IET_PORT_EN;
 754	else
 755		val &= ~AM65_CPSW_PN_CTL_IET_PORT_EN;
 756
 757	writel(val, port->port_base + AM65_CPSW_PN_REG_CTL);
 758	am65_cpsw_iet_common_enable(port->common);
 759}
 760
 761static void am65_cpsw_port_iet_tx_enable(struct am65_cpsw_port *port, bool enable)
 762{
 763	u32 val;
 764
 765	val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 766	if (enable)
 767		val |= AM65_CPSW_PN_IET_MAC_PENABLE;
 768	else
 769		val &= ~AM65_CPSW_PN_IET_MAC_PENABLE;
 770
 771	writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 772}
 773
 774static int am65_cpsw_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
 775{
 776	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 777	struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev);
 778	u32 port_ctrl, iet_ctrl, iet_status;
 779	u32 add_frag_size;
 780
 781	if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS))
 782		return -EOPNOTSUPP;
 783
 784	mutex_lock(&priv->mm_lock);
 785
 786	iet_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 787	port_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_CTL);
 788
 789	state->tx_enabled = !!(iet_ctrl & AM65_CPSW_PN_IET_MAC_PENABLE);
 790	state->pmac_enabled = !!(port_ctrl & AM65_CPSW_PN_CTL_IET_PORT_EN);
 791
 792	iet_status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS);
 793
 794	if (iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY)
 795		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
 796	else if (iet_status & AM65_CPSW_PN_MAC_VERIFIED)
 797		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
 798	else if (iet_status & AM65_CPSW_PN_MAC_VERIFY_FAIL)
 799		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
 800	else
 801		state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
 802
 803	add_frag_size = AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(iet_ctrl);
 804	state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size);
 805
 806	/* Errata i2208: RX min fragment size cannot be less than 124 */
 807	state->rx_min_frag_size = 124;
 808
 809	/* FPE active if common tx_enabled and verification success or disabled (forced) */
 810	state->tx_active = state->tx_enabled &&
 811			   (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
 812			    state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
 813	state->verify_enabled = !(iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY);
 814
 815	state->verify_time = port->qos.iet.verify_time_ms;
 816
 817	/* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime
 818	 * variable has a range between 1 and 128 ms inclusive. Limit to that.
 819	 */
 820	state->max_verify_time = 128;
 821
 822	mutex_unlock(&priv->mm_lock);
 823
 824	return 0;
 825}
 826
 827static int am65_cpsw_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 828			    struct netlink_ext_ack *extack)
 829{
 830	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 831	struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev);
 832	struct am65_cpsw_iet *iet = &port->qos.iet;
 833	u32 val, add_frag_size;
 834	int err;
 835
 836	if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS))
 837		return -EOPNOTSUPP;
 838
 839	err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, &add_frag_size, extack);
 840	if (err)
 841		return err;
 842
 843	mutex_lock(&priv->mm_lock);
 844
 845	if (cfg->pmac_enabled) {
 846		/* change TX & RX FIFO MAX_BLKS as per TRM recommendation */
 847		if (!iet->original_max_blks)
 848			iet->original_max_blks = readl(port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
 849
 850		writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET,
 851		       port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
 852	} else if (iet->original_max_blks) {
 853		/* restore RX & TX FIFO MAX_BLKS */
 854		writel(iet->original_max_blks,
 855		       port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
 856	}
 857
 858	am65_cpsw_port_iet_rx_enable(port, cfg->pmac_enabled);
 859	am65_cpsw_port_iet_tx_enable(port, cfg->tx_enabled);
 860
 861	val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 862	if (cfg->verify_enabled) {
 863		val &= ~AM65_CPSW_PN_IET_MAC_DISABLEVERIFY;
 864		/* Reset Verify state machine. Verification won't start here.
 865		 * Verification will be done once link-up.
 866		 */
 867		val |= AM65_CPSW_PN_IET_MAC_LINKFAIL;
 868	} else {
 869		val |= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY;
 870		/* Clear LINKFAIL to allow verify/response packets */
 871		val &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL;
 872	}
 873
 874	val &= ~AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK;
 875	val |= AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(add_frag_size);
 876	writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
 877
 878	/* verify_timeout_count can only be set at valid link */
 879	port->qos.iet.verify_time_ms = cfg->verify_time;
 880
 881	/* enable/disable preemption based on link status */
 882	am65_cpsw_iet_commit_preemptible_tcs(port);
 883
 884	mutex_unlock(&priv->mm_lock);
 885
 886	return 0;
 887}
 888
 889static void am65_cpsw_get_mm_stats(struct net_device *ndev,
 890				   struct ethtool_mm_stats *s)
 891{
 892	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 893	void __iomem *base = port->stat_base;
 894
 895	s->MACMergeFrameAssOkCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK);
 896	s->MACMergeFrameAssErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR);
 897	s->MACMergeFrameSmdErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_SMD_ERROR);
 898	/* CPSW Functional Spec states:
 899	 * "The IET stat aMACMergeFragCountRx is derived by adding the
 900	 *  Receive Assembly Error count to this value. i.e. AM65_CPSW_STATN_IET_RX_FRAG"
 901	 */
 902	s->MACMergeFragCountRx = readl(base + AM65_CPSW_STATN_IET_RX_FRAG) + s->MACMergeFrameAssErrorCount;
 903	s->MACMergeFragCountTx = readl(base + AM65_CPSW_STATN_IET_TX_FRAG);
 904	s->MACMergeHoldCount = readl(base + AM65_CPSW_STATN_IET_TX_HOLD);
 905}
 906
 907static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
 908				  struct kernel_ethtool_coalesce *kernel_coal,
 909				  struct netlink_ext_ack *extack)
 910{
 911	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 912	struct am65_cpsw_tx_chn *tx_chn;
 913
 914	tx_chn = &common->tx_chns[0];
 915
 916	coal->rx_coalesce_usecs = common->rx_pace_timeout / 1000;
 917	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;
 918
 919	return 0;
 920}
 921
 922static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue,
 923					    struct ethtool_coalesce *coal)
 924{
 925	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 926	struct am65_cpsw_tx_chn *tx_chn;
 927
 928	if (queue >= AM65_CPSW_MAX_TX_QUEUES)
 929		return -EINVAL;
 930
 931	tx_chn = &common->tx_chns[queue];
 932
 933	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;
 934
 935	return 0;
 936}
 937
 938static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
 939				  struct kernel_ethtool_coalesce *kernel_coal,
 940				  struct netlink_ext_ack *extack)
 941{
 942	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 943	struct am65_cpsw_tx_chn *tx_chn;
 944
 945	tx_chn = &common->tx_chns[0];
 946
 947	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20)
 948		return -EINVAL;
 949
 950	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20)
 951		return -EINVAL;
 952
 953	common->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;
 954	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
 955
 956	return 0;
 957}
 958
 959static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
 960					    struct ethtool_coalesce *coal)
 961{
 962	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 963	struct am65_cpsw_tx_chn *tx_chn;
 964
 965	if (queue >= AM65_CPSW_MAX_TX_QUEUES)
 966		return -EINVAL;
 967
 968	tx_chn = &common->tx_chns[queue];
 969
 970	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) {
 971		dev_info(common->dev, "defaulting to min value of 20us for tx-usecs for tx-%u\n",
 972			 queue);
 973		coal->tx_coalesce_usecs = 20;
 974	}
 975
 976	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
 977
 978	return 0;
 979}
 980
 981const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
 982	.begin			= am65_cpsw_ethtool_op_begin,
 983	.complete		= am65_cpsw_ethtool_op_complete,
 984	.get_drvinfo		= am65_cpsw_get_drvinfo,
 985	.get_msglevel		= am65_cpsw_get_msglevel,
 986	.set_msglevel		= am65_cpsw_set_msglevel,
 987	.get_channels		= am65_cpsw_get_channels,
 988	.set_channels		= am65_cpsw_set_channels,
 989	.get_ringparam		= am65_cpsw_get_ringparam,
 990	.get_regs_len		= am65_cpsw_get_regs_len,
 991	.get_regs		= am65_cpsw_get_regs,
 992	.get_sset_count		= am65_cpsw_get_sset_count,
 993	.get_strings		= am65_cpsw_get_strings,
 994	.get_ethtool_stats	= am65_cpsw_get_ethtool_stats,
 995	.get_eth_mac_stats	= am65_cpsw_get_eth_mac_stats,
 996	.get_ts_info		= am65_cpsw_get_ethtool_ts_info,
 997	.get_priv_flags		= am65_cpsw_get_ethtool_priv_flags,
 998	.set_priv_flags		= am65_cpsw_set_ethtool_priv_flags,
 999	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
1000	.get_coalesce           = am65_cpsw_get_coalesce,
1001	.set_coalesce           = am65_cpsw_set_coalesce,
1002	.get_per_queue_coalesce = am65_cpsw_get_per_queue_coalesce,
1003	.set_per_queue_coalesce = am65_cpsw_set_per_queue_coalesce,
1004
1005	.get_link		= ethtool_op_get_link,
1006	.get_link_ksettings	= am65_cpsw_get_link_ksettings,
1007	.set_link_ksettings	= am65_cpsw_set_link_ksettings,
1008	.get_pauseparam		= am65_cpsw_get_pauseparam,
1009	.set_pauseparam		= am65_cpsw_set_pauseparam,
1010	.get_wol		= am65_cpsw_get_wol,
1011	.set_wol		= am65_cpsw_set_wol,
1012	.get_eee		= am65_cpsw_get_eee,
1013	.set_eee		= am65_cpsw_set_eee,
1014	.nway_reset		= am65_cpsw_nway_reset,
1015	.get_mm			= am65_cpsw_get_mm,
1016	.set_mm			= am65_cpsw_set_mm,
1017	.get_mm_stats		= am65_cpsw_get_mm_stats,
1018};