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,240 @@ 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
+
907
+ static 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
+
922
+ static 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
+
938
+ static 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
+
959
+ static 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
+
743
981
const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
744
982
.begin = am65_cpsw_ethtool_op_begin ,
745
983
.complete = am65_cpsw_ethtool_op_complete ,
@@ -758,6 +996,11 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
758
996
.get_ts_info = am65_cpsw_get_ethtool_ts_info ,
759
997
.get_priv_flags = am65_cpsw_get_ethtool_priv_flags ,
760
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 ,
761
1004
762
1005
.get_link = ethtool_op_get_link ,
763
1006
.get_link_ksettings = am65_cpsw_get_link_ksettings ,
@@ -769,4 +1012,7 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
769
1012
.get_eee = am65_cpsw_get_eee ,
770
1013
.set_eee = am65_cpsw_set_eee ,
771
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 ,
772
1018
};
0 commit comments