|
11 | 11 | #include <linux/pm_runtime.h>
|
12 | 12 |
|
13 | 13 | #include "am65-cpsw-nuss.h"
|
| 14 | +#include "am65-cpsw-qos.h" |
14 | 15 | #include "cpsw_ale.h"
|
15 | 16 | #include "am65-cpts.h"
|
16 | 17 |
|
@@ -670,6 +671,9 @@ static void am65_cpsw_get_eth_mac_stats(struct net_device *ndev,
|
670 | 671 |
|
671 | 672 | stats = port->stat_base;
|
672 | 673 |
|
| 674 | + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) |
| 675 | + return; |
| 676 | + |
673 | 677 | s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames);
|
674 | 678 | s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames);
|
675 | 679 | s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames);
|
@@ -740,6 +744,166 @@ static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
|
740 | 744 | return 0;
|
741 | 745 | }
|
742 | 746 |
|
| 747 | +static 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 | + |
| 761 | +static 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 | + |
| 774 | +static 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 | + |
| 827 | +static 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 | + |
| 889 | +static 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 | + |
743 | 907 | const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
|
744 | 908 | .begin = am65_cpsw_ethtool_op_begin,
|
745 | 909 | .complete = am65_cpsw_ethtool_op_complete,
|
@@ -769,4 +933,7 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
|
769 | 933 | .get_eee = am65_cpsw_get_eee,
|
770 | 934 | .set_eee = am65_cpsw_set_eee,
|
771 | 935 | .nway_reset = am65_cpsw_nway_reset,
|
| 936 | + .get_mm = am65_cpsw_get_mm, |
| 937 | + .set_mm = am65_cpsw_set_mm, |
| 938 | + .get_mm_stats = am65_cpsw_get_mm_stats, |
772 | 939 | };
|
0 commit comments