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

Merge branch 'mvneta-next'

Maxime Chevallier says:

====================
net: mvneta: mqprio cleanups and shaping support

This is the second version of the series that adds some improvements to the
existing mqprio implementation in mvneta, and adds support for
egress shaping offload.

The first 3 patches are some minor cleanups, such as using the
tc_mqprio_qopt_offload structure to get access to more offloading
options, cleaning the logic to detect whether or not we should offload
mqprio setting, and allowing to have a 1 to N mapping between TCs and
queues.

The last patch adds traffic shaping offload, using mvneta's per-queue
token buckets, allowing to limit rates from 10Kbps up to 5Gbps with
10Kbps increments.

This was tested only on an Armada 3720, with traffic up to 2.5Gbps.

Changes since V1 fixes the build for 32bits kernels, using the right
div helpers as suggested by Jakub.
====================

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

+144 -16
+144 -16
drivers/net/ethernet/marvell/mvneta.c
··· 38 38 #include <net/ipv6.h> 39 39 #include <net/tso.h> 40 40 #include <net/page_pool.h> 41 + #include <net/pkt_cls.h> 41 42 #include <linux/bpf_trace.h> 42 43 43 44 /* Registers */ ··· 248 247 #define MVNETA_TXQ_SENT_DESC_MASK 0x3fff0000 249 248 #define MVNETA_PORT_TX_RESET 0x3cf0 250 249 #define MVNETA_PORT_TX_DMA_RESET BIT(0) 250 + #define MVNETA_TXQ_CMD1_REG 0x3e00 251 + #define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3) 252 + #define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0) 253 + #define MVNETA_REFILL_NUM_CLK_REG 0x3e08 254 + #define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff 251 255 #define MVNETA_TX_MTU 0x3e0c 252 256 #define MVNETA_TX_TOKEN_SIZE 0x3e14 253 257 #define MVNETA_TX_TOKEN_SIZE_MAX 0xffffffff 258 + #define MVNETA_TXQ_BUCKET_REFILL_REG(q) (0x3e20 + ((q) << 2)) 259 + #define MVNETA_TXQ_BUCKET_REFILL_PERIOD_MASK 0x3ff00000 260 + #define MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT 20 261 + #define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff 254 262 #define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2)) 255 263 #define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff 264 + 265 + /* The values of the bucket refill base period and refill period are taken from 266 + * the reference manual, and adds up to a base resolution of 10Kbps. This allows 267 + * to cover all rate-limit values from 10Kbps up to 5Gbps 268 + */ 269 + 270 + /* Base period for the rate limit algorithm */ 271 + #define MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS 100 272 + 273 + /* Number of Base Period to wait between each bucket refill */ 274 + #define MVNETA_TXQ_BUCKET_REFILL_PERIOD 1000 275 + 276 + /* The base resolution for rate limiting, in bps. Any max_rate value should be 277 + * a multiple of that value. 278 + */ 279 + #define MVNETA_TXQ_RATE_LIMIT_RESOLUTION (NSEC_PER_SEC / \ 280 + (MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS * \ 281 + MVNETA_TXQ_BUCKET_REFILL_PERIOD)) 256 282 257 283 #define MVNETA_LPI_CTRL_0 0x2cc0 258 284 #define MVNETA_LPI_CTRL_1 0x2cc4 ··· 520 492 u8 mcast_count[256]; 521 493 u16 tx_ring_size; 522 494 u16 rx_ring_size; 523 - u8 prio_tc_map[8]; 524 495 525 496 phy_interface_t phy_interface; 526 497 struct device_node *dn; ··· 4923 4896 mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, 0); 4924 4897 } 4925 4898 4926 - static void mvneta_setup_rx_prio_map(struct mvneta_port *pp) 4899 + static void mvneta_map_vlan_prio_to_rxq(struct mvneta_port *pp, u8 pri, u8 rxq) 4927 4900 { 4928 - u32 val = 0; 4929 - int i; 4901 + u32 val = mvreg_read(pp, MVNETA_VLAN_PRIO_TO_RXQ); 4930 4902 4931 - for (i = 0; i < rxq_number; i++) 4932 - val |= MVNETA_VLAN_PRIO_RXQ_MAP(i, pp->prio_tc_map[i]); 4903 + val &= ~MVNETA_VLAN_PRIO_RXQ_MAP(pri, 0x7); 4904 + val |= MVNETA_VLAN_PRIO_RXQ_MAP(pri, rxq); 4933 4905 4934 4906 mvreg_write(pp, MVNETA_VLAN_PRIO_TO_RXQ, val); 4935 4907 } 4936 4908 4909 + static int mvneta_enable_per_queue_rate_limit(struct mvneta_port *pp) 4910 + { 4911 + unsigned long core_clk_rate; 4912 + u32 refill_cycles; 4913 + u32 val; 4914 + 4915 + core_clk_rate = clk_get_rate(pp->clk); 4916 + if (!core_clk_rate) 4917 + return -EINVAL; 4918 + 4919 + refill_cycles = MVNETA_TXQ_BUCKET_REFILL_BASE_PERIOD_NS / 4920 + (NSEC_PER_SEC / core_clk_rate); 4921 + 4922 + if (refill_cycles > MVNETA_REFILL_MAX_NUM_CLK) 4923 + return -EINVAL; 4924 + 4925 + /* Enable bw limit algorithm version 3 */ 4926 + val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); 4927 + val &= ~(MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); 4928 + mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); 4929 + 4930 + /* Set the base refill rate */ 4931 + mvreg_write(pp, MVNETA_REFILL_NUM_CLK_REG, refill_cycles); 4932 + 4933 + return 0; 4934 + } 4935 + 4936 + static void mvneta_disable_per_queue_rate_limit(struct mvneta_port *pp) 4937 + { 4938 + u32 val = mvreg_read(pp, MVNETA_TXQ_CMD1_REG); 4939 + 4940 + val |= (MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 | MVNETA_TXQ_CMD1_BW_LIM_EN); 4941 + mvreg_write(pp, MVNETA_TXQ_CMD1_REG, val); 4942 + } 4943 + 4944 + static int mvneta_setup_queue_rates(struct mvneta_port *pp, int queue, 4945 + u64 min_rate, u64 max_rate) 4946 + { 4947 + u32 refill_val, rem; 4948 + u32 val = 0; 4949 + 4950 + /* Convert to from Bps to bps */ 4951 + max_rate *= 8; 4952 + 4953 + if (min_rate) 4954 + return -EINVAL; 4955 + 4956 + refill_val = div_u64_rem(max_rate, MVNETA_TXQ_RATE_LIMIT_RESOLUTION, 4957 + &rem); 4958 + 4959 + if (rem || !refill_val || 4960 + refill_val > MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX) 4961 + return -EINVAL; 4962 + 4963 + val = refill_val; 4964 + val |= (MVNETA_TXQ_BUCKET_REFILL_PERIOD << 4965 + MVNETA_TXQ_BUCKET_REFILL_PERIOD_SHIFT); 4966 + 4967 + mvreg_write(pp, MVNETA_TXQ_BUCKET_REFILL_REG(queue), val); 4968 + 4969 + return 0; 4970 + } 4971 + 4937 4972 static int mvneta_setup_mqprio(struct net_device *dev, 4938 - struct tc_mqprio_qopt *qopt) 4973 + struct tc_mqprio_qopt_offload *mqprio) 4939 4974 { 4940 4975 struct mvneta_port *pp = netdev_priv(dev); 4976 + int rxq, txq, tc, ret; 4941 4977 u8 num_tc; 4942 - int i; 4943 4978 4944 - qopt->hw = TC_MQPRIO_HW_OFFLOAD_TCS; 4945 - num_tc = qopt->num_tc; 4979 + if (mqprio->qopt.hw != TC_MQPRIO_HW_OFFLOAD_TCS) 4980 + return 0; 4981 + 4982 + num_tc = mqprio->qopt.num_tc; 4946 4983 4947 4984 if (num_tc > rxq_number) 4948 4985 return -EINVAL; 4949 4986 4987 + mvneta_clear_rx_prio_map(pp); 4988 + 4950 4989 if (!num_tc) { 4951 - mvneta_clear_rx_prio_map(pp); 4990 + mvneta_disable_per_queue_rate_limit(pp); 4952 4991 netdev_reset_tc(dev); 4953 4992 return 0; 4954 4993 } 4955 4994 4956 - memcpy(pp->prio_tc_map, qopt->prio_tc_map, sizeof(pp->prio_tc_map)); 4995 + netdev_set_num_tc(dev, mqprio->qopt.num_tc); 4957 4996 4958 - mvneta_setup_rx_prio_map(pp); 4997 + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { 4998 + netdev_set_tc_queue(dev, tc, mqprio->qopt.count[tc], 4999 + mqprio->qopt.offset[tc]); 4959 5000 4960 - netdev_set_num_tc(dev, qopt->num_tc); 4961 - for (i = 0; i < qopt->num_tc; i++) 4962 - netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); 5001 + for (rxq = mqprio->qopt.offset[tc]; 5002 + rxq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; 5003 + rxq++) { 5004 + if (rxq >= rxq_number) 5005 + return -EINVAL; 5006 + 5007 + mvneta_map_vlan_prio_to_rxq(pp, tc, rxq); 5008 + } 5009 + } 5010 + 5011 + if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) { 5012 + mvneta_disable_per_queue_rate_limit(pp); 5013 + return 0; 5014 + } 5015 + 5016 + if (mqprio->qopt.num_tc > txq_number) 5017 + return -EINVAL; 5018 + 5019 + ret = mvneta_enable_per_queue_rate_limit(pp); 5020 + if (ret) 5021 + return ret; 5022 + 5023 + for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { 5024 + for (txq = mqprio->qopt.offset[tc]; 5025 + txq < mqprio->qopt.count[tc] + mqprio->qopt.offset[tc]; 5026 + txq++) { 5027 + if (txq >= txq_number) 5028 + return -EINVAL; 5029 + 5030 + ret = mvneta_setup_queue_rates(pp, txq, 5031 + mqprio->min_rate[tc], 5032 + mqprio->max_rate[tc]); 5033 + if (ret) 5034 + return ret; 5035 + } 5036 + } 4963 5037 4964 5038 return 0; 4965 5039 }