cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

am65-cpsw-ethtool.c (22305B)


      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 "cpsw_ale.h"
     15#include "am65-cpts.h"
     16
     17#define AM65_CPSW_REGDUMP_VER 0x1
     18
     19enum {
     20	AM65_CPSW_REGDUMP_MOD_NUSS = 1,
     21	AM65_CPSW_REGDUMP_MOD_RGMII_STATUS = 2,
     22	AM65_CPSW_REGDUMP_MOD_MDIO = 3,
     23	AM65_CPSW_REGDUMP_MOD_CPSW = 4,
     24	AM65_CPSW_REGDUMP_MOD_CPSW_P0 = 5,
     25	AM65_CPSW_REGDUMP_MOD_CPSW_P1 = 6,
     26	AM65_CPSW_REGDUMP_MOD_CPSW_CPTS = 7,
     27	AM65_CPSW_REGDUMP_MOD_CPSW_ALE = 8,
     28	AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL = 9,
     29	AM65_CPSW_REGDUMP_MOD_LAST,
     30};
     31
     32/**
     33 * struct am65_cpsw_regdump_hdr - regdump record header
     34 *
     35 * @module_id: CPSW module ID
     36 * @len: CPSW module registers space length in u32
     37 */
     38
     39struct am65_cpsw_regdump_hdr {
     40	u32 module_id;
     41	u32 len;
     42};
     43
     44/**
     45 * struct am65_cpsw_regdump_item - regdump module description
     46 *
     47 * @hdr: CPSW module header
     48 * @start_ofs: CPSW module registers start addr
     49 * @end_ofs: CPSW module registers end addr
     50 *
     51 * Registers dump provided in the format:
     52 *  u32 : module ID
     53 *  u32 : dump length
     54 *  u32[..len]: registers values
     55 */
     56struct am65_cpsw_regdump_item {
     57	struct am65_cpsw_regdump_hdr hdr;
     58	u32 start_ofs;
     59	u32 end_ofs;
     60};
     61
     62#define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
     63	.hdr.module_id = (mod), \
     64	.hdr.len = (end + 4 - start) * 2 + \
     65		   sizeof(struct am65_cpsw_regdump_hdr), \
     66	.start_ofs = (start), \
     67	.end_ofs = end, \
     68}
     69
     70static const struct am65_cpsw_regdump_item am65_cpsw_regdump[] = {
     71	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS, 0x0, 0x1c),
     72	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS, 0x30, 0x4c),
     73	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO, 0xf00, 0xffc),
     74	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW, 0x20000, 0x2011c),
     75	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0, 0x21000, 0x21320),
     76	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1, 0x22000, 0x223a4),
     77	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS,
     78			      0x3d000, 0x3d048),
     79	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE, 0x3e000, 0x3e13c),
     80	AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL, 0, 0),
     81};
     82
     83struct am65_cpsw_stats_regs {
     84	u32	rx_good_frames;
     85	u32	rx_broadcast_frames;
     86	u32	rx_multicast_frames;
     87	u32	rx_pause_frames;		/* slave */
     88	u32	rx_crc_errors;
     89	u32	rx_align_code_errors;		/* slave */
     90	u32	rx_oversized_frames;
     91	u32	rx_jabber_frames;		/* slave */
     92	u32	rx_undersized_frames;
     93	u32	rx_fragments;			/* slave */
     94	u32	ale_drop;
     95	u32	ale_overrun_drop;
     96	u32	rx_octets;
     97	u32	tx_good_frames;
     98	u32	tx_broadcast_frames;
     99	u32	tx_multicast_frames;
    100	u32	tx_pause_frames;		/* slave */
    101	u32	tx_deferred_frames;		/* slave */
    102	u32	tx_collision_frames;		/* slave */
    103	u32	tx_single_coll_frames;		/* slave */
    104	u32	tx_mult_coll_frames;		/* slave */
    105	u32	tx_excessive_collisions;	/* slave */
    106	u32	tx_late_collisions;		/* slave */
    107	u32	rx_ipg_error;			/* slave 10G only */
    108	u32	tx_carrier_sense_errors;	/* slave */
    109	u32	tx_octets;
    110	u32	tx_64B_frames;
    111	u32	tx_65_to_127B_frames;
    112	u32	tx_128_to_255B_frames;
    113	u32	tx_256_to_511B_frames;
    114	u32	tx_512_to_1023B_frames;
    115	u32	tx_1024B_frames;
    116	u32	net_octets;
    117	u32	rx_bottom_fifo_drop;
    118	u32	rx_port_mask_drop;
    119	u32	rx_top_fifo_drop;
    120	u32	ale_rate_limit_drop;
    121	u32	ale_vid_ingress_drop;
    122	u32	ale_da_eq_sa_drop;
    123	u32	ale_block_drop;			/* K3 */
    124	u32	ale_secure_drop;		/* K3 */
    125	u32	ale_auth_drop;			/* K3 */
    126	u32	ale_unknown_ucast;
    127	u32	ale_unknown_ucast_bytes;
    128	u32	ale_unknown_mcast;
    129	u32	ale_unknown_mcast_bytes;
    130	u32	ale_unknown_bcast;
    131	u32	ale_unknown_bcast_bytes;
    132	u32	ale_pol_match;
    133	u32	ale_pol_match_red;
    134	u32	ale_pol_match_yellow;
    135	u32	ale_mcast_sa_drop;		/* K3 */
    136	u32	ale_dual_vlan_drop;		/* K3 */
    137	u32	ale_len_err_drop;		/* K3 */
    138	u32	ale_ip_next_hdr_drop;		/* K3 */
    139	u32	ale_ipv4_frag_drop;		/* K3 */
    140	u32	__rsvd_1[24];
    141	u32	iet_rx_assembly_err;		/* K3 slave */
    142	u32	iet_rx_assembly_ok;		/* K3 slave */
    143	u32	iet_rx_smd_err;			/* K3 slave */
    144	u32	iet_rx_frag;			/* K3 slave */
    145	u32	iet_tx_hold;			/* K3 slave */
    146	u32	iet_tx_frag;			/* K3 slave */
    147	u32	__rsvd_2[9];
    148	u32	tx_mem_protect_err;
    149	/* following NU only */
    150	u32	tx_pri0;
    151	u32	tx_pri1;
    152	u32	tx_pri2;
    153	u32	tx_pri3;
    154	u32	tx_pri4;
    155	u32	tx_pri5;
    156	u32	tx_pri6;
    157	u32	tx_pri7;
    158	u32	tx_pri0_bcnt;
    159	u32	tx_pri1_bcnt;
    160	u32	tx_pri2_bcnt;
    161	u32	tx_pri3_bcnt;
    162	u32	tx_pri4_bcnt;
    163	u32	tx_pri5_bcnt;
    164	u32	tx_pri6_bcnt;
    165	u32	tx_pri7_bcnt;
    166	u32	tx_pri0_drop;
    167	u32	tx_pri1_drop;
    168	u32	tx_pri2_drop;
    169	u32	tx_pri3_drop;
    170	u32	tx_pri4_drop;
    171	u32	tx_pri5_drop;
    172	u32	tx_pri6_drop;
    173	u32	tx_pri7_drop;
    174	u32	tx_pri0_drop_bcnt;
    175	u32	tx_pri1_drop_bcnt;
    176	u32	tx_pri2_drop_bcnt;
    177	u32	tx_pri3_drop_bcnt;
    178	u32	tx_pri4_drop_bcnt;
    179	u32	tx_pri5_drop_bcnt;
    180	u32	tx_pri6_drop_bcnt;
    181	u32	tx_pri7_drop_bcnt;
    182};
    183
    184struct am65_cpsw_ethtool_stat {
    185	char desc[ETH_GSTRING_LEN];
    186	int offset;
    187};
    188
    189#define AM65_CPSW_STATS(prefix, field)			\
    190{							\
    191	#prefix#field,					\
    192	offsetof(struct am65_cpsw_stats_regs, field)	\
    193}
    194
    195static const struct am65_cpsw_ethtool_stat am65_host_stats[] = {
    196	AM65_CPSW_STATS(p0_, rx_good_frames),
    197	AM65_CPSW_STATS(p0_, rx_broadcast_frames),
    198	AM65_CPSW_STATS(p0_, rx_multicast_frames),
    199	AM65_CPSW_STATS(p0_, rx_crc_errors),
    200	AM65_CPSW_STATS(p0_, rx_oversized_frames),
    201	AM65_CPSW_STATS(p0_, rx_undersized_frames),
    202	AM65_CPSW_STATS(p0_, ale_drop),
    203	AM65_CPSW_STATS(p0_, ale_overrun_drop),
    204	AM65_CPSW_STATS(p0_, rx_octets),
    205	AM65_CPSW_STATS(p0_, tx_good_frames),
    206	AM65_CPSW_STATS(p0_, tx_broadcast_frames),
    207	AM65_CPSW_STATS(p0_, tx_multicast_frames),
    208	AM65_CPSW_STATS(p0_, tx_octets),
    209	AM65_CPSW_STATS(p0_, tx_64B_frames),
    210	AM65_CPSW_STATS(p0_, tx_65_to_127B_frames),
    211	AM65_CPSW_STATS(p0_, tx_128_to_255B_frames),
    212	AM65_CPSW_STATS(p0_, tx_256_to_511B_frames),
    213	AM65_CPSW_STATS(p0_, tx_512_to_1023B_frames),
    214	AM65_CPSW_STATS(p0_, tx_1024B_frames),
    215	AM65_CPSW_STATS(p0_, net_octets),
    216	AM65_CPSW_STATS(p0_, rx_bottom_fifo_drop),
    217	AM65_CPSW_STATS(p0_, rx_port_mask_drop),
    218	AM65_CPSW_STATS(p0_, rx_top_fifo_drop),
    219	AM65_CPSW_STATS(p0_, ale_rate_limit_drop),
    220	AM65_CPSW_STATS(p0_, ale_vid_ingress_drop),
    221	AM65_CPSW_STATS(p0_, ale_da_eq_sa_drop),
    222	AM65_CPSW_STATS(p0_, ale_block_drop),
    223	AM65_CPSW_STATS(p0_, ale_secure_drop),
    224	AM65_CPSW_STATS(p0_, ale_auth_drop),
    225	AM65_CPSW_STATS(p0_, ale_unknown_ucast),
    226	AM65_CPSW_STATS(p0_, ale_unknown_ucast_bytes),
    227	AM65_CPSW_STATS(p0_, ale_unknown_mcast),
    228	AM65_CPSW_STATS(p0_, ale_unknown_mcast_bytes),
    229	AM65_CPSW_STATS(p0_, ale_unknown_bcast),
    230	AM65_CPSW_STATS(p0_, ale_unknown_bcast_bytes),
    231	AM65_CPSW_STATS(p0_, ale_pol_match),
    232	AM65_CPSW_STATS(p0_, ale_pol_match_red),
    233	AM65_CPSW_STATS(p0_, ale_pol_match_yellow),
    234	AM65_CPSW_STATS(p0_, ale_mcast_sa_drop),
    235	AM65_CPSW_STATS(p0_, ale_dual_vlan_drop),
    236	AM65_CPSW_STATS(p0_, ale_len_err_drop),
    237	AM65_CPSW_STATS(p0_, ale_ip_next_hdr_drop),
    238	AM65_CPSW_STATS(p0_, ale_ipv4_frag_drop),
    239	AM65_CPSW_STATS(p0_, tx_mem_protect_err),
    240	AM65_CPSW_STATS(p0_, tx_pri0),
    241	AM65_CPSW_STATS(p0_, tx_pri1),
    242	AM65_CPSW_STATS(p0_, tx_pri2),
    243	AM65_CPSW_STATS(p0_, tx_pri3),
    244	AM65_CPSW_STATS(p0_, tx_pri4),
    245	AM65_CPSW_STATS(p0_, tx_pri5),
    246	AM65_CPSW_STATS(p0_, tx_pri6),
    247	AM65_CPSW_STATS(p0_, tx_pri7),
    248	AM65_CPSW_STATS(p0_, tx_pri0_bcnt),
    249	AM65_CPSW_STATS(p0_, tx_pri1_bcnt),
    250	AM65_CPSW_STATS(p0_, tx_pri2_bcnt),
    251	AM65_CPSW_STATS(p0_, tx_pri3_bcnt),
    252	AM65_CPSW_STATS(p0_, tx_pri4_bcnt),
    253	AM65_CPSW_STATS(p0_, tx_pri5_bcnt),
    254	AM65_CPSW_STATS(p0_, tx_pri6_bcnt),
    255	AM65_CPSW_STATS(p0_, tx_pri7_bcnt),
    256	AM65_CPSW_STATS(p0_, tx_pri0_drop),
    257	AM65_CPSW_STATS(p0_, tx_pri1_drop),
    258	AM65_CPSW_STATS(p0_, tx_pri2_drop),
    259	AM65_CPSW_STATS(p0_, tx_pri3_drop),
    260	AM65_CPSW_STATS(p0_, tx_pri4_drop),
    261	AM65_CPSW_STATS(p0_, tx_pri5_drop),
    262	AM65_CPSW_STATS(p0_, tx_pri6_drop),
    263	AM65_CPSW_STATS(p0_, tx_pri7_drop),
    264	AM65_CPSW_STATS(p0_, tx_pri0_drop_bcnt),
    265	AM65_CPSW_STATS(p0_, tx_pri1_drop_bcnt),
    266	AM65_CPSW_STATS(p0_, tx_pri2_drop_bcnt),
    267	AM65_CPSW_STATS(p0_, tx_pri3_drop_bcnt),
    268	AM65_CPSW_STATS(p0_, tx_pri4_drop_bcnt),
    269	AM65_CPSW_STATS(p0_, tx_pri5_drop_bcnt),
    270	AM65_CPSW_STATS(p0_, tx_pri6_drop_bcnt),
    271	AM65_CPSW_STATS(p0_, tx_pri7_drop_bcnt),
    272};
    273
    274static const struct am65_cpsw_ethtool_stat am65_slave_stats[] = {
    275	AM65_CPSW_STATS(, rx_good_frames),
    276	AM65_CPSW_STATS(, rx_broadcast_frames),
    277	AM65_CPSW_STATS(, rx_multicast_frames),
    278	AM65_CPSW_STATS(, rx_pause_frames),
    279	AM65_CPSW_STATS(, rx_crc_errors),
    280	AM65_CPSW_STATS(, rx_align_code_errors),
    281	AM65_CPSW_STATS(, rx_oversized_frames),
    282	AM65_CPSW_STATS(, rx_jabber_frames),
    283	AM65_CPSW_STATS(, rx_undersized_frames),
    284	AM65_CPSW_STATS(, rx_fragments),
    285	AM65_CPSW_STATS(, ale_drop),
    286	AM65_CPSW_STATS(, ale_overrun_drop),
    287	AM65_CPSW_STATS(, rx_octets),
    288	AM65_CPSW_STATS(, tx_good_frames),
    289	AM65_CPSW_STATS(, tx_broadcast_frames),
    290	AM65_CPSW_STATS(, tx_multicast_frames),
    291	AM65_CPSW_STATS(, tx_pause_frames),
    292	AM65_CPSW_STATS(, tx_deferred_frames),
    293	AM65_CPSW_STATS(, tx_collision_frames),
    294	AM65_CPSW_STATS(, tx_single_coll_frames),
    295	AM65_CPSW_STATS(, tx_mult_coll_frames),
    296	AM65_CPSW_STATS(, tx_excessive_collisions),
    297	AM65_CPSW_STATS(, tx_late_collisions),
    298	AM65_CPSW_STATS(, rx_ipg_error),
    299	AM65_CPSW_STATS(, tx_carrier_sense_errors),
    300	AM65_CPSW_STATS(, tx_octets),
    301	AM65_CPSW_STATS(, tx_64B_frames),
    302	AM65_CPSW_STATS(, tx_65_to_127B_frames),
    303	AM65_CPSW_STATS(, tx_128_to_255B_frames),
    304	AM65_CPSW_STATS(, tx_256_to_511B_frames),
    305	AM65_CPSW_STATS(, tx_512_to_1023B_frames),
    306	AM65_CPSW_STATS(, tx_1024B_frames),
    307	AM65_CPSW_STATS(, net_octets),
    308	AM65_CPSW_STATS(, rx_bottom_fifo_drop),
    309	AM65_CPSW_STATS(, rx_port_mask_drop),
    310	AM65_CPSW_STATS(, rx_top_fifo_drop),
    311	AM65_CPSW_STATS(, ale_rate_limit_drop),
    312	AM65_CPSW_STATS(, ale_vid_ingress_drop),
    313	AM65_CPSW_STATS(, ale_da_eq_sa_drop),
    314	AM65_CPSW_STATS(, ale_block_drop),
    315	AM65_CPSW_STATS(, ale_secure_drop),
    316	AM65_CPSW_STATS(, ale_auth_drop),
    317	AM65_CPSW_STATS(, ale_unknown_ucast),
    318	AM65_CPSW_STATS(, ale_unknown_ucast_bytes),
    319	AM65_CPSW_STATS(, ale_unknown_mcast),
    320	AM65_CPSW_STATS(, ale_unknown_mcast_bytes),
    321	AM65_CPSW_STATS(, ale_unknown_bcast),
    322	AM65_CPSW_STATS(, ale_unknown_bcast_bytes),
    323	AM65_CPSW_STATS(, ale_pol_match),
    324	AM65_CPSW_STATS(, ale_pol_match_red),
    325	AM65_CPSW_STATS(, ale_pol_match_yellow),
    326	AM65_CPSW_STATS(, ale_mcast_sa_drop),
    327	AM65_CPSW_STATS(, ale_dual_vlan_drop),
    328	AM65_CPSW_STATS(, ale_len_err_drop),
    329	AM65_CPSW_STATS(, ale_ip_next_hdr_drop),
    330	AM65_CPSW_STATS(, ale_ipv4_frag_drop),
    331	AM65_CPSW_STATS(, iet_rx_assembly_err),
    332	AM65_CPSW_STATS(, iet_rx_assembly_ok),
    333	AM65_CPSW_STATS(, iet_rx_smd_err),
    334	AM65_CPSW_STATS(, iet_rx_frag),
    335	AM65_CPSW_STATS(, iet_tx_hold),
    336	AM65_CPSW_STATS(, iet_tx_frag),
    337	AM65_CPSW_STATS(, tx_mem_protect_err),
    338	AM65_CPSW_STATS(, tx_pri0),
    339	AM65_CPSW_STATS(, tx_pri1),
    340	AM65_CPSW_STATS(, tx_pri2),
    341	AM65_CPSW_STATS(, tx_pri3),
    342	AM65_CPSW_STATS(, tx_pri4),
    343	AM65_CPSW_STATS(, tx_pri5),
    344	AM65_CPSW_STATS(, tx_pri6),
    345	AM65_CPSW_STATS(, tx_pri7),
    346	AM65_CPSW_STATS(, tx_pri0_bcnt),
    347	AM65_CPSW_STATS(, tx_pri1_bcnt),
    348	AM65_CPSW_STATS(, tx_pri2_bcnt),
    349	AM65_CPSW_STATS(, tx_pri3_bcnt),
    350	AM65_CPSW_STATS(, tx_pri4_bcnt),
    351	AM65_CPSW_STATS(, tx_pri5_bcnt),
    352	AM65_CPSW_STATS(, tx_pri6_bcnt),
    353	AM65_CPSW_STATS(, tx_pri7_bcnt),
    354	AM65_CPSW_STATS(, tx_pri0_drop),
    355	AM65_CPSW_STATS(, tx_pri1_drop),
    356	AM65_CPSW_STATS(, tx_pri2_drop),
    357	AM65_CPSW_STATS(, tx_pri3_drop),
    358	AM65_CPSW_STATS(, tx_pri4_drop),
    359	AM65_CPSW_STATS(, tx_pri5_drop),
    360	AM65_CPSW_STATS(, tx_pri6_drop),
    361	AM65_CPSW_STATS(, tx_pri7_drop),
    362	AM65_CPSW_STATS(, tx_pri0_drop_bcnt),
    363	AM65_CPSW_STATS(, tx_pri1_drop_bcnt),
    364	AM65_CPSW_STATS(, tx_pri2_drop_bcnt),
    365	AM65_CPSW_STATS(, tx_pri3_drop_bcnt),
    366	AM65_CPSW_STATS(, tx_pri4_drop_bcnt),
    367	AM65_CPSW_STATS(, tx_pri5_drop_bcnt),
    368	AM65_CPSW_STATS(, tx_pri6_drop_bcnt),
    369	AM65_CPSW_STATS(, tx_pri7_drop_bcnt),
    370};
    371
    372/* Ethtool priv_flags */
    373static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
    374#define	AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN	BIT(0)
    375	"p0-rx-ptype-rrobin",
    376};
    377
    378static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
    379{
    380	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    381	int ret;
    382
    383	ret = pm_runtime_resume_and_get(common->dev);
    384	if (ret < 0)
    385		dev_err(common->dev, "ethtool begin failed %d\n", ret);
    386
    387	return ret;
    388}
    389
    390static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
    391{
    392	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    393	int ret;
    394
    395	ret = pm_runtime_put(common->dev);
    396	if (ret < 0 && ret != -EBUSY)
    397		dev_err(common->dev, "ethtool complete failed %d\n", ret);
    398}
    399
    400static void am65_cpsw_get_drvinfo(struct net_device *ndev,
    401				  struct ethtool_drvinfo *info)
    402{
    403	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    404
    405	strlcpy(info->driver, dev_driver_string(common->dev),
    406		sizeof(info->driver));
    407	strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
    408}
    409
    410static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
    411{
    412	struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
    413
    414	return priv->msg_enable;
    415}
    416
    417static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
    418{
    419	struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
    420
    421	priv->msg_enable = value;
    422}
    423
    424static void am65_cpsw_get_channels(struct net_device *ndev,
    425				   struct ethtool_channels *ch)
    426{
    427	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    428
    429	ch->max_rx = AM65_CPSW_MAX_RX_QUEUES;
    430	ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
    431	ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
    432	ch->tx_count = common->tx_ch_num;
    433}
    434
    435static int am65_cpsw_set_channels(struct net_device *ndev,
    436				  struct ethtool_channels *chs)
    437{
    438	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    439
    440	if (!chs->rx_count || !chs->tx_count)
    441		return -EINVAL;
    442
    443	/* Check if interface is up. Can change the num queues when
    444	 * the interface is down.
    445	 */
    446	if (common->usage_count)
    447		return -EBUSY;
    448
    449	am65_cpsw_nuss_remove_tx_chns(common);
    450
    451	return am65_cpsw_nuss_update_tx_chns(common, chs->tx_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_eee *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_eee *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 int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
    666					 struct ethtool_ts_info *info)
    667{
    668	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    669
    670	if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
    671		return ethtool_op_get_ts_info(ndev, info);
    672
    673	info->so_timestamping =
    674		SOF_TIMESTAMPING_TX_HARDWARE |
    675		SOF_TIMESTAMPING_TX_SOFTWARE |
    676		SOF_TIMESTAMPING_RX_HARDWARE |
    677		SOF_TIMESTAMPING_RX_SOFTWARE |
    678		SOF_TIMESTAMPING_SOFTWARE |
    679		SOF_TIMESTAMPING_RAW_HARDWARE;
    680	info->phc_index = am65_cpts_phc_index(common->cpts);
    681	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
    682	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
    683	return 0;
    684}
    685
    686static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
    687{
    688	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    689	u32 priv_flags = 0;
    690
    691	if (common->pf_p0_rx_ptype_rrobin)
    692		priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
    693
    694	return priv_flags;
    695}
    696
    697static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
    698{
    699	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
    700	int rrobin;
    701
    702	rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
    703
    704	if (common->usage_count)
    705		return -EBUSY;
    706
    707	if (common->est_enabled && rrobin) {
    708		netdev_err(ndev,
    709			   "p0-rx-ptype-rrobin flag conflicts with QOS\n");
    710		return -EINVAL;
    711	}
    712
    713	common->pf_p0_rx_ptype_rrobin = rrobin;
    714
    715	return 0;
    716}
    717
    718const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
    719	.begin			= am65_cpsw_ethtool_op_begin,
    720	.complete		= am65_cpsw_ethtool_op_complete,
    721	.get_drvinfo		= am65_cpsw_get_drvinfo,
    722	.get_msglevel		= am65_cpsw_get_msglevel,
    723	.set_msglevel		= am65_cpsw_set_msglevel,
    724	.get_channels		= am65_cpsw_get_channels,
    725	.set_channels		= am65_cpsw_set_channels,
    726	.get_ringparam		= am65_cpsw_get_ringparam,
    727	.get_regs_len		= am65_cpsw_get_regs_len,
    728	.get_regs		= am65_cpsw_get_regs,
    729	.get_sset_count		= am65_cpsw_get_sset_count,
    730	.get_strings		= am65_cpsw_get_strings,
    731	.get_ethtool_stats	= am65_cpsw_get_ethtool_stats,
    732	.get_ts_info		= am65_cpsw_get_ethtool_ts_info,
    733	.get_priv_flags		= am65_cpsw_get_ethtool_priv_flags,
    734	.set_priv_flags		= am65_cpsw_set_ethtool_priv_flags,
    735
    736	.get_link		= ethtool_op_get_link,
    737	.get_link_ksettings	= am65_cpsw_get_link_ksettings,
    738	.set_link_ksettings	= am65_cpsw_set_link_ksettings,
    739	.get_pauseparam		= am65_cpsw_get_pauseparam,
    740	.set_pauseparam		= am65_cpsw_set_pauseparam,
    741	.get_wol		= am65_cpsw_get_wol,
    742	.set_wol		= am65_cpsw_set_wol,
    743	.get_eee		= am65_cpsw_get_eee,
    744	.set_eee		= am65_cpsw_set_eee,
    745	.nway_reset		= am65_cpsw_nway_reset,
    746};