Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver ethtool ops
0003  *
0004  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
0005  *
0006  */
0007 
0008 #include <linux/net_tstamp.h>
0009 #include <linux/phylink.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/pm_runtime.h>
0012 
0013 #include "am65-cpsw-nuss.h"
0014 #include "cpsw_ale.h"
0015 #include "am65-cpts.h"
0016 
0017 #define AM65_CPSW_REGDUMP_VER 0x1
0018 
0019 enum {
0020     AM65_CPSW_REGDUMP_MOD_NUSS = 1,
0021     AM65_CPSW_REGDUMP_MOD_RGMII_STATUS = 2,
0022     AM65_CPSW_REGDUMP_MOD_MDIO = 3,
0023     AM65_CPSW_REGDUMP_MOD_CPSW = 4,
0024     AM65_CPSW_REGDUMP_MOD_CPSW_P0 = 5,
0025     AM65_CPSW_REGDUMP_MOD_CPSW_P1 = 6,
0026     AM65_CPSW_REGDUMP_MOD_CPSW_CPTS = 7,
0027     AM65_CPSW_REGDUMP_MOD_CPSW_ALE = 8,
0028     AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL = 9,
0029     AM65_CPSW_REGDUMP_MOD_LAST,
0030 };
0031 
0032 /**
0033  * struct am65_cpsw_regdump_hdr - regdump record header
0034  *
0035  * @module_id: CPSW module ID
0036  * @len: CPSW module registers space length in u32
0037  */
0038 
0039 struct am65_cpsw_regdump_hdr {
0040     u32 module_id;
0041     u32 len;
0042 };
0043 
0044 /**
0045  * struct am65_cpsw_regdump_item - regdump module description
0046  *
0047  * @hdr: CPSW module header
0048  * @start_ofs: CPSW module registers start addr
0049  * @end_ofs: CPSW module registers end addr
0050  *
0051  * Registers dump provided in the format:
0052  *  u32 : module ID
0053  *  u32 : dump length
0054  *  u32[..len]: registers values
0055  */
0056 struct am65_cpsw_regdump_item {
0057     struct am65_cpsw_regdump_hdr hdr;
0058     u32 start_ofs;
0059     u32 end_ofs;
0060 };
0061 
0062 #define AM65_CPSW_REGDUMP_REC(mod, start, end) { \
0063     .hdr.module_id = (mod), \
0064     .hdr.len = (end + 4 - start) * 2 + \
0065            sizeof(struct am65_cpsw_regdump_hdr), \
0066     .start_ofs = (start), \
0067     .end_ofs = end, \
0068 }
0069 
0070 static const struct am65_cpsw_regdump_item am65_cpsw_regdump[] = {
0071     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_NUSS, 0x0, 0x1c),
0072     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_RGMII_STATUS, 0x30, 0x4c),
0073     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_MDIO, 0xf00, 0xffc),
0074     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW, 0x20000, 0x2011c),
0075     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P0, 0x21000, 0x21320),
0076     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_P1, 0x22000, 0x223a4),
0077     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_CPTS,
0078                   0x3d000, 0x3d048),
0079     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE, 0x3e000, 0x3e13c),
0080     AM65_CPSW_REGDUMP_REC(AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL, 0, 0),
0081 };
0082 
0083 struct am65_cpsw_stats_regs {
0084     u32 rx_good_frames;
0085     u32 rx_broadcast_frames;
0086     u32 rx_multicast_frames;
0087     u32 rx_pause_frames;        /* slave */
0088     u32 rx_crc_errors;
0089     u32 rx_align_code_errors;       /* slave */
0090     u32 rx_oversized_frames;
0091     u32 rx_jabber_frames;       /* slave */
0092     u32 rx_undersized_frames;
0093     u32 rx_fragments;           /* slave */
0094     u32 ale_drop;
0095     u32 ale_overrun_drop;
0096     u32 rx_octets;
0097     u32 tx_good_frames;
0098     u32 tx_broadcast_frames;
0099     u32 tx_multicast_frames;
0100     u32 tx_pause_frames;        /* slave */
0101     u32 tx_deferred_frames;     /* slave */
0102     u32 tx_collision_frames;        /* slave */
0103     u32 tx_single_coll_frames;      /* slave */
0104     u32 tx_mult_coll_frames;        /* slave */
0105     u32 tx_excessive_collisions;    /* slave */
0106     u32 tx_late_collisions;     /* slave */
0107     u32 rx_ipg_error;           /* slave 10G only */
0108     u32 tx_carrier_sense_errors;    /* slave */
0109     u32 tx_octets;
0110     u32 tx_64B_frames;
0111     u32 tx_65_to_127B_frames;
0112     u32 tx_128_to_255B_frames;
0113     u32 tx_256_to_511B_frames;
0114     u32 tx_512_to_1023B_frames;
0115     u32 tx_1024B_frames;
0116     u32 net_octets;
0117     u32 rx_bottom_fifo_drop;
0118     u32 rx_port_mask_drop;
0119     u32 rx_top_fifo_drop;
0120     u32 ale_rate_limit_drop;
0121     u32 ale_vid_ingress_drop;
0122     u32 ale_da_eq_sa_drop;
0123     u32 ale_block_drop;         /* K3 */
0124     u32 ale_secure_drop;        /* K3 */
0125     u32 ale_auth_drop;          /* K3 */
0126     u32 ale_unknown_ucast;
0127     u32 ale_unknown_ucast_bytes;
0128     u32 ale_unknown_mcast;
0129     u32 ale_unknown_mcast_bytes;
0130     u32 ale_unknown_bcast;
0131     u32 ale_unknown_bcast_bytes;
0132     u32 ale_pol_match;
0133     u32 ale_pol_match_red;
0134     u32 ale_pol_match_yellow;
0135     u32 ale_mcast_sa_drop;      /* K3 */
0136     u32 ale_dual_vlan_drop;     /* K3 */
0137     u32 ale_len_err_drop;       /* K3 */
0138     u32 ale_ip_next_hdr_drop;       /* K3 */
0139     u32 ale_ipv4_frag_drop;     /* K3 */
0140     u32 __rsvd_1[24];
0141     u32 iet_rx_assembly_err;        /* K3 slave */
0142     u32 iet_rx_assembly_ok;     /* K3 slave */
0143     u32 iet_rx_smd_err;         /* K3 slave */
0144     u32 iet_rx_frag;            /* K3 slave */
0145     u32 iet_tx_hold;            /* K3 slave */
0146     u32 iet_tx_frag;            /* K3 slave */
0147     u32 __rsvd_2[9];
0148     u32 tx_mem_protect_err;
0149     /* following NU only */
0150     u32 tx_pri0;
0151     u32 tx_pri1;
0152     u32 tx_pri2;
0153     u32 tx_pri3;
0154     u32 tx_pri4;
0155     u32 tx_pri5;
0156     u32 tx_pri6;
0157     u32 tx_pri7;
0158     u32 tx_pri0_bcnt;
0159     u32 tx_pri1_bcnt;
0160     u32 tx_pri2_bcnt;
0161     u32 tx_pri3_bcnt;
0162     u32 tx_pri4_bcnt;
0163     u32 tx_pri5_bcnt;
0164     u32 tx_pri6_bcnt;
0165     u32 tx_pri7_bcnt;
0166     u32 tx_pri0_drop;
0167     u32 tx_pri1_drop;
0168     u32 tx_pri2_drop;
0169     u32 tx_pri3_drop;
0170     u32 tx_pri4_drop;
0171     u32 tx_pri5_drop;
0172     u32 tx_pri6_drop;
0173     u32 tx_pri7_drop;
0174     u32 tx_pri0_drop_bcnt;
0175     u32 tx_pri1_drop_bcnt;
0176     u32 tx_pri2_drop_bcnt;
0177     u32 tx_pri3_drop_bcnt;
0178     u32 tx_pri4_drop_bcnt;
0179     u32 tx_pri5_drop_bcnt;
0180     u32 tx_pri6_drop_bcnt;
0181     u32 tx_pri7_drop_bcnt;
0182 };
0183 
0184 struct am65_cpsw_ethtool_stat {
0185     char desc[ETH_GSTRING_LEN];
0186     int offset;
0187 };
0188 
0189 #define AM65_CPSW_STATS(prefix, field)          \
0190 {                           \
0191     #prefix#field,                  \
0192     offsetof(struct am65_cpsw_stats_regs, field)    \
0193 }
0194 
0195 static const struct am65_cpsw_ethtool_stat am65_host_stats[] = {
0196     AM65_CPSW_STATS(p0_, rx_good_frames),
0197     AM65_CPSW_STATS(p0_, rx_broadcast_frames),
0198     AM65_CPSW_STATS(p0_, rx_multicast_frames),
0199     AM65_CPSW_STATS(p0_, rx_crc_errors),
0200     AM65_CPSW_STATS(p0_, rx_oversized_frames),
0201     AM65_CPSW_STATS(p0_, rx_undersized_frames),
0202     AM65_CPSW_STATS(p0_, ale_drop),
0203     AM65_CPSW_STATS(p0_, ale_overrun_drop),
0204     AM65_CPSW_STATS(p0_, rx_octets),
0205     AM65_CPSW_STATS(p0_, tx_good_frames),
0206     AM65_CPSW_STATS(p0_, tx_broadcast_frames),
0207     AM65_CPSW_STATS(p0_, tx_multicast_frames),
0208     AM65_CPSW_STATS(p0_, tx_octets),
0209     AM65_CPSW_STATS(p0_, tx_64B_frames),
0210     AM65_CPSW_STATS(p0_, tx_65_to_127B_frames),
0211     AM65_CPSW_STATS(p0_, tx_128_to_255B_frames),
0212     AM65_CPSW_STATS(p0_, tx_256_to_511B_frames),
0213     AM65_CPSW_STATS(p0_, tx_512_to_1023B_frames),
0214     AM65_CPSW_STATS(p0_, tx_1024B_frames),
0215     AM65_CPSW_STATS(p0_, net_octets),
0216     AM65_CPSW_STATS(p0_, rx_bottom_fifo_drop),
0217     AM65_CPSW_STATS(p0_, rx_port_mask_drop),
0218     AM65_CPSW_STATS(p0_, rx_top_fifo_drop),
0219     AM65_CPSW_STATS(p0_, ale_rate_limit_drop),
0220     AM65_CPSW_STATS(p0_, ale_vid_ingress_drop),
0221     AM65_CPSW_STATS(p0_, ale_da_eq_sa_drop),
0222     AM65_CPSW_STATS(p0_, ale_block_drop),
0223     AM65_CPSW_STATS(p0_, ale_secure_drop),
0224     AM65_CPSW_STATS(p0_, ale_auth_drop),
0225     AM65_CPSW_STATS(p0_, ale_unknown_ucast),
0226     AM65_CPSW_STATS(p0_, ale_unknown_ucast_bytes),
0227     AM65_CPSW_STATS(p0_, ale_unknown_mcast),
0228     AM65_CPSW_STATS(p0_, ale_unknown_mcast_bytes),
0229     AM65_CPSW_STATS(p0_, ale_unknown_bcast),
0230     AM65_CPSW_STATS(p0_, ale_unknown_bcast_bytes),
0231     AM65_CPSW_STATS(p0_, ale_pol_match),
0232     AM65_CPSW_STATS(p0_, ale_pol_match_red),
0233     AM65_CPSW_STATS(p0_, ale_pol_match_yellow),
0234     AM65_CPSW_STATS(p0_, ale_mcast_sa_drop),
0235     AM65_CPSW_STATS(p0_, ale_dual_vlan_drop),
0236     AM65_CPSW_STATS(p0_, ale_len_err_drop),
0237     AM65_CPSW_STATS(p0_, ale_ip_next_hdr_drop),
0238     AM65_CPSW_STATS(p0_, ale_ipv4_frag_drop),
0239     AM65_CPSW_STATS(p0_, tx_mem_protect_err),
0240     AM65_CPSW_STATS(p0_, tx_pri0),
0241     AM65_CPSW_STATS(p0_, tx_pri1),
0242     AM65_CPSW_STATS(p0_, tx_pri2),
0243     AM65_CPSW_STATS(p0_, tx_pri3),
0244     AM65_CPSW_STATS(p0_, tx_pri4),
0245     AM65_CPSW_STATS(p0_, tx_pri5),
0246     AM65_CPSW_STATS(p0_, tx_pri6),
0247     AM65_CPSW_STATS(p0_, tx_pri7),
0248     AM65_CPSW_STATS(p0_, tx_pri0_bcnt),
0249     AM65_CPSW_STATS(p0_, tx_pri1_bcnt),
0250     AM65_CPSW_STATS(p0_, tx_pri2_bcnt),
0251     AM65_CPSW_STATS(p0_, tx_pri3_bcnt),
0252     AM65_CPSW_STATS(p0_, tx_pri4_bcnt),
0253     AM65_CPSW_STATS(p0_, tx_pri5_bcnt),
0254     AM65_CPSW_STATS(p0_, tx_pri6_bcnt),
0255     AM65_CPSW_STATS(p0_, tx_pri7_bcnt),
0256     AM65_CPSW_STATS(p0_, tx_pri0_drop),
0257     AM65_CPSW_STATS(p0_, tx_pri1_drop),
0258     AM65_CPSW_STATS(p0_, tx_pri2_drop),
0259     AM65_CPSW_STATS(p0_, tx_pri3_drop),
0260     AM65_CPSW_STATS(p0_, tx_pri4_drop),
0261     AM65_CPSW_STATS(p0_, tx_pri5_drop),
0262     AM65_CPSW_STATS(p0_, tx_pri6_drop),
0263     AM65_CPSW_STATS(p0_, tx_pri7_drop),
0264     AM65_CPSW_STATS(p0_, tx_pri0_drop_bcnt),
0265     AM65_CPSW_STATS(p0_, tx_pri1_drop_bcnt),
0266     AM65_CPSW_STATS(p0_, tx_pri2_drop_bcnt),
0267     AM65_CPSW_STATS(p0_, tx_pri3_drop_bcnt),
0268     AM65_CPSW_STATS(p0_, tx_pri4_drop_bcnt),
0269     AM65_CPSW_STATS(p0_, tx_pri5_drop_bcnt),
0270     AM65_CPSW_STATS(p0_, tx_pri6_drop_bcnt),
0271     AM65_CPSW_STATS(p0_, tx_pri7_drop_bcnt),
0272 };
0273 
0274 static const struct am65_cpsw_ethtool_stat am65_slave_stats[] = {
0275     AM65_CPSW_STATS(, rx_good_frames),
0276     AM65_CPSW_STATS(, rx_broadcast_frames),
0277     AM65_CPSW_STATS(, rx_multicast_frames),
0278     AM65_CPSW_STATS(, rx_pause_frames),
0279     AM65_CPSW_STATS(, rx_crc_errors),
0280     AM65_CPSW_STATS(, rx_align_code_errors),
0281     AM65_CPSW_STATS(, rx_oversized_frames),
0282     AM65_CPSW_STATS(, rx_jabber_frames),
0283     AM65_CPSW_STATS(, rx_undersized_frames),
0284     AM65_CPSW_STATS(, rx_fragments),
0285     AM65_CPSW_STATS(, ale_drop),
0286     AM65_CPSW_STATS(, ale_overrun_drop),
0287     AM65_CPSW_STATS(, rx_octets),
0288     AM65_CPSW_STATS(, tx_good_frames),
0289     AM65_CPSW_STATS(, tx_broadcast_frames),
0290     AM65_CPSW_STATS(, tx_multicast_frames),
0291     AM65_CPSW_STATS(, tx_pause_frames),
0292     AM65_CPSW_STATS(, tx_deferred_frames),
0293     AM65_CPSW_STATS(, tx_collision_frames),
0294     AM65_CPSW_STATS(, tx_single_coll_frames),
0295     AM65_CPSW_STATS(, tx_mult_coll_frames),
0296     AM65_CPSW_STATS(, tx_excessive_collisions),
0297     AM65_CPSW_STATS(, tx_late_collisions),
0298     AM65_CPSW_STATS(, rx_ipg_error),
0299     AM65_CPSW_STATS(, tx_carrier_sense_errors),
0300     AM65_CPSW_STATS(, tx_octets),
0301     AM65_CPSW_STATS(, tx_64B_frames),
0302     AM65_CPSW_STATS(, tx_65_to_127B_frames),
0303     AM65_CPSW_STATS(, tx_128_to_255B_frames),
0304     AM65_CPSW_STATS(, tx_256_to_511B_frames),
0305     AM65_CPSW_STATS(, tx_512_to_1023B_frames),
0306     AM65_CPSW_STATS(, tx_1024B_frames),
0307     AM65_CPSW_STATS(, net_octets),
0308     AM65_CPSW_STATS(, rx_bottom_fifo_drop),
0309     AM65_CPSW_STATS(, rx_port_mask_drop),
0310     AM65_CPSW_STATS(, rx_top_fifo_drop),
0311     AM65_CPSW_STATS(, ale_rate_limit_drop),
0312     AM65_CPSW_STATS(, ale_vid_ingress_drop),
0313     AM65_CPSW_STATS(, ale_da_eq_sa_drop),
0314     AM65_CPSW_STATS(, ale_block_drop),
0315     AM65_CPSW_STATS(, ale_secure_drop),
0316     AM65_CPSW_STATS(, ale_auth_drop),
0317     AM65_CPSW_STATS(, ale_unknown_ucast),
0318     AM65_CPSW_STATS(, ale_unknown_ucast_bytes),
0319     AM65_CPSW_STATS(, ale_unknown_mcast),
0320     AM65_CPSW_STATS(, ale_unknown_mcast_bytes),
0321     AM65_CPSW_STATS(, ale_unknown_bcast),
0322     AM65_CPSW_STATS(, ale_unknown_bcast_bytes),
0323     AM65_CPSW_STATS(, ale_pol_match),
0324     AM65_CPSW_STATS(, ale_pol_match_red),
0325     AM65_CPSW_STATS(, ale_pol_match_yellow),
0326     AM65_CPSW_STATS(, ale_mcast_sa_drop),
0327     AM65_CPSW_STATS(, ale_dual_vlan_drop),
0328     AM65_CPSW_STATS(, ale_len_err_drop),
0329     AM65_CPSW_STATS(, ale_ip_next_hdr_drop),
0330     AM65_CPSW_STATS(, ale_ipv4_frag_drop),
0331     AM65_CPSW_STATS(, iet_rx_assembly_err),
0332     AM65_CPSW_STATS(, iet_rx_assembly_ok),
0333     AM65_CPSW_STATS(, iet_rx_smd_err),
0334     AM65_CPSW_STATS(, iet_rx_frag),
0335     AM65_CPSW_STATS(, iet_tx_hold),
0336     AM65_CPSW_STATS(, iet_tx_frag),
0337     AM65_CPSW_STATS(, tx_mem_protect_err),
0338     AM65_CPSW_STATS(, tx_pri0),
0339     AM65_CPSW_STATS(, tx_pri1),
0340     AM65_CPSW_STATS(, tx_pri2),
0341     AM65_CPSW_STATS(, tx_pri3),
0342     AM65_CPSW_STATS(, tx_pri4),
0343     AM65_CPSW_STATS(, tx_pri5),
0344     AM65_CPSW_STATS(, tx_pri6),
0345     AM65_CPSW_STATS(, tx_pri7),
0346     AM65_CPSW_STATS(, tx_pri0_bcnt),
0347     AM65_CPSW_STATS(, tx_pri1_bcnt),
0348     AM65_CPSW_STATS(, tx_pri2_bcnt),
0349     AM65_CPSW_STATS(, tx_pri3_bcnt),
0350     AM65_CPSW_STATS(, tx_pri4_bcnt),
0351     AM65_CPSW_STATS(, tx_pri5_bcnt),
0352     AM65_CPSW_STATS(, tx_pri6_bcnt),
0353     AM65_CPSW_STATS(, tx_pri7_bcnt),
0354     AM65_CPSW_STATS(, tx_pri0_drop),
0355     AM65_CPSW_STATS(, tx_pri1_drop),
0356     AM65_CPSW_STATS(, tx_pri2_drop),
0357     AM65_CPSW_STATS(, tx_pri3_drop),
0358     AM65_CPSW_STATS(, tx_pri4_drop),
0359     AM65_CPSW_STATS(, tx_pri5_drop),
0360     AM65_CPSW_STATS(, tx_pri6_drop),
0361     AM65_CPSW_STATS(, tx_pri7_drop),
0362     AM65_CPSW_STATS(, tx_pri0_drop_bcnt),
0363     AM65_CPSW_STATS(, tx_pri1_drop_bcnt),
0364     AM65_CPSW_STATS(, tx_pri2_drop_bcnt),
0365     AM65_CPSW_STATS(, tx_pri3_drop_bcnt),
0366     AM65_CPSW_STATS(, tx_pri4_drop_bcnt),
0367     AM65_CPSW_STATS(, tx_pri5_drop_bcnt),
0368     AM65_CPSW_STATS(, tx_pri6_drop_bcnt),
0369     AM65_CPSW_STATS(, tx_pri7_drop_bcnt),
0370 };
0371 
0372 /* Ethtool priv_flags */
0373 static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
0374 #define AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN   BIT(0)
0375     "p0-rx-ptype-rrobin",
0376 };
0377 
0378 static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
0379 {
0380     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0381     int ret;
0382 
0383     ret = pm_runtime_resume_and_get(common->dev);
0384     if (ret < 0)
0385         dev_err(common->dev, "ethtool begin failed %d\n", ret);
0386 
0387     return ret;
0388 }
0389 
0390 static void am65_cpsw_ethtool_op_complete(struct net_device *ndev)
0391 {
0392     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0393     int ret;
0394 
0395     ret = pm_runtime_put(common->dev);
0396     if (ret < 0 && ret != -EBUSY)
0397         dev_err(common->dev, "ethtool complete failed %d\n", ret);
0398 }
0399 
0400 static void am65_cpsw_get_drvinfo(struct net_device *ndev,
0401                   struct ethtool_drvinfo *info)
0402 {
0403     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0404 
0405     strlcpy(info->driver, dev_driver_string(common->dev),
0406         sizeof(info->driver));
0407     strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
0408 }
0409 
0410 static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
0411 {
0412     struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
0413 
0414     return priv->msg_enable;
0415 }
0416 
0417 static void am65_cpsw_set_msglevel(struct net_device *ndev, u32 value)
0418 {
0419     struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev);
0420 
0421     priv->msg_enable = value;
0422 }
0423 
0424 static void am65_cpsw_get_channels(struct net_device *ndev,
0425                    struct ethtool_channels *ch)
0426 {
0427     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0428 
0429     ch->max_rx = AM65_CPSW_MAX_RX_QUEUES;
0430     ch->max_tx = AM65_CPSW_MAX_TX_QUEUES;
0431     ch->rx_count = AM65_CPSW_MAX_RX_QUEUES;
0432     ch->tx_count = common->tx_ch_num;
0433 }
0434 
0435 static int am65_cpsw_set_channels(struct net_device *ndev,
0436                   struct ethtool_channels *chs)
0437 {
0438     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0439 
0440     if (!chs->rx_count || !chs->tx_count)
0441         return -EINVAL;
0442 
0443     /* Check if interface is up. Can change the num queues when
0444      * the interface is down.
0445      */
0446     if (common->usage_count)
0447         return -EBUSY;
0448 
0449     am65_cpsw_nuss_remove_tx_chns(common);
0450 
0451     return am65_cpsw_nuss_update_tx_chns(common, chs->tx_count);
0452 }
0453 
0454 static void
0455 am65_cpsw_get_ringparam(struct net_device *ndev,
0456             struct ethtool_ringparam *ering,
0457             struct kernel_ethtool_ringparam *kernel_ering,
0458             struct netlink_ext_ack *extack)
0459 {
0460     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0461 
0462     /* not supported */
0463     ering->tx_pending = common->tx_chns[0].descs_num;
0464     ering->rx_pending = common->rx_chns.descs_num;
0465 }
0466 
0467 static void am65_cpsw_get_pauseparam(struct net_device *ndev,
0468                      struct ethtool_pauseparam *pause)
0469 {
0470     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0471 
0472     phylink_ethtool_get_pauseparam(salve->phylink, pause);
0473 }
0474 
0475 static int am65_cpsw_set_pauseparam(struct net_device *ndev,
0476                     struct ethtool_pauseparam *pause)
0477 {
0478     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0479 
0480     return phylink_ethtool_set_pauseparam(salve->phylink, pause);
0481 }
0482 
0483 static void am65_cpsw_get_wol(struct net_device *ndev,
0484                   struct ethtool_wolinfo *wol)
0485 {
0486     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0487 
0488     phylink_ethtool_get_wol(salve->phylink, wol);
0489 }
0490 
0491 static int am65_cpsw_set_wol(struct net_device *ndev,
0492                  struct ethtool_wolinfo *wol)
0493 {
0494     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0495 
0496     return phylink_ethtool_set_wol(salve->phylink, wol);
0497 }
0498 
0499 static int am65_cpsw_get_link_ksettings(struct net_device *ndev,
0500                     struct ethtool_link_ksettings *ecmd)
0501 {
0502     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0503 
0504     return phylink_ethtool_ksettings_get(salve->phylink, ecmd);
0505 }
0506 
0507 static int
0508 am65_cpsw_set_link_ksettings(struct net_device *ndev,
0509                  const struct ethtool_link_ksettings *ecmd)
0510 {
0511     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0512 
0513     return phylink_ethtool_ksettings_set(salve->phylink, ecmd);
0514 }
0515 
0516 static int am65_cpsw_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
0517 {
0518     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0519 
0520     return phylink_ethtool_get_eee(salve->phylink, edata);
0521 }
0522 
0523 static int am65_cpsw_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
0524 {
0525     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0526 
0527     return phylink_ethtool_set_eee(salve->phylink, edata);
0528 }
0529 
0530 static int am65_cpsw_nway_reset(struct net_device *ndev)
0531 {
0532     struct am65_cpsw_slave_data *salve = am65_ndev_to_slave(ndev);
0533 
0534     return phylink_ethtool_nway_reset(salve->phylink);
0535 }
0536 
0537 static int am65_cpsw_get_regs_len(struct net_device *ndev)
0538 {
0539     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0540     u32 ale_entries, i, regdump_len = 0;
0541 
0542     ale_entries = cpsw_ale_get_num_entries(common->ale);
0543     for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
0544         if (am65_cpsw_regdump[i].hdr.module_id ==
0545             AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
0546             regdump_len += sizeof(struct am65_cpsw_regdump_hdr);
0547             regdump_len += ale_entries *
0548                        ALE_ENTRY_WORDS * sizeof(u32);
0549             continue;
0550         }
0551         regdump_len += am65_cpsw_regdump[i].hdr.len;
0552     }
0553 
0554     return regdump_len;
0555 }
0556 
0557 static void am65_cpsw_get_regs(struct net_device *ndev,
0558                    struct ethtool_regs *regs, void *p)
0559 {
0560     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0561     u32 ale_entries, i, j, pos, *reg = p;
0562 
0563     /* update CPSW IP version */
0564     regs->version = AM65_CPSW_REGDUMP_VER;
0565     ale_entries = cpsw_ale_get_num_entries(common->ale);
0566 
0567     pos = 0;
0568     for (i = 0; i < ARRAY_SIZE(am65_cpsw_regdump); i++) {
0569         reg[pos++] = am65_cpsw_regdump[i].hdr.module_id;
0570 
0571         if (am65_cpsw_regdump[i].hdr.module_id ==
0572             AM65_CPSW_REGDUMP_MOD_CPSW_ALE_TBL) {
0573             u32 ale_tbl_len = ale_entries *
0574                       ALE_ENTRY_WORDS * sizeof(u32) +
0575                       sizeof(struct am65_cpsw_regdump_hdr);
0576             reg[pos++] = ale_tbl_len;
0577             cpsw_ale_dump(common->ale, &reg[pos]);
0578             pos += ale_tbl_len;
0579             continue;
0580         }
0581 
0582         reg[pos++] = am65_cpsw_regdump[i].hdr.len;
0583 
0584         j = am65_cpsw_regdump[i].start_ofs;
0585         do {
0586             reg[pos++] = j;
0587             reg[pos++] = readl_relaxed(common->ss_base + j);
0588             j += sizeof(u32);
0589         } while (j <= am65_cpsw_regdump[i].end_ofs);
0590     }
0591 }
0592 
0593 static int am65_cpsw_get_sset_count(struct net_device *ndev, int sset)
0594 {
0595     switch (sset) {
0596     case ETH_SS_STATS:
0597         return ARRAY_SIZE(am65_host_stats) +
0598                ARRAY_SIZE(am65_slave_stats);
0599     case ETH_SS_PRIV_FLAGS:
0600         return ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
0601     default:
0602         return -EOPNOTSUPP;
0603     }
0604 }
0605 
0606 static void am65_cpsw_get_strings(struct net_device *ndev,
0607                   u32 stringset, u8 *data)
0608 {
0609     const struct am65_cpsw_ethtool_stat *hw_stats;
0610     u32 i, num_stats;
0611     u8 *p = data;
0612 
0613     switch (stringset) {
0614     case ETH_SS_STATS:
0615         num_stats = ARRAY_SIZE(am65_host_stats);
0616         hw_stats = am65_host_stats;
0617         for (i = 0; i < num_stats; i++) {
0618             memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
0619             p += ETH_GSTRING_LEN;
0620         }
0621 
0622         num_stats = ARRAY_SIZE(am65_slave_stats);
0623         hw_stats = am65_slave_stats;
0624         for (i = 0; i < num_stats; i++) {
0625             memcpy(p, hw_stats[i].desc, ETH_GSTRING_LEN);
0626             p += ETH_GSTRING_LEN;
0627         }
0628         break;
0629     case ETH_SS_PRIV_FLAGS:
0630         num_stats = ARRAY_SIZE(am65_cpsw_ethtool_priv_flags);
0631 
0632         for (i = 0; i < num_stats; i++) {
0633             memcpy(p, am65_cpsw_ethtool_priv_flags[i],
0634                    ETH_GSTRING_LEN);
0635             p += ETH_GSTRING_LEN;
0636         }
0637         break;
0638     }
0639 }
0640 
0641 static void am65_cpsw_get_ethtool_stats(struct net_device *ndev,
0642                     struct ethtool_stats *stats, u64 *data)
0643 {
0644     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0645     const struct am65_cpsw_ethtool_stat *hw_stats;
0646     struct am65_cpsw_host *host_p;
0647     struct am65_cpsw_port *port;
0648     u32 i, num_stats;
0649 
0650     host_p = am65_common_get_host(common);
0651     port = am65_ndev_to_port(ndev);
0652     num_stats = ARRAY_SIZE(am65_host_stats);
0653     hw_stats = am65_host_stats;
0654     for (i = 0; i < num_stats; i++)
0655         *data++ = readl_relaxed(host_p->stat_base +
0656                     hw_stats[i].offset);
0657 
0658     num_stats = ARRAY_SIZE(am65_slave_stats);
0659     hw_stats = am65_slave_stats;
0660     for (i = 0; i < num_stats; i++)
0661         *data++ = readl_relaxed(port->stat_base +
0662                     hw_stats[i].offset);
0663 }
0664 
0665 static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev,
0666                      struct ethtool_ts_info *info)
0667 {
0668     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0669 
0670     if (!IS_ENABLED(CONFIG_TI_K3_AM65_CPTS))
0671         return ethtool_op_get_ts_info(ndev, info);
0672 
0673     info->so_timestamping =
0674         SOF_TIMESTAMPING_TX_HARDWARE |
0675         SOF_TIMESTAMPING_TX_SOFTWARE |
0676         SOF_TIMESTAMPING_RX_HARDWARE |
0677         SOF_TIMESTAMPING_RX_SOFTWARE |
0678         SOF_TIMESTAMPING_SOFTWARE |
0679         SOF_TIMESTAMPING_RAW_HARDWARE;
0680     info->phc_index = am65_cpts_phc_index(common->cpts);
0681     info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
0682     info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
0683     return 0;
0684 }
0685 
0686 static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
0687 {
0688     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0689     u32 priv_flags = 0;
0690 
0691     if (common->pf_p0_rx_ptype_rrobin)
0692         priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
0693 
0694     return priv_flags;
0695 }
0696 
0697 static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
0698 {
0699     struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
0700     int rrobin;
0701 
0702     rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
0703 
0704     if (common->usage_count)
0705         return -EBUSY;
0706 
0707     if (common->est_enabled && rrobin) {
0708         netdev_err(ndev,
0709                "p0-rx-ptype-rrobin flag conflicts with QOS\n");
0710         return -EINVAL;
0711     }
0712 
0713     common->pf_p0_rx_ptype_rrobin = rrobin;
0714 
0715     return 0;
0716 }
0717 
0718 const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
0719     .begin          = am65_cpsw_ethtool_op_begin,
0720     .complete       = am65_cpsw_ethtool_op_complete,
0721     .get_drvinfo        = am65_cpsw_get_drvinfo,
0722     .get_msglevel       = am65_cpsw_get_msglevel,
0723     .set_msglevel       = am65_cpsw_set_msglevel,
0724     .get_channels       = am65_cpsw_get_channels,
0725     .set_channels       = am65_cpsw_set_channels,
0726     .get_ringparam      = am65_cpsw_get_ringparam,
0727     .get_regs_len       = am65_cpsw_get_regs_len,
0728     .get_regs       = am65_cpsw_get_regs,
0729     .get_sset_count     = am65_cpsw_get_sset_count,
0730     .get_strings        = am65_cpsw_get_strings,
0731     .get_ethtool_stats  = am65_cpsw_get_ethtool_stats,
0732     .get_ts_info        = am65_cpsw_get_ethtool_ts_info,
0733     .get_priv_flags     = am65_cpsw_get_ethtool_priv_flags,
0734     .set_priv_flags     = am65_cpsw_set_ethtool_priv_flags,
0735 
0736     .get_link       = ethtool_op_get_link,
0737     .get_link_ksettings = am65_cpsw_get_link_ksettings,
0738     .set_link_ksettings = am65_cpsw_set_link_ksettings,
0739     .get_pauseparam     = am65_cpsw_get_pauseparam,
0740     .set_pauseparam     = am65_cpsw_set_pauseparam,
0741     .get_wol        = am65_cpsw_get_wol,
0742     .set_wol        = am65_cpsw_set_wol,
0743     .get_eee        = am65_cpsw_get_eee,
0744     .set_eee        = am65_cpsw_set_eee,
0745     .nway_reset     = am65_cpsw_nway_reset,
0746 };