Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'am65-cpsw-preemption-coalescing'

Roger Quadros says:

====================
net: ethernet: am65-cpsw: Add mqprio, frame preemption & coalescing

This series adds mqprio qdisc offload in channel mode,
Frame Preemption MAC merge support and RX/TX coalesing
for AM65 CPSW driver.

In v11 following changes were made
- Fix patch "net: ethernet: ti: am65-cpsw: add mqprio qdisc offload in channel mode"
by including units.h

Changelog information in each patch file.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+1104 -191
+8 -6
drivers/net/ethernet/ti/Kconfig
··· 134 134 protocol, Ethernet Enhanced Scheduled Traffic Operations (CPTS_ESTFn) 135 135 and PCIe Subsystem Precision Time Measurement (PTM). 136 136 137 - config TI_AM65_CPSW_TAS 138 - bool "Enable TAS offload in AM65 CPSW" 137 + config TI_AM65_CPSW_QOS 138 + bool "Enable QoS offload features in AM65 CPSW" 139 139 depends on TI_K3_AM65_CPSW_NUSS && NET_SCH_TAPRIO && TI_K3_AM65_CPTS 140 140 help 141 - Say y here to support Time Aware Shaper(TAS) offload in AM65 CPSW. 142 - AM65 CPSW hardware supports Enhanced Scheduled Traffic (EST) 143 - defined in IEEE 802.1Q 2018. The EST scheduler runs on CPTS and the 144 - TAS/EST schedule is updated in the Fetch RAM memory of the CPSW. 141 + This option enables QoS offload features in AM65 CPSW like 142 + Time Aware Shaper (TAS) / Enhanced Scheduled Traffic (EST), 143 + MQPRIO qdisc offload and Frame-Preemption MAC Merge / Interspersing 144 + Express Traffic (IET). 145 + The EST scheduler runs on CPTS and the TAS/EST schedule is 146 + updated in the Fetch RAM memory of the CPSW. 145 147 146 148 config TI_KEYSTONE_NETCP 147 149 tristate "TI Keystone NETCP Core Support"
+2 -1
drivers/net/ethernet/ti/Makefile
··· 26 26 obj-$(CONFIG_TI_K3_CPPI_DESC_POOL) += k3-cppi-desc-pool.o 27 27 28 28 obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o 29 - ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o am65-cpsw-qos.o 29 + ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o 30 + ti-am65-cpsw-nuss-$(CONFIG_TI_AM65_CPSW_QOS) += am65-cpsw-qos.o 30 31 ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o 31 32 obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o 32 33
+246
drivers/net/ethernet/ti/am65-cpsw-ethtool.c
··· 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 ··· 671 670 672 671 stats = port->stat_base; 673 672 673 + if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) 674 + return; 675 + 674 676 s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames); 675 677 s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames); 676 678 s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames); ··· 744 740 return 0; 745 741 } 746 742 743 + static void am65_cpsw_port_iet_rx_enable(struct am65_cpsw_port *port, bool enable) 744 + { 745 + u32 val; 746 + 747 + val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); 748 + if (enable) 749 + val |= AM65_CPSW_PN_CTL_IET_PORT_EN; 750 + else 751 + val &= ~AM65_CPSW_PN_CTL_IET_PORT_EN; 752 + 753 + writel(val, port->port_base + AM65_CPSW_PN_REG_CTL); 754 + am65_cpsw_iet_common_enable(port->common); 755 + } 756 + 757 + static void am65_cpsw_port_iet_tx_enable(struct am65_cpsw_port *port, bool enable) 758 + { 759 + u32 val; 760 + 761 + val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 762 + if (enable) 763 + val |= AM65_CPSW_PN_IET_MAC_PENABLE; 764 + else 765 + val &= ~AM65_CPSW_PN_IET_MAC_PENABLE; 766 + 767 + writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 768 + } 769 + 770 + static int am65_cpsw_get_mm(struct net_device *ndev, struct ethtool_mm_state *state) 771 + { 772 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 773 + struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev); 774 + u32 port_ctrl, iet_ctrl, iet_status; 775 + u32 add_frag_size; 776 + 777 + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS)) 778 + return -EOPNOTSUPP; 779 + 780 + mutex_lock(&priv->mm_lock); 781 + 782 + iet_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 783 + port_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_CTL); 784 + 785 + state->tx_enabled = !!(iet_ctrl & AM65_CPSW_PN_IET_MAC_PENABLE); 786 + state->pmac_enabled = !!(port_ctrl & AM65_CPSW_PN_CTL_IET_PORT_EN); 787 + 788 + iet_status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); 789 + 790 + if (iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY) 791 + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED; 792 + else if (iet_status & AM65_CPSW_PN_MAC_VERIFIED) 793 + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED; 794 + else if (iet_status & AM65_CPSW_PN_MAC_VERIFY_FAIL) 795 + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED; 796 + else 797 + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN; 798 + 799 + add_frag_size = AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(iet_ctrl); 800 + state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size); 801 + 802 + /* Errata i2208: RX min fragment size cannot be less than 124 */ 803 + state->rx_min_frag_size = 124; 804 + 805 + /* FPE active if common tx_enabled and verification success or disabled (forced) */ 806 + state->tx_active = state->tx_enabled && 807 + (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED || 808 + state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED); 809 + state->verify_enabled = !(iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY); 810 + 811 + state->verify_time = port->qos.iet.verify_time_ms; 812 + 813 + /* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime 814 + * variable has a range between 1 and 128 ms inclusive. Limit to that. 815 + */ 816 + state->max_verify_time = 128; 817 + 818 + mutex_unlock(&priv->mm_lock); 819 + 820 + return 0; 821 + } 822 + 823 + static int am65_cpsw_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg, 824 + struct netlink_ext_ack *extack) 825 + { 826 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 827 + struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev); 828 + struct am65_cpsw_iet *iet = &port->qos.iet; 829 + u32 val, add_frag_size; 830 + int err; 831 + 832 + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS)) 833 + return -EOPNOTSUPP; 834 + 835 + err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, &add_frag_size, extack); 836 + if (err) 837 + return err; 838 + 839 + mutex_lock(&priv->mm_lock); 840 + 841 + if (cfg->pmac_enabled) { 842 + /* change TX & RX FIFO MAX_BLKS as per TRM recommendation */ 843 + if (!iet->original_max_blks) 844 + iet->original_max_blks = readl(port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); 845 + 846 + writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET, 847 + port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); 848 + } else if (iet->original_max_blks) { 849 + /* restore RX & TX FIFO MAX_BLKS */ 850 + writel(iet->original_max_blks, 851 + port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); 852 + } 853 + 854 + am65_cpsw_port_iet_rx_enable(port, cfg->pmac_enabled); 855 + am65_cpsw_port_iet_tx_enable(port, cfg->tx_enabled); 856 + 857 + val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 858 + if (cfg->verify_enabled) { 859 + val &= ~AM65_CPSW_PN_IET_MAC_DISABLEVERIFY; 860 + /* Reset Verify state machine. Verification won't start here. 861 + * Verification will be done once link-up. 862 + */ 863 + val |= AM65_CPSW_PN_IET_MAC_LINKFAIL; 864 + } else { 865 + val |= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY; 866 + /* Clear LINKFAIL to allow verify/response packets */ 867 + val &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; 868 + } 869 + 870 + val &= ~AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK; 871 + val |= AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(add_frag_size); 872 + writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 873 + 874 + /* verify_timeout_count can only be set at valid link */ 875 + port->qos.iet.verify_time_ms = cfg->verify_time; 876 + 877 + /* enable/disable preemption based on link status */ 878 + am65_cpsw_iet_commit_preemptible_tcs(port); 879 + 880 + mutex_unlock(&priv->mm_lock); 881 + 882 + return 0; 883 + } 884 + 885 + static void am65_cpsw_get_mm_stats(struct net_device *ndev, 886 + struct ethtool_mm_stats *s) 887 + { 888 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 889 + void __iomem *base = port->stat_base; 890 + 891 + s->MACMergeFrameAssOkCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK); 892 + s->MACMergeFrameAssErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR); 893 + s->MACMergeFrameSmdErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_SMD_ERROR); 894 + /* CPSW Functional Spec states: 895 + * "The IET stat aMACMergeFragCountRx is derived by adding the 896 + * Receive Assembly Error count to this value. i.e. AM65_CPSW_STATN_IET_RX_FRAG" 897 + */ 898 + s->MACMergeFragCountRx = readl(base + AM65_CPSW_STATN_IET_RX_FRAG) + s->MACMergeFrameAssErrorCount; 899 + s->MACMergeFragCountTx = readl(base + AM65_CPSW_STATN_IET_TX_FRAG); 900 + s->MACMergeHoldCount = readl(base + AM65_CPSW_STATN_IET_TX_HOLD); 901 + } 902 + 903 + static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, 904 + struct kernel_ethtool_coalesce *kernel_coal, 905 + struct netlink_ext_ack *extack) 906 + { 907 + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); 908 + struct am65_cpsw_tx_chn *tx_chn; 909 + 910 + tx_chn = &common->tx_chns[0]; 911 + 912 + coal->rx_coalesce_usecs = common->rx_pace_timeout / 1000; 913 + coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000; 914 + 915 + return 0; 916 + } 917 + 918 + static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue, 919 + struct ethtool_coalesce *coal) 920 + { 921 + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); 922 + struct am65_cpsw_tx_chn *tx_chn; 923 + 924 + if (queue >= AM65_CPSW_MAX_TX_QUEUES) 925 + return -EINVAL; 926 + 927 + tx_chn = &common->tx_chns[queue]; 928 + 929 + coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000; 930 + 931 + return 0; 932 + } 933 + 934 + static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, 935 + struct kernel_ethtool_coalesce *kernel_coal, 936 + struct netlink_ext_ack *extack) 937 + { 938 + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); 939 + struct am65_cpsw_tx_chn *tx_chn; 940 + 941 + tx_chn = &common->tx_chns[0]; 942 + 943 + if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20) 944 + return -EINVAL; 945 + 946 + if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) 947 + return -EINVAL; 948 + 949 + common->rx_pace_timeout = coal->rx_coalesce_usecs * 1000; 950 + tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000; 951 + 952 + return 0; 953 + } 954 + 955 + static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue, 956 + struct ethtool_coalesce *coal) 957 + { 958 + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); 959 + struct am65_cpsw_tx_chn *tx_chn; 960 + 961 + if (queue >= AM65_CPSW_MAX_TX_QUEUES) 962 + return -EINVAL; 963 + 964 + tx_chn = &common->tx_chns[queue]; 965 + 966 + if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) { 967 + dev_info(common->dev, "defaulting to min value of 20us for tx-usecs for tx-%u\n", 968 + queue); 969 + coal->tx_coalesce_usecs = 20; 970 + } 971 + 972 + tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000; 973 + 974 + return 0; 975 + } 976 + 747 977 const struct ethtool_ops am65_cpsw_ethtool_ops_slave = { 748 978 .begin = am65_cpsw_ethtool_op_begin, 749 979 .complete = am65_cpsw_ethtool_op_complete, ··· 996 758 .get_ts_info = am65_cpsw_get_ethtool_ts_info, 997 759 .get_priv_flags = am65_cpsw_get_ethtool_priv_flags, 998 760 .set_priv_flags = am65_cpsw_set_ethtool_priv_flags, 761 + .supported_coalesce_params = ETHTOOL_COALESCE_USECS, 762 + .get_coalesce = am65_cpsw_get_coalesce, 763 + .set_coalesce = am65_cpsw_set_coalesce, 764 + .get_per_queue_coalesce = am65_cpsw_get_per_queue_coalesce, 765 + .set_per_queue_coalesce = am65_cpsw_set_per_queue_coalesce, 999 766 1000 767 .get_link = ethtool_op_get_link, 1001 768 .get_link_ksettings = am65_cpsw_get_link_ksettings, ··· 1012 769 .get_eee = am65_cpsw_get_eee, 1013 770 .set_eee = am65_cpsw_set_eee, 1014 771 .nway_reset = am65_cpsw_nway_reset, 772 + .get_mm = am65_cpsw_get_mm, 773 + .set_mm = am65_cpsw_set_mm, 774 + .get_mm_stats = am65_cpsw_get_mm_stats, 1015 775 };
+56 -8
drivers/net/ethernet/ti/am65-cpsw-nuss.c
··· 596 596 msecs_to_jiffies(1000)); 597 597 if (!i) 598 598 dev_err(common->dev, "tx timeout\n"); 599 - for (i = 0; i < common->tx_ch_num; i++) 599 + for (i = 0; i < common->tx_ch_num; i++) { 600 600 napi_disable(&common->tx_chns[i].napi_tx); 601 + hrtimer_cancel(&common->tx_chns[i].tx_hrtimer); 602 + } 601 603 602 604 for (i = 0; i < common->tx_ch_num; i++) { 603 605 k3_udma_glue_reset_tx_chn(common->tx_chns[i].tx_chn, ··· 618 616 } 619 617 620 618 napi_disable(&common->napi_rx); 619 + hrtimer_cancel(&common->rx_hrtimer); 621 620 622 621 for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++) 623 622 k3_udma_glue_reset_rx_chn(common->rx_chns.rx_chn, i, ··· 888 885 return ret; 889 886 } 890 887 888 + static enum hrtimer_restart am65_cpsw_nuss_rx_timer_callback(struct hrtimer *timer) 889 + { 890 + struct am65_cpsw_common *common = 891 + container_of(timer, struct am65_cpsw_common, rx_hrtimer); 892 + 893 + enable_irq(common->rx_chns.irq); 894 + return HRTIMER_NORESTART; 895 + } 896 + 891 897 static int am65_cpsw_nuss_rx_poll(struct napi_struct *napi_rx, int budget) 892 898 { 893 899 struct am65_cpsw_common *common = am65_cpsw_napi_to_common(napi_rx); ··· 924 912 if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) { 925 913 if (common->rx_irq_disabled) { 926 914 common->rx_irq_disabled = false; 927 - enable_irq(common->rx_chns.irq); 915 + if (unlikely(common->rx_pace_timeout)) { 916 + hrtimer_start(&common->rx_hrtimer, 917 + ns_to_ktime(common->rx_pace_timeout), 918 + HRTIMER_MODE_REL_PINNED); 919 + } else { 920 + enable_irq(common->rx_chns.irq); 921 + } 928 922 } 929 923 } 930 924 ··· 986 968 } 987 969 988 970 static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common, 989 - int chn, unsigned int budget) 971 + int chn, unsigned int budget, bool *tdown) 990 972 { 991 973 struct device *dev = common->dev; 992 974 struct am65_cpsw_tx_chn *tx_chn; ··· 1009 991 if (cppi5_desc_is_tdcm(desc_dma)) { 1010 992 if (atomic_dec_and_test(&common->tdown_cnt)) 1011 993 complete(&common->tdown_complete); 994 + *tdown = true; 1012 995 break; 1013 996 } 1014 997 ··· 1032 1013 } 1033 1014 1034 1015 static int am65_cpsw_nuss_tx_compl_packets_2g(struct am65_cpsw_common *common, 1035 - int chn, unsigned int budget) 1016 + int chn, unsigned int budget, bool *tdown) 1036 1017 { 1037 1018 struct device *dev = common->dev; 1038 1019 struct am65_cpsw_tx_chn *tx_chn; ··· 1053 1034 if (cppi5_desc_is_tdcm(desc_dma)) { 1054 1035 if (atomic_dec_and_test(&common->tdown_cnt)) 1055 1036 complete(&common->tdown_complete); 1037 + *tdown = true; 1056 1038 break; 1057 1039 } 1058 1040 ··· 1079 1059 return num_tx; 1080 1060 } 1081 1061 1062 + static enum hrtimer_restart am65_cpsw_nuss_tx_timer_callback(struct hrtimer *timer) 1063 + { 1064 + struct am65_cpsw_tx_chn *tx_chns = 1065 + container_of(timer, struct am65_cpsw_tx_chn, tx_hrtimer); 1066 + 1067 + enable_irq(tx_chns->irq); 1068 + return HRTIMER_NORESTART; 1069 + } 1070 + 1082 1071 static int am65_cpsw_nuss_tx_poll(struct napi_struct *napi_tx, int budget) 1083 1072 { 1084 1073 struct am65_cpsw_tx_chn *tx_chn = am65_cpsw_napi_to_tx_chn(napi_tx); 1074 + bool tdown = false; 1085 1075 int num_tx; 1086 1076 1087 1077 if (AM65_CPSW_IS_CPSW2G(tx_chn->common)) 1088 - num_tx = am65_cpsw_nuss_tx_compl_packets_2g(tx_chn->common, tx_chn->id, budget); 1078 + num_tx = am65_cpsw_nuss_tx_compl_packets_2g(tx_chn->common, tx_chn->id, 1079 + budget, &tdown); 1089 1080 else 1090 - num_tx = am65_cpsw_nuss_tx_compl_packets(tx_chn->common, tx_chn->id, budget); 1081 + num_tx = am65_cpsw_nuss_tx_compl_packets(tx_chn->common, 1082 + tx_chn->id, budget, &tdown); 1091 1083 1092 1084 if (num_tx >= budget) 1093 1085 return budget; 1094 1086 1095 - if (napi_complete_done(napi_tx, num_tx)) 1096 - enable_irq(tx_chn->irq); 1087 + if (napi_complete_done(napi_tx, num_tx)) { 1088 + if (unlikely(tx_chn->tx_pace_timeout && !tdown)) { 1089 + hrtimer_start(&tx_chn->tx_hrtimer, 1090 + ns_to_ktime(tx_chn->tx_pace_timeout), 1091 + HRTIMER_MODE_REL_PINNED); 1092 + } else { 1093 + enable_irq(tx_chn->irq); 1094 + } 1095 + } 1097 1096 1098 1097 return 0; 1099 1098 } ··· 1744 1705 1745 1706 netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx, 1746 1707 am65_cpsw_nuss_tx_poll); 1708 + hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); 1709 + tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback; 1747 1710 1748 1711 ret = devm_request_irq(dev, tx_chn->irq, 1749 1712 am65_cpsw_nuss_tx_irq, ··· 1971 1930 1972 1931 netif_napi_add(common->dma_ndev, &common->napi_rx, 1973 1932 am65_cpsw_nuss_rx_poll); 1933 + hrtimer_init(&common->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); 1934 + common->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback; 1974 1935 1975 1936 ret = devm_request_irq(dev, rx_chn->irq, 1976 1937 am65_cpsw_nuss_rx_irq, ··· 2170 2127 dev_err(dev, "Use random MAC address\n"); 2171 2128 } 2172 2129 } 2130 + 2131 + /* Reset all Queue priorities to 0 */ 2132 + writel(0, port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); 2173 2133 } 2174 2134 of_node_put(node); 2175 2135 ··· 2237 2191 ndev_priv = netdev_priv(port->ndev); 2238 2192 ndev_priv->port = port; 2239 2193 ndev_priv->msg_enable = AM65_CPSW_DEBUG; 2194 + mutex_init(&ndev_priv->mm_lock); 2195 + port->qos.link_speed = SPEED_UNKNOWN; 2240 2196 SET_NETDEV_DEV(port->ndev, dev); 2241 2197 2242 2198 eth_hw_addr_set(port->ndev, port->slave.mac_addr);
+9
drivers/net/ethernet/ti/am65-cpsw-nuss.h
··· 75 75 struct k3_cppi_desc_pool *desc_pool; 76 76 struct k3_udma_glue_tx_channel *tx_chn; 77 77 spinlock_t lock; /* protect TX rings in multi-port mode */ 78 + struct hrtimer tx_hrtimer; 79 + unsigned long tx_pace_timeout; 78 80 int irq; 79 81 u32 id; 80 82 u32 descs_num; ··· 140 138 struct napi_struct napi_rx; 141 139 142 140 bool rx_irq_disabled; 141 + struct hrtimer rx_hrtimer; 142 + unsigned long rx_pace_timeout; 143 143 144 144 u32 nuss_ver; 145 145 u32 cpsw_ver; ··· 149 145 bool pf_p0_rx_ptype_rrobin; 150 146 struct am65_cpts *cpts; 151 147 int est_enabled; 148 + bool iet_enabled; 152 149 153 150 bool is_emac_mode; 154 151 u16 br_members; ··· 175 170 struct am65_cpsw_port *port; 176 171 struct am65_cpsw_ndev_stats __percpu *stats; 177 172 bool offload_fwd_mark; 173 + /* Serialize access to MAC Merge state between ethtool requests 174 + * and link state updates 175 + */ 176 + struct mutex mm_lock; 178 177 }; 179 178 180 179 #define am65_ndev_to_priv(ndev) \
+542 -174
drivers/net/ethernet/ti/am65-cpsw-qos.c
··· 4 4 * 5 5 * quality of service module includes: 6 6 * Enhanced Scheduler Traffic (EST - P802.1Qbv/D2.2) 7 + * Interspersed Express Traffic (IET - P802.3br/D2.0) 7 8 */ 8 9 9 10 #include <linux/pm_runtime.h> 11 + #include <linux/math.h> 10 12 #include <linux/time.h> 13 + #include <linux/units.h> 11 14 #include <net/pkt_cls.h> 12 15 13 16 #include "am65-cpsw-nuss.h" ··· 18 15 #include "am65-cpts.h" 19 16 #include "cpsw_ale.h" 20 17 21 - #define AM65_CPSW_REG_CTL 0x004 22 - #define AM65_CPSW_PN_REG_CTL 0x004 23 - #define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 24 - #define AM65_CPSW_PN_REG_EST_CTL 0x060 25 - #define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) 26 - 27 - /* AM65_CPSW_REG_CTL register fields */ 28 - #define AM65_CPSW_CTL_EST_EN BIT(18) 29 - 30 - /* AM65_CPSW_PN_REG_CTL register fields */ 31 - #define AM65_CPSW_PN_CTL_EST_PORT_EN BIT(17) 32 - 33 - /* AM65_CPSW_PN_REG_EST_CTL register fields */ 34 - #define AM65_CPSW_PN_EST_ONEBUF BIT(0) 35 - #define AM65_CPSW_PN_EST_BUFSEL BIT(1) 36 - #define AM65_CPSW_PN_EST_TS_EN BIT(2) 37 - #define AM65_CPSW_PN_EST_TS_FIRST BIT(3) 38 - #define AM65_CPSW_PN_EST_ONEPRI BIT(4) 39 - #define AM65_CPSW_PN_EST_TS_PRI_MSK GENMASK(7, 5) 40 - 41 - /* AM65_CPSW_PN_REG_FIFO_STATUS register fields */ 42 - #define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK GENMASK(7, 0) 43 - #define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK GENMASK(15, 8) 44 - #define AM65_CPSW_PN_FST_EST_CNT_ERR BIT(16) 45 - #define AM65_CPSW_PN_FST_EST_ADD_ERR BIT(17) 46 - #define AM65_CPSW_PN_FST_EST_BUFACT BIT(18) 47 - 48 - /* EST FETCH COMMAND RAM */ 49 - #define AM65_CPSW_FETCH_RAM_CMD_NUM 0x80 50 - #define AM65_CPSW_FETCH_CNT_MSK GENMASK(21, 8) 51 - #define AM65_CPSW_FETCH_CNT_MAX (AM65_CPSW_FETCH_CNT_MSK >> 8) 52 - #define AM65_CPSW_FETCH_CNT_OFFSET 8 53 - #define AM65_CPSW_FETCH_ALLOW_MSK GENMASK(7, 0) 54 - #define AM65_CPSW_FETCH_ALLOW_MAX AM65_CPSW_FETCH_ALLOW_MSK 18 + #define TO_MBPS(x) DIV_ROUND_UP((x), BYTES_PER_MBIT) 55 19 56 20 enum timer_act { 57 21 TACT_PROG, /* need program timer */ 58 22 TACT_NEED_STOP, /* need stop first */ 59 23 TACT_SKIP_PROG, /* just buffer can be updated */ 60 24 }; 25 + 26 + static void am65_cpsw_iet_change_preemptible_tcs(struct am65_cpsw_port *port, u8 preemptible_tcs); 27 + 28 + static u32 29 + am65_cpsw_qos_tx_rate_calc(u32 rate_mbps, unsigned long bus_freq) 30 + { 31 + u32 ir; 32 + 33 + bus_freq /= 1000000; 34 + ir = DIV_ROUND_UP(((u64)rate_mbps * 32768), bus_freq); 35 + return ir; 36 + } 37 + 38 + static void am65_cpsw_tx_pn_shaper_reset(struct am65_cpsw_port *port) 39 + { 40 + int prio; 41 + 42 + for (prio = 0; prio < AM65_CPSW_PN_FIFO_PRIO_NUM; prio++) { 43 + writel(0, port->port_base + AM65_CPSW_PN_REG_PRI_CIR(prio)); 44 + writel(0, port->port_base + AM65_CPSW_PN_REG_PRI_EIR(prio)); 45 + } 46 + } 47 + 48 + static void am65_cpsw_tx_pn_shaper_apply(struct am65_cpsw_port *port) 49 + { 50 + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; 51 + struct am65_cpsw_common *common = port->common; 52 + struct tc_mqprio_qopt_offload *mqprio; 53 + bool enable, shaper_susp = false; 54 + u32 rate_mbps; 55 + int tc, prio; 56 + 57 + mqprio = &p_mqprio->mqprio_hw; 58 + /* takes care of no link case as well */ 59 + if (p_mqprio->max_rate_total > port->qos.link_speed) 60 + shaper_susp = true; 61 + 62 + am65_cpsw_tx_pn_shaper_reset(port); 63 + 64 + enable = p_mqprio->shaper_en && !shaper_susp; 65 + if (!enable) 66 + return; 67 + 68 + /* Rate limit is specified per Traffic Class but 69 + * for CPSW, rate limit can be applied per priority 70 + * at port FIFO. 71 + * 72 + * We have assigned the same priority (TCn) to all queues 73 + * of a Traffic Class so they share the same shaper 74 + * bandwidth. 75 + */ 76 + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { 77 + prio = tc; 78 + 79 + rate_mbps = TO_MBPS(mqprio->min_rate[tc]); 80 + rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, 81 + common->bus_freq); 82 + writel(rate_mbps, 83 + port->port_base + AM65_CPSW_PN_REG_PRI_CIR(prio)); 84 + 85 + rate_mbps = 0; 86 + 87 + if (mqprio->max_rate[tc]) { 88 + rate_mbps = mqprio->max_rate[tc] - mqprio->min_rate[tc]; 89 + rate_mbps = TO_MBPS(rate_mbps); 90 + rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, 91 + common->bus_freq); 92 + } 93 + 94 + writel(rate_mbps, 95 + port->port_base + AM65_CPSW_PN_REG_PRI_EIR(prio)); 96 + } 97 + } 98 + 99 + static int am65_cpsw_mqprio_verify_shaper(struct am65_cpsw_port *port, 100 + struct tc_mqprio_qopt_offload *mqprio) 101 + { 102 + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; 103 + struct netlink_ext_ack *extack = mqprio->extack; 104 + u64 min_rate_total = 0, max_rate_total = 0; 105 + u32 min_rate_msk = 0, max_rate_msk = 0; 106 + bool has_min_rate, has_max_rate; 107 + int num_tc, i; 108 + 109 + if (!(mqprio->flags & TC_MQPRIO_F_SHAPER)) 110 + return 0; 111 + 112 + if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) 113 + return 0; 114 + 115 + has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); 116 + has_max_rate = !!(mqprio->flags & TC_MQPRIO_F_MAX_RATE); 117 + 118 + if (!has_min_rate && has_max_rate) { 119 + NL_SET_ERR_MSG_MOD(extack, "min_rate is required with max_rate"); 120 + return -EOPNOTSUPP; 121 + } 122 + 123 + if (!has_min_rate) 124 + return 0; 125 + 126 + num_tc = mqprio->qopt.num_tc; 127 + 128 + for (i = num_tc - 1; i >= 0; i--) { 129 + u32 ch_msk; 130 + 131 + if (mqprio->min_rate[i]) 132 + min_rate_msk |= BIT(i); 133 + min_rate_total += mqprio->min_rate[i]; 134 + 135 + if (has_max_rate) { 136 + if (mqprio->max_rate[i]) 137 + max_rate_msk |= BIT(i); 138 + max_rate_total += mqprio->max_rate[i]; 139 + 140 + if (!mqprio->min_rate[i] && mqprio->max_rate[i]) { 141 + NL_SET_ERR_MSG_FMT_MOD(extack, 142 + "TX tc%d rate max>0 but min=0", 143 + i); 144 + return -EINVAL; 145 + } 146 + 147 + if (mqprio->max_rate[i] && 148 + mqprio->max_rate[i] < mqprio->min_rate[i]) { 149 + NL_SET_ERR_MSG_FMT_MOD(extack, 150 + "TX tc%d rate min(%llu)>max(%llu)", 151 + i, mqprio->min_rate[i], 152 + mqprio->max_rate[i]); 153 + return -EINVAL; 154 + } 155 + } 156 + 157 + ch_msk = GENMASK(num_tc - 1, i); 158 + if ((min_rate_msk & BIT(i)) && (min_rate_msk ^ ch_msk)) { 159 + NL_SET_ERR_MSG_FMT_MOD(extack, 160 + "Min rate must be set sequentially hi->lo tx_rate_msk%x", 161 + min_rate_msk); 162 + return -EINVAL; 163 + } 164 + 165 + if ((max_rate_msk & BIT(i)) && (max_rate_msk ^ ch_msk)) { 166 + NL_SET_ERR_MSG_FMT_MOD(extack, 167 + "Max rate must be set sequentially hi->lo tx_rate_msk%x", 168 + max_rate_msk); 169 + return -EINVAL; 170 + } 171 + } 172 + 173 + min_rate_total = TO_MBPS(min_rate_total); 174 + max_rate_total = TO_MBPS(max_rate_total); 175 + 176 + p_mqprio->shaper_en = true; 177 + p_mqprio->max_rate_total = max_t(u64, min_rate_total, max_rate_total); 178 + 179 + return 0; 180 + } 181 + 182 + static void am65_cpsw_reset_tc_mqprio(struct net_device *ndev) 183 + { 184 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 185 + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; 186 + 187 + p_mqprio->shaper_en = false; 188 + p_mqprio->max_rate_total = 0; 189 + 190 + am65_cpsw_tx_pn_shaper_reset(port); 191 + netdev_reset_tc(ndev); 192 + 193 + /* Reset all Queue priorities to 0 */ 194 + writel(0, port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); 195 + 196 + am65_cpsw_iet_change_preemptible_tcs(port, 0); 197 + } 198 + 199 + static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data) 200 + { 201 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 202 + struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; 203 + struct tc_mqprio_qopt_offload *mqprio = type_data; 204 + struct am65_cpsw_common *common = port->common; 205 + struct tc_mqprio_qopt *qopt = &mqprio->qopt; 206 + int i, tc, offset, count, prio, ret; 207 + u8 num_tc = qopt->num_tc; 208 + u32 tx_prio_map = 0; 209 + 210 + memcpy(&p_mqprio->mqprio_hw, mqprio, sizeof(*mqprio)); 211 + 212 + ret = pm_runtime_get_sync(common->dev); 213 + if (ret < 0) { 214 + pm_runtime_put_noidle(common->dev); 215 + return ret; 216 + } 217 + 218 + if (!num_tc) { 219 + am65_cpsw_reset_tc_mqprio(ndev); 220 + ret = 0; 221 + goto exit_put; 222 + } 223 + 224 + ret = am65_cpsw_mqprio_verify_shaper(port, mqprio); 225 + if (ret) 226 + goto exit_put; 227 + 228 + netdev_set_num_tc(ndev, num_tc); 229 + 230 + /* Multiple Linux priorities can map to a Traffic Class 231 + * A Traffic Class can have multiple contiguous Queues, 232 + * Queues get mapped to Channels (thread_id), 233 + * if not VLAN tagged, thread_id is used as packet_priority 234 + * if VLAN tagged. VLAN priority is used as packet_priority 235 + * packet_priority gets mapped to header_priority in p0_rx_pri_map, 236 + * header_priority gets mapped to switch_priority in pn_tx_pri_map. 237 + * As p0_rx_pri_map is left at defaults (0x76543210), we can 238 + * assume that Queue_n gets mapped to header_priority_n. We can then 239 + * set the switch priority in pn_tx_pri_map. 240 + */ 241 + 242 + for (tc = 0; tc < num_tc; tc++) { 243 + prio = tc; 244 + 245 + /* For simplicity we assign the same priority (TCn) to 246 + * all queues of a Traffic Class. 247 + */ 248 + for (i = qopt->offset[tc]; i < qopt->offset[tc] + qopt->count[tc]; i++) 249 + tx_prio_map |= prio << (4 * i); 250 + 251 + count = qopt->count[tc]; 252 + offset = qopt->offset[tc]; 253 + netdev_set_tc_queue(ndev, tc, count, offset); 254 + } 255 + 256 + writel(tx_prio_map, port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); 257 + 258 + am65_cpsw_tx_pn_shaper_apply(port); 259 + am65_cpsw_iet_change_preemptible_tcs(port, mqprio->preemptible_tcs); 260 + 261 + exit_put: 262 + pm_runtime_put(common->dev); 263 + 264 + return ret; 265 + } 266 + 267 + static int am65_cpsw_iet_set_verify_timeout_count(struct am65_cpsw_port *port) 268 + { 269 + int verify_time_ms = port->qos.iet.verify_time_ms; 270 + u32 val; 271 + 272 + /* The number of wireside clocks contained in the verify 273 + * timeout counter. The default is 0x1312d0 274 + * (10ms at 125Mhz in 1G mode). 275 + */ 276 + val = 125 * HZ_PER_MHZ; /* assuming 125MHz wireside clock */ 277 + 278 + val /= MILLIHZ_PER_HZ; /* count per ms timeout */ 279 + val *= verify_time_ms; /* count for timeout ms */ 280 + 281 + if (val > AM65_CPSW_PN_MAC_VERIFY_CNT_MASK) 282 + return -EINVAL; 283 + 284 + writel(val, port->port_base + AM65_CPSW_PN_REG_IET_VERIFY); 285 + 286 + return 0; 287 + } 288 + 289 + static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port) 290 + { 291 + u32 ctrl, status; 292 + int try; 293 + 294 + try = 20; 295 + do { 296 + /* Reset the verify state machine by writing 1 297 + * to LINKFAIL 298 + */ 299 + ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 300 + ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL; 301 + writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 302 + 303 + /* Clear MAC_LINKFAIL bit to start Verify. */ 304 + ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 305 + ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; 306 + writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 307 + 308 + msleep(port->qos.iet.verify_time_ms); 309 + 310 + status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); 311 + if (status & AM65_CPSW_PN_MAC_VERIFIED) 312 + return 0; 313 + 314 + if (status & AM65_CPSW_PN_MAC_VERIFY_FAIL) { 315 + netdev_dbg(port->ndev, 316 + "MAC Merge verify failed, trying again\n"); 317 + continue; 318 + } 319 + 320 + if (status & AM65_CPSW_PN_MAC_RESPOND_ERR) { 321 + netdev_dbg(port->ndev, "MAC Merge respond error\n"); 322 + return -ENODEV; 323 + } 324 + 325 + if (status & AM65_CPSW_PN_MAC_VERIFY_ERR) { 326 + netdev_dbg(port->ndev, "MAC Merge verify error\n"); 327 + return -ENODEV; 328 + } 329 + } while (try-- > 0); 330 + 331 + netdev_dbg(port->ndev, "MAC Merge verify timeout\n"); 332 + return -ETIMEDOUT; 333 + } 334 + 335 + static void am65_cpsw_iet_set_preempt_mask(struct am65_cpsw_port *port, u8 preemptible_tcs) 336 + { 337 + u32 val; 338 + 339 + val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 340 + val &= ~AM65_CPSW_PN_IET_MAC_PREMPT_MASK; 341 + val |= AM65_CPSW_PN_IET_MAC_SET_PREEMPT(preemptible_tcs); 342 + writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 343 + } 344 + 345 + /* enable common IET_ENABLE only if at least 1 port has rx IET enabled. 346 + * UAPI doesn't allow tx enable without rx enable. 347 + */ 348 + void am65_cpsw_iet_common_enable(struct am65_cpsw_common *common) 349 + { 350 + struct am65_cpsw_port *port; 351 + bool rx_enable = false; 352 + u32 val; 353 + int i; 354 + 355 + for (i = 0; i < common->port_num; i++) { 356 + port = &common->ports[i]; 357 + val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); 358 + rx_enable = !!(val & AM65_CPSW_PN_CTL_IET_PORT_EN); 359 + if (rx_enable) 360 + break; 361 + } 362 + 363 + val = readl(common->cpsw_base + AM65_CPSW_REG_CTL); 364 + 365 + if (rx_enable) 366 + val |= AM65_CPSW_CTL_IET_EN; 367 + else 368 + val &= ~AM65_CPSW_CTL_IET_EN; 369 + 370 + writel(val, common->cpsw_base + AM65_CPSW_REG_CTL); 371 + common->iet_enabled = rx_enable; 372 + } 373 + 374 + /* CPSW does not have an IRQ to notify changes to the MAC Merge TX status 375 + * (active/inactive), but the preemptible traffic classes should only be 376 + * committed to hardware once TX is active. Resort to polling. 377 + */ 378 + void am65_cpsw_iet_commit_preemptible_tcs(struct am65_cpsw_port *port) 379 + { 380 + u8 preemptible_tcs; 381 + int err; 382 + u32 val; 383 + 384 + if (port->qos.link_speed == SPEED_UNKNOWN) 385 + return; 386 + 387 + val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); 388 + if (!(val & AM65_CPSW_PN_CTL_IET_PORT_EN)) 389 + return; 390 + 391 + /* update common IET enable */ 392 + am65_cpsw_iet_common_enable(port->common); 393 + 394 + /* update verify count */ 395 + err = am65_cpsw_iet_set_verify_timeout_count(port); 396 + if (err) { 397 + netdev_err(port->ndev, "couldn't set verify count: %d\n", err); 398 + return; 399 + } 400 + 401 + val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); 402 + if (!(val & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY)) { 403 + err = am65_cpsw_iet_verify_wait(port); 404 + if (err) 405 + return; 406 + } 407 + 408 + preemptible_tcs = port->qos.iet.preemptible_tcs; 409 + am65_cpsw_iet_set_preempt_mask(port, preemptible_tcs); 410 + } 411 + 412 + static void am65_cpsw_iet_change_preemptible_tcs(struct am65_cpsw_port *port, u8 preemptible_tcs) 413 + { 414 + struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(port->ndev); 415 + 416 + port->qos.iet.preemptible_tcs = preemptible_tcs; 417 + mutex_lock(&priv->mm_lock); 418 + am65_cpsw_iet_commit_preemptible_tcs(port); 419 + mutex_unlock(&priv->mm_lock); 420 + } 421 + 422 + static void am65_cpsw_iet_link_state_update(struct net_device *ndev) 423 + { 424 + struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev); 425 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 426 + 427 + mutex_lock(&priv->mm_lock); 428 + am65_cpsw_iet_commit_preemptible_tcs(port); 429 + mutex_unlock(&priv->mm_lock); 430 + } 61 431 62 432 static int am65_cpsw_port_est_enabled(struct am65_cpsw_port *port) 63 433 { ··· 804 428 am65_cpsw_timer_stop(ndev); 805 429 } 806 430 807 - static void am65_cpsw_purge_est(struct net_device *ndev) 431 + static void am65_cpsw_taprio_destroy(struct net_device *ndev) 808 432 { 809 433 struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 810 434 ··· 815 439 816 440 port->qos.est_oper = NULL; 817 441 port->qos.est_admin = NULL; 818 - } 819 442 820 - static int am65_cpsw_configure_taprio(struct net_device *ndev, 821 - struct am65_cpsw_est *est_new) 822 - { 823 - struct am65_cpsw_common *common = am65_ndev_to_common(ndev); 824 - struct am65_cpts *cpts = common->cpts; 825 - int ret = 0, tact = TACT_PROG; 826 - 827 - am65_cpsw_est_update_state(ndev); 828 - 829 - if (est_new->taprio.cmd == TAPRIO_CMD_DESTROY) { 830 - am65_cpsw_stop_est(ndev); 831 - return ret; 832 - } 833 - 834 - ret = am65_cpsw_est_check_scheds(ndev, est_new); 835 - if (ret < 0) 836 - return ret; 837 - 838 - tact = am65_cpsw_timer_act(ndev, est_new); 839 - if (tact == TACT_NEED_STOP) { 840 - dev_err(&ndev->dev, 841 - "Can't toggle estf timer, stop taprio first"); 842 - return -EINVAL; 843 - } 844 - 845 - if (tact == TACT_PROG) 846 - am65_cpsw_timer_stop(ndev); 847 - 848 - if (!est_new->taprio.base_time) 849 - est_new->taprio.base_time = am65_cpts_ns_gettime(cpts); 850 - 851 - am65_cpsw_port_est_get_buf_num(ndev, est_new); 852 - am65_cpsw_est_set_sched_list(ndev, est_new); 853 - am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf); 854 - 855 - am65_cpsw_est_set(ndev, est_new->taprio.cmd == TAPRIO_CMD_REPLACE); 856 - 857 - if (tact == TACT_PROG) { 858 - ret = am65_cpsw_timer_set(ndev, est_new); 859 - if (ret) { 860 - dev_err(&ndev->dev, "Failed to set cycle time"); 861 - return ret; 862 - } 863 - } 864 - 865 - return ret; 443 + am65_cpsw_reset_tc_mqprio(ndev); 866 444 } 867 445 868 446 static void am65_cpsw_cp_taprio(struct tc_taprio_qopt_offload *from, ··· 829 499 to->entries[i] = from->entries[i]; 830 500 } 831 501 832 - static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data) 502 + static int am65_cpsw_taprio_replace(struct net_device *ndev, 503 + struct tc_taprio_qopt_offload *taprio) 833 504 { 505 + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); 506 + struct netlink_ext_ack *extack = taprio->mqprio.extack; 834 507 struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 835 - struct tc_taprio_qopt_offload *taprio = type_data; 508 + struct am65_cpts *cpts = common->cpts; 836 509 struct am65_cpsw_est *est_new; 837 - int ret = 0; 510 + int ret, tact; 511 + 512 + if (!netif_running(ndev)) { 513 + NL_SET_ERR_MSG_MOD(extack, "interface is down, link speed unknown"); 514 + return -ENETDOWN; 515 + } 516 + 517 + if (common->pf_p0_rx_ptype_rrobin) { 518 + NL_SET_ERR_MSG_MOD(extack, 519 + "p0-rx-ptype-rrobin flag conflicts with taprio qdisc"); 520 + return -EINVAL; 521 + } 522 + 523 + if (port->qos.link_speed == SPEED_UNKNOWN) 524 + return -ENOLINK; 838 525 839 526 if (taprio->cycle_time_extension) { 840 - dev_err(&ndev->dev, "Failed to set cycle time extension"); 527 + NL_SET_ERR_MSG_MOD(extack, 528 + "cycle time extension not supported"); 841 529 return -EOPNOTSUPP; 842 530 } 843 531 ··· 865 517 if (!est_new) 866 518 return -ENOMEM; 867 519 868 - am65_cpsw_cp_taprio(taprio, &est_new->taprio); 869 - ret = am65_cpsw_configure_taprio(ndev, est_new); 870 - if (!ret) { 871 - if (taprio->cmd == TAPRIO_CMD_REPLACE) { 872 - devm_kfree(&ndev->dev, port->qos.est_admin); 520 + ret = am65_cpsw_setup_mqprio(ndev, &taprio->mqprio); 521 + if (ret) 522 + return ret; 873 523 874 - port->qos.est_admin = est_new; 875 - } else { 876 - devm_kfree(&ndev->dev, est_new); 877 - am65_cpsw_purge_est(ndev); 878 - } 879 - } else { 880 - devm_kfree(&ndev->dev, est_new); 524 + am65_cpsw_cp_taprio(taprio, &est_new->taprio); 525 + 526 + am65_cpsw_est_update_state(ndev); 527 + 528 + ret = am65_cpsw_est_check_scheds(ndev, est_new); 529 + if (ret < 0) 530 + goto fail; 531 + 532 + tact = am65_cpsw_timer_act(ndev, est_new); 533 + if (tact == TACT_NEED_STOP) { 534 + NL_SET_ERR_MSG_MOD(extack, 535 + "Can't toggle estf timer, stop taprio first"); 536 + ret = -EINVAL; 537 + goto fail; 881 538 } 882 539 540 + if (tact == TACT_PROG) 541 + am65_cpsw_timer_stop(ndev); 542 + 543 + if (!est_new->taprio.base_time) 544 + est_new->taprio.base_time = am65_cpts_ns_gettime(cpts); 545 + 546 + am65_cpsw_port_est_get_buf_num(ndev, est_new); 547 + am65_cpsw_est_set_sched_list(ndev, est_new); 548 + am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf); 549 + 550 + am65_cpsw_est_set(ndev, 1); 551 + 552 + if (tact == TACT_PROG) { 553 + ret = am65_cpsw_timer_set(ndev, est_new); 554 + if (ret) { 555 + NL_SET_ERR_MSG_MOD(extack, 556 + "Failed to set cycle time"); 557 + goto fail; 558 + } 559 + } 560 + 561 + devm_kfree(&ndev->dev, port->qos.est_admin); 562 + port->qos.est_admin = est_new; 563 + am65_cpsw_iet_change_preemptible_tcs(port, taprio->mqprio.preemptible_tcs); 564 + 565 + return 0; 566 + 567 + fail: 568 + am65_cpsw_reset_tc_mqprio(ndev); 569 + devm_kfree(&ndev->dev, est_new); 883 570 return ret; 884 571 } 885 572 ··· 924 541 ktime_t cur_time; 925 542 s64 delta; 926 543 927 - port->qos.link_speed = link_speed; 928 544 if (!am65_cpsw_port_est_enabled(port)) 929 545 return; 930 546 ··· 940 558 return; 941 559 942 560 purge_est: 943 - am65_cpsw_purge_est(ndev); 561 + am65_cpsw_taprio_destroy(ndev); 944 562 } 945 563 946 564 static int am65_cpsw_setup_taprio(struct net_device *ndev, void *type_data) 947 565 { 948 - struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 949 566 struct tc_taprio_qopt_offload *taprio = type_data; 950 - struct am65_cpsw_common *common = port->common; 567 + int err = 0; 951 568 952 - if (taprio->cmd != TAPRIO_CMD_REPLACE && 953 - taprio->cmd != TAPRIO_CMD_DESTROY) 954 - return -EOPNOTSUPP; 955 - 956 - if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) 957 - return -ENODEV; 958 - 959 - if (!netif_running(ndev)) { 960 - dev_err(&ndev->dev, "interface is down, link speed unknown\n"); 961 - return -ENETDOWN; 569 + switch (taprio->cmd) { 570 + case TAPRIO_CMD_REPLACE: 571 + err = am65_cpsw_taprio_replace(ndev, taprio); 572 + break; 573 + case TAPRIO_CMD_DESTROY: 574 + am65_cpsw_taprio_destroy(ndev); 575 + break; 576 + default: 577 + err = -EOPNOTSUPP; 962 578 } 963 579 964 - if (common->pf_p0_rx_ptype_rrobin) { 965 - dev_err(&ndev->dev, 966 - "p0-rx-ptype-rrobin flag conflicts with taprio qdisc\n"); 967 - return -EINVAL; 968 - } 969 - 970 - if (port->qos.link_speed == SPEED_UNKNOWN) 971 - return -ENOLINK; 972 - 973 - return am65_cpsw_set_taprio(ndev, type_data); 580 + return err; 974 581 } 975 582 976 583 static int am65_cpsw_tc_query_caps(struct net_device *ndev, void *type_data) ··· 967 596 struct tc_query_caps_base *base = type_data; 968 597 969 598 switch (base->type) { 599 + case TC_SETUP_QDISC_MQPRIO: { 600 + struct tc_mqprio_caps *caps = base->caps; 601 + 602 + caps->validate_queue_counts = true; 603 + 604 + return 0; 605 + } 606 + 970 607 case TC_SETUP_QDISC_TAPRIO: { 971 608 struct tc_taprio_caps *caps = base->caps; 972 - 973 - if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) 974 - return -EOPNOTSUPP; 975 609 976 610 caps->gate_mask_per_txq = true; 977 611 ··· 1163 787 port, port, true); 1164 788 } 1165 789 1166 - int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, 1167 - void *type_data) 1168 - { 1169 - switch (type) { 1170 - case TC_QUERY_CAPS: 1171 - return am65_cpsw_tc_query_caps(ndev, type_data); 1172 - case TC_SETUP_QDISC_TAPRIO: 1173 - return am65_cpsw_setup_taprio(ndev, type_data); 1174 - case TC_SETUP_BLOCK: 1175 - return am65_cpsw_qos_setup_tc_block(ndev, type_data); 1176 - default: 1177 - return -EOPNOTSUPP; 1178 - } 1179 - } 1180 - 1181 - void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed) 1182 - { 1183 - struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 1184 - 1185 - if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) 1186 - return; 1187 - 1188 - am65_cpsw_est_link_up(ndev, link_speed); 1189 - port->qos.link_down_time = 0; 1190 - } 1191 - 1192 - void am65_cpsw_qos_link_down(struct net_device *ndev) 1193 - { 1194 - struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 1195 - 1196 - if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) 1197 - return; 1198 - 1199 - if (!port->qos.link_down_time) 1200 - port->qos.link_down_time = ktime_get(); 1201 - 1202 - port->qos.link_speed = SPEED_UNKNOWN; 1203 - } 1204 - 1205 - static u32 1206 - am65_cpsw_qos_tx_rate_calc(u32 rate_mbps, unsigned long bus_freq) 1207 - { 1208 - u32 ir; 1209 - 1210 - bus_freq /= 1000000; 1211 - ir = DIV_ROUND_UP(((u64)rate_mbps * 32768), bus_freq); 1212 - return ir; 1213 - } 1214 - 1215 790 static void 1216 791 am65_cpsw_qos_tx_p0_rate_apply(struct am65_cpsw_common *common, 1217 792 int tx_ch, u32 rate_mbps) ··· 1263 936 writel(ch_cir, 1264 937 host->port_base + AM65_CPSW_PN_REG_PRI_CIR(tx_ch)); 1265 938 } 939 + } 940 + 941 + int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, 942 + void *type_data) 943 + { 944 + switch (type) { 945 + case TC_QUERY_CAPS: 946 + return am65_cpsw_tc_query_caps(ndev, type_data); 947 + case TC_SETUP_QDISC_TAPRIO: 948 + return am65_cpsw_setup_taprio(ndev, type_data); 949 + case TC_SETUP_QDISC_MQPRIO: 950 + return am65_cpsw_setup_mqprio(ndev, type_data); 951 + case TC_SETUP_BLOCK: 952 + return am65_cpsw_qos_setup_tc_block(ndev, type_data); 953 + default: 954 + return -EOPNOTSUPP; 955 + } 956 + } 957 + 958 + void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed) 959 + { 960 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 961 + 962 + port->qos.link_speed = link_speed; 963 + am65_cpsw_tx_pn_shaper_apply(port); 964 + am65_cpsw_iet_link_state_update(ndev); 965 + 966 + am65_cpsw_est_link_up(ndev, link_speed); 967 + port->qos.link_down_time = 0; 968 + } 969 + 970 + void am65_cpsw_qos_link_down(struct net_device *ndev) 971 + { 972 + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); 973 + 974 + port->qos.link_speed = SPEED_UNKNOWN; 975 + am65_cpsw_tx_pn_shaper_apply(port); 976 + am65_cpsw_iet_link_state_update(ndev); 977 + 978 + if (!port->qos.link_down_time) 979 + port->qos.link_down_time = ktime_get(); 1266 980 }
+186
drivers/net/ethernet/ti/am65-cpsw-qos.h
··· 9 9 #include <net/pkt_sched.h> 10 10 11 11 struct am65_cpsw_common; 12 + struct am65_cpsw_port; 12 13 13 14 struct am65_cpsw_est { 14 15 int buf; 15 16 /* has to be the last one */ 16 17 struct tc_taprio_qopt_offload taprio; 18 + }; 19 + 20 + struct am65_cpsw_mqprio { 21 + struct tc_mqprio_qopt_offload mqprio_hw; 22 + u64 max_rate_total; 23 + bool shaper_en; 24 + }; 25 + 26 + struct am65_cpsw_iet { 27 + u8 preemptible_tcs; 28 + u32 original_max_blks; 29 + int verify_time_ms; 17 30 }; 18 31 19 32 struct am65_cpsw_ale_ratelimit { ··· 39 26 struct am65_cpsw_est *est_oper; 40 27 ktime_t link_down_time; 41 28 int link_speed; 29 + struct am65_cpsw_mqprio mqprio; 30 + struct am65_cpsw_iet iet; 42 31 43 32 struct am65_cpsw_ale_ratelimit ale_bc_ratelimit; 44 33 struct am65_cpsw_ale_ratelimit ale_mc_ratelimit; 45 34 }; 46 35 36 + #define AM65_CPSW_REG_CTL 0x004 37 + #define AM65_CPSW_PN_REG_CTL 0x004 38 + #define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 39 + #define AM65_CPSW_PN_REG_EST_CTL 0x060 40 + #define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) 41 + #define AM65_CPSW_P0_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) 42 + 43 + #define AM65_CPSW_PN_REG_CTL 0x004 44 + #define AM65_CPSW_PN_REG_TX_PRI_MAP 0x018 45 + #define AM65_CPSW_PN_REG_RX_PRI_MAP 0x020 46 + #define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 47 + #define AM65_CPSW_PN_REG_EST_CTL 0x060 48 + #define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) 49 + #define AM65_CPSW_PN_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) 50 + 51 + /* AM65_CPSW_REG_CTL register fields */ 52 + #define AM65_CPSW_CTL_EST_EN BIT(18) 53 + 54 + /* AM65_CPSW_PN_REG_CTL register fields */ 55 + #define AM65_CPSW_PN_CTL_EST_PORT_EN BIT(17) 56 + 57 + /* AM65_CPSW_PN_REG_EST_CTL register fields */ 58 + #define AM65_CPSW_PN_EST_ONEBUF BIT(0) 59 + #define AM65_CPSW_PN_EST_BUFSEL BIT(1) 60 + #define AM65_CPSW_PN_EST_TS_EN BIT(2) 61 + #define AM65_CPSW_PN_EST_TS_FIRST BIT(3) 62 + #define AM65_CPSW_PN_EST_ONEPRI BIT(4) 63 + #define AM65_CPSW_PN_EST_TS_PRI_MSK GENMASK(7, 5) 64 + 65 + /* AM65_CPSW_PN_REG_FIFO_STATUS register fields */ 66 + #define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK GENMASK(7, 0) 67 + #define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK GENMASK(15, 8) 68 + #define AM65_CPSW_PN_FST_EST_CNT_ERR BIT(16) 69 + #define AM65_CPSW_PN_FST_EST_ADD_ERR BIT(17) 70 + #define AM65_CPSW_PN_FST_EST_BUFACT BIT(18) 71 + 72 + /* EST FETCH COMMAND RAM */ 73 + #define AM65_CPSW_FETCH_RAM_CMD_NUM 0x80 74 + #define AM65_CPSW_FETCH_CNT_MSK GENMASK(21, 8) 75 + #define AM65_CPSW_FETCH_CNT_MAX (AM65_CPSW_FETCH_CNT_MSK >> 8) 76 + #define AM65_CPSW_FETCH_CNT_OFFSET 8 77 + #define AM65_CPSW_FETCH_ALLOW_MSK GENMASK(7, 0) 78 + #define AM65_CPSW_FETCH_ALLOW_MAX AM65_CPSW_FETCH_ALLOW_MSK 79 + 80 + /* number of priority queues per port FIFO */ 81 + #define AM65_CPSW_PN_FIFO_PRIO_NUM 8 82 + 83 + #if IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS) 47 84 int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, 48 85 void *type_data); 49 86 void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed); 50 87 void am65_cpsw_qos_link_down(struct net_device *ndev); 51 88 int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, int queue, u32 rate_mbps); 52 89 void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common); 90 + void am65_cpsw_iet_commit_preemptible_tcs(struct am65_cpsw_port *port); 91 + void am65_cpsw_iet_common_enable(struct am65_cpsw_common *common); 92 + #else 93 + static inline int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, 94 + enum tc_setup_type type, 95 + void *type_data) 96 + { 97 + return -EOPNOTSUPP; 98 + } 99 + 100 + static inline void am65_cpsw_qos_link_up(struct net_device *ndev, 101 + int link_speed) 102 + { } 103 + 104 + static inline void am65_cpsw_qos_link_down(struct net_device *ndev) 105 + { } 106 + 107 + static inline int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, 108 + int queue, 109 + u32 rate_mbps) 110 + { 111 + return 0; 112 + } 113 + 114 + static inline void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common) 115 + { } 116 + static inline void am65_cpsw_iet_commit_preemptible_tcs(struct am65_cpsw_port *port) 117 + { } 118 + static inline void am65_cpsw_iet_common_enable(struct am65_cpsw_common *common) 119 + { } 120 + #endif 121 + 122 + #define AM65_CPSW_REG_CTL 0x004 123 + #define AM65_CPSW_PN_REG_CTL 0x004 124 + #define AM65_CPSW_PN_REG_MAX_BLKS 0x008 125 + #define AM65_CPSW_PN_REG_TX_PRI_MAP 0x018 126 + #define AM65_CPSW_PN_REG_RX_PRI_MAP 0x020 127 + #define AM65_CPSW_PN_REG_IET_CTRL 0x040 128 + #define AM65_CPSW_PN_REG_IET_STATUS 0x044 129 + #define AM65_CPSW_PN_REG_IET_VERIFY 0x048 130 + #define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 131 + #define AM65_CPSW_PN_REG_EST_CTL 0x060 132 + #define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) 133 + #define AM65_CPSW_PN_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) 134 + 135 + /* AM65_CPSW_REG_CTL register fields */ 136 + #define AM65_CPSW_CTL_IET_EN BIT(17) 137 + #define AM65_CPSW_CTL_EST_EN BIT(18) 138 + 139 + /* AM65_CPSW_PN_REG_CTL register fields */ 140 + #define AM65_CPSW_PN_CTL_IET_PORT_EN BIT(16) 141 + #define AM65_CPSW_PN_CTL_EST_PORT_EN BIT(17) 142 + 143 + /* AM65_CPSW_PN_REG_EST_CTL register fields */ 144 + #define AM65_CPSW_PN_EST_ONEBUF BIT(0) 145 + #define AM65_CPSW_PN_EST_BUFSEL BIT(1) 146 + #define AM65_CPSW_PN_EST_TS_EN BIT(2) 147 + #define AM65_CPSW_PN_EST_TS_FIRST BIT(3) 148 + #define AM65_CPSW_PN_EST_ONEPRI BIT(4) 149 + #define AM65_CPSW_PN_EST_TS_PRI_MSK GENMASK(7, 5) 150 + 151 + /* AM65_CPSW_PN_REG_IET_CTRL register fields */ 152 + #define AM65_CPSW_PN_IET_MAC_PENABLE BIT(0) 153 + #define AM65_CPSW_PN_IET_MAC_DISABLEVERIFY BIT(2) 154 + #define AM65_CPSW_PN_IET_MAC_LINKFAIL BIT(3) 155 + #define AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK GENMASK(10, 8) 156 + #define AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET 8 157 + #define AM65_CPSW_PN_IET_MAC_PREMPT_MASK GENMASK(23, 16) 158 + #define AM65_CPSW_PN_IET_MAC_PREMPT_OFFSET 16 159 + 160 + #define AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(n) (((n) << AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET) & \ 161 + AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK) 162 + #define AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(n) (((n) & AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK) >> \ 163 + AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET) 164 + #define AM65_CPSW_PN_IET_MAC_SET_PREEMPT(n) (((n) << AM65_CPSW_PN_IET_MAC_PREMPT_OFFSET) & \ 165 + AM65_CPSW_PN_IET_MAC_PREMPT_MASK) 166 + #define AM65_CPSW_PN_IET_MAC_GET_PREEMPT(n) (((n) & AM65_CPSW_PN_IET_MAC_PREMPT_MASK) >> \ 167 + AM65_CPSW_PN_IET_MAC_PREMPT_OFFSET) 168 + 169 + /* AM65_CPSW_PN_REG_IET_STATUS register fields */ 170 + #define AM65_CPSW_PN_MAC_STATUS GENMASK(3, 0) 171 + #define AM65_CPSW_PN_MAC_VERIFIED BIT(0) 172 + #define AM65_CPSW_PN_MAC_VERIFY_FAIL BIT(1) 173 + #define AM65_CPSW_PN_MAC_RESPOND_ERR BIT(2) 174 + #define AM65_CPSW_PN_MAC_VERIFY_ERR BIT(3) 175 + 176 + /* AM65_CPSW_PN_REG_IET_VERIFY register fields */ 177 + #define AM65_CPSW_PN_MAC_VERIFY_CNT_MASK GENMASK(23, 0) 178 + #define AM65_CPSW_PN_MAC_GET_VERIFY_CNT(n) ((n) & AM65_CPSW_PN_MAC_VERIFY_CNT_MASK) 179 + /* 10 msec converted to NSEC */ 180 + #define AM65_CPSW_IET_VERIFY_CNT_MS (10) 181 + #define AM65_CPSW_IET_VERIFY_CNT_NS (AM65_CPSW_IET_VERIFY_CNT_MS * \ 182 + NSEC_PER_MSEC) 183 + 184 + /* AM65_CPSW_PN_REG_FIFO_STATUS register fields */ 185 + #define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK GENMASK(7, 0) 186 + #define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK GENMASK(15, 8) 187 + #define AM65_CPSW_PN_FST_EST_CNT_ERR BIT(16) 188 + #define AM65_CPSW_PN_FST_EST_ADD_ERR BIT(17) 189 + #define AM65_CPSW_PN_FST_EST_BUFACT BIT(18) 190 + 191 + /* EST FETCH COMMAND RAM */ 192 + #define AM65_CPSW_FETCH_RAM_CMD_NUM 0x80 193 + #define AM65_CPSW_FETCH_CNT_MSK GENMASK(21, 8) 194 + #define AM65_CPSW_FETCH_CNT_MAX (AM65_CPSW_FETCH_CNT_MSK >> 8) 195 + #define AM65_CPSW_FETCH_CNT_OFFSET 8 196 + #define AM65_CPSW_FETCH_ALLOW_MSK GENMASK(7, 0) 197 + #define AM65_CPSW_FETCH_ALLOW_MAX AM65_CPSW_FETCH_ALLOW_MSK 198 + 199 + /* AM65_CPSW_PN_REG_MAX_BLKS fields for IET and No IET cases */ 200 + /* 7 blocks for pn_rx_max_blks, 13 for pn_tx_max_blks*/ 201 + #define AM65_CPSW_PN_TX_RX_MAX_BLKS_IET 0xD07 202 + 203 + /* Slave IET Stats. register offsets */ 204 + #define AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR 0x140 205 + #define AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK 0x144 206 + #define AM65_CPSW_STATN_IET_RX_SMD_ERROR 0x148 207 + #define AM65_CPSW_STATN_IET_RX_FRAG 0x14c 208 + #define AM65_CPSW_STATN_IET_TX_HOLD 0x150 209 + #define AM65_CPSW_STATN_IET_TX_FRAG 0x154 210 + 211 + /* number of priority queues per port FIFO */ 212 + #define AM65_CPSW_PN_FIFO_PRIO_NUM 8 53 213 54 214 #endif /* AM65_CPSW_QOS_H_ */
+46 -2
tools/testing/selftests/net/forwarding/ethtool_mm.sh
··· 25 25 local after= 26 26 local delta= 27 27 28 + if [ ${has_pmac_stats[$if]} = false ]; then 29 + src="aggregate" 30 + fi 31 + 28 32 before=$(ethtool_std_stats_get $if "eth-mac" "FramesTransmittedOK" $src) 29 33 30 34 $MZ $if -q -c $num_pkts -p 64 -b bcast -t ip -R $PREEMPTIBLE_PRIO ··· 159 155 manual_failed_verification $h2 $h1 160 156 } 161 157 158 + smallest_supported_add_frag_size() 159 + { 160 + local iface=$1 161 + local rx_min_frag_size= 162 + 163 + rx_min_frag_size=$(ethtool --json --show-mm $iface | \ 164 + jq '.[]."rx-min-frag-size"') 165 + 166 + if [ $rx_min_frag_size -le 60 ]; then 167 + echo 0 168 + elif [ $rx_min_frag_size -le 124 ]; then 169 + echo 1 170 + elif [ $rx_min_frag_size -le 188 ]; then 171 + echo 2 172 + elif [ $rx_min_frag_size -le 252 ]; then 173 + echo 3 174 + else 175 + echo "$iface: RX min frag size $rx_min_frag_size cannot be advertised over LLDP" 176 + exit 1 177 + fi 178 + } 179 + 180 + expected_add_frag_size() 181 + { 182 + local iface=$1 183 + local requested=$2 184 + local min=$(smallest_supported_add_frag_size $iface) 185 + 186 + [ $requested -le $min ] && echo $min || echo $requested 187 + } 188 + 162 189 lldp_change_add_frag_size() 163 190 { 164 191 local add_frag_size=$1 192 + local pattern= 165 193 166 194 lldptool -T -i $h1 -V addEthCaps addFragSize=$add_frag_size >/dev/null 167 195 # Wait for TLVs to be received 168 196 sleep 2 169 - lldptool -i $h2 -t -n -V addEthCaps | \ 170 - grep -q "Additional fragment size: $add_frag_size" 197 + pattern=$(printf "Additional fragment size: %d" \ 198 + $(expected_add_frag_size $h1 $add_frag_size)) 199 + lldptool -i $h2 -t -n -V addEthCaps | grep -q "$pattern" 171 200 } 172 201 173 202 lldp() ··· 320 283 if [[ $? -ne 0 ]]; then 321 284 echo "SKIP: $netif does not support MAC Merge" 322 285 exit $ksft_skip 286 + fi 287 + 288 + if check_ethtool_pmac_std_stats_support $netif eth-mac; then 289 + has_pmac_stats[$netif]=true 290 + else 291 + has_pmac_stats[$netif]=false 292 + echo "$netif does not report pMAC statistics, falling back to aggregate" 323 293 fi 324 294 done 325 295
+9
tools/testing/selftests/net/forwarding/lib.sh
··· 155 155 fi 156 156 } 157 157 158 + check_ethtool_pmac_std_stats_support() 159 + { 160 + local dev=$1; shift 161 + local grp=$1; shift 162 + 163 + [ 0 -ne $(ethtool --json -S $dev --all-groups --src pmac 2>/dev/null \ 164 + | jq ".[].\"$grp\" | length") ] 165 + } 166 + 158 167 check_locked_port_support() 159 168 { 160 169 if ! bridge -d link show | grep -q " locked"; then