diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-net-queues | 8 | ||||
-rw-r--r-- | Documentation/networking/scaling.txt | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/qp.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 6 | ||||
-rw-r--r-- | include/linux/mlx4/device.h | 17 | ||||
-rw-r--r-- | include/linux/mlx4/qp.h | 14 | ||||
-rw-r--r-- | include/linux/netdevice.h | 8 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 67 |
12 files changed, 181 insertions, 18 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-queues b/Documentation/ABI/testing/sysfs-class-net-queues index 5e9aeb91d355..0c0df91b1516 100644 --- a/Documentation/ABI/testing/sysfs-class-net-queues +++ b/Documentation/ABI/testing/sysfs-class-net-queues | |||
@@ -24,6 +24,14 @@ Description: | |||
24 | Indicates the number of transmit timeout events seen by this | 24 | Indicates the number of transmit timeout events seen by this |
25 | network interface transmit queue. | 25 | network interface transmit queue. |
26 | 26 | ||
27 | What: /sys/class/<iface>/queues/tx-<queue>/tx_maxrate | ||
28 | Date: March 2015 | ||
29 | KernelVersion: 4.1 | ||
30 | Contact: netdev@vger.kernel.org | ||
31 | Description: | ||
32 | A Mbps max-rate set for the queue, a value of zero means disabled, | ||
33 | default is disabled. | ||
34 | |||
27 | What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus | 35 | What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus |
28 | Date: November 2010 | 36 | Date: November 2010 |
29 | KernelVersion: 2.6.38 | 37 | KernelVersion: 2.6.38 |
diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt index 99ca40e8e810..cbfac0949635 100644 --- a/Documentation/networking/scaling.txt +++ b/Documentation/networking/scaling.txt | |||
@@ -421,6 +421,15 @@ best CPUs to share a given queue are probably those that share the cache | |||
421 | with the CPU that processes transmit completions for that queue | 421 | with the CPU that processes transmit completions for that queue |
422 | (transmit interrupts). | 422 | (transmit interrupts). |
423 | 423 | ||
424 | Per TX Queue rate limitation: | ||
425 | ============================= | ||
426 | |||
427 | These are rate-limitation mechanisms implemented by HW, where currently | ||
428 | a max-rate attribute is supported, by setting a Mbps value to | ||
429 | |||
430 | /sys/class/net/<dev>/queues/tx-<n>/tx_maxrate | ||
431 | |||
432 | A value of zero means disabled, and this is the default. | ||
424 | 433 | ||
425 | Further Information | 434 | Further Information |
426 | =================== | 435 | =================== |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index c59ed925adaf..d8dc3f985c2b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -2379,6 +2379,33 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb, | |||
2379 | } | 2379 | } |
2380 | #endif | 2380 | #endif |
2381 | 2381 | ||
2382 | int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate) | ||
2383 | { | ||
2384 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
2385 | struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[queue_index]; | ||
2386 | struct mlx4_update_qp_params params; | ||
2387 | int err; | ||
2388 | |||
2389 | if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT)) | ||
2390 | return -EOPNOTSUPP; | ||
2391 | |||
2392 | /* rate provided to us in Mbs, check if it fits into 12 bits, if not use Gbs */ | ||
2393 | if (maxrate >> 12) { | ||
2394 | params.rate_unit = MLX4_QP_RATE_LIMIT_GBS; | ||
2395 | params.rate_val = maxrate / 1000; | ||
2396 | } else if (maxrate) { | ||
2397 | params.rate_unit = MLX4_QP_RATE_LIMIT_MBS; | ||
2398 | params.rate_val = maxrate; | ||
2399 | } else { /* zero serves to revoke the QP rate-limitation */ | ||
2400 | params.rate_unit = 0; | ||
2401 | params.rate_val = 0; | ||
2402 | } | ||
2403 | |||
2404 | err = mlx4_update_qp(priv->mdev->dev, tx_ring->qpn, MLX4_UPDATE_QP_RATE_LIMIT, | ||
2405 | ¶ms); | ||
2406 | return err; | ||
2407 | } | ||
2408 | |||
2382 | static const struct net_device_ops mlx4_netdev_ops = { | 2409 | static const struct net_device_ops mlx4_netdev_ops = { |
2383 | .ndo_open = mlx4_en_open, | 2410 | .ndo_open = mlx4_en_open, |
2384 | .ndo_stop = mlx4_en_close, | 2411 | .ndo_stop = mlx4_en_close, |
@@ -2410,6 +2437,7 @@ static const struct net_device_ops mlx4_netdev_ops = { | |||
2410 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, | 2437 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, |
2411 | .ndo_features_check = mlx4_en_features_check, | 2438 | .ndo_features_check = mlx4_en_features_check, |
2412 | #endif | 2439 | #endif |
2440 | .ndo_set_tx_maxrate = mlx4_en_set_tx_maxrate, | ||
2413 | }; | 2441 | }; |
2414 | 2442 | ||
2415 | static const struct net_device_ops mlx4_netdev_ops_master = { | 2443 | static const struct net_device_ops mlx4_netdev_ops_master = { |
@@ -2444,6 +2472,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = { | |||
2444 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, | 2472 | .ndo_del_vxlan_port = mlx4_en_del_vxlan_port, |
2445 | .ndo_features_check = mlx4_en_features_check, | 2473 | .ndo_features_check = mlx4_en_features_check, |
2446 | #endif | 2474 | #endif |
2475 | .ndo_set_tx_maxrate = mlx4_en_set_tx_maxrate, | ||
2447 | }; | 2476 | }; |
2448 | 2477 | ||
2449 | struct mlx4_en_bond { | 2478 | struct mlx4_en_bond { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 242bcee5d774..4a471f5d1b56 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -144,7 +144,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) | |||
144 | [19] = "Performance optimized for limited rule configuration flow steering support", | 144 | [19] = "Performance optimized for limited rule configuration flow steering support", |
145 | [20] = "Recoverable error events support", | 145 | [20] = "Recoverable error events support", |
146 | [21] = "Port Remap support", | 146 | [21] = "Port Remap support", |
147 | [22] = "QCN support" | 147 | [22] = "QCN support", |
148 | [23] = "QP rate limiting support" | ||
148 | }; | 149 | }; |
149 | int i; | 150 | int i; |
150 | 151 | ||
@@ -697,6 +698,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
697 | #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 | 698 | #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 |
698 | #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 | 699 | #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 |
699 | #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac | 700 | #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac |
701 | #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET 0xcc | ||
702 | #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET 0xd0 | ||
703 | #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET 0xd2 | ||
704 | |||
700 | 705 | ||
701 | dev_cap->flags2 = 0; | 706 | dev_cap->flags2 = 0; |
702 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 707 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
@@ -904,6 +909,18 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
904 | QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET); | 909 | QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET); |
905 | dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK; | 910 | dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK; |
906 | 911 | ||
912 | MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET); | ||
913 | dev_cap->rl_caps.num_rates = size; | ||
914 | if (dev_cap->rl_caps.num_rates) { | ||
915 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT; | ||
916 | MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET); | ||
917 | dev_cap->rl_caps.max_val = size & 0xfff; | ||
918 | dev_cap->rl_caps.max_unit = size >> 14; | ||
919 | MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET); | ||
920 | dev_cap->rl_caps.min_val = size & 0xfff; | ||
921 | dev_cap->rl_caps.min_unit = size >> 14; | ||
922 | } | ||
923 | |||
907 | MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); | 924 | MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); |
908 | if (field32 & (1 << 16)) | 925 | if (field32 & (1 << 16)) |
909 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; | 926 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; |
@@ -979,6 +996,15 @@ void mlx4_dev_cap_dump(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
979 | dev_cap->dmfs_high_rate_qpn_base); | 996 | dev_cap->dmfs_high_rate_qpn_base); |
980 | mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n", | 997 | mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n", |
981 | dev_cap->dmfs_high_rate_qpn_range); | 998 | dev_cap->dmfs_high_rate_qpn_range); |
999 | |||
1000 | if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT) { | ||
1001 | struct mlx4_rate_limit_caps *rl_caps = &dev_cap->rl_caps; | ||
1002 | |||
1003 | mlx4_dbg(dev, "QP Rate-Limit: #rates %d, unit/val max %d/%d, min %d/%d\n", | ||
1004 | rl_caps->num_rates, rl_caps->max_unit, rl_caps->max_val, | ||
1005 | rl_caps->min_unit, rl_caps->min_val); | ||
1006 | } | ||
1007 | |||
982 | dump_dev_cap_flags(dev, dev_cap->flags); | 1008 | dump_dev_cap_flags(dev, dev_cap->flags); |
983 | dump_dev_cap_flags2(dev, dev_cap->flags2); | 1009 | dump_dev_cap_flags2(dev, dev_cap->flags2); |
984 | } | 1010 | } |
@@ -1075,6 +1101,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
1075 | u64 flags; | 1101 | u64 flags; |
1076 | int err = 0; | 1102 | int err = 0; |
1077 | u8 field; | 1103 | u8 field; |
1104 | u16 field16; | ||
1078 | u32 bmme_flags, field32; | 1105 | u32 bmme_flags, field32; |
1079 | int real_port; | 1106 | int real_port; |
1080 | int slave_port; | 1107 | int slave_port; |
@@ -1158,6 +1185,10 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
1158 | field &= 0xfe; | 1185 | field &= 0xfe; |
1159 | MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET); | 1186 | MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET); |
1160 | 1187 | ||
1188 | /* turn off QP max-rate limiting for guests */ | ||
1189 | field16 = 0; | ||
1190 | MLX4_PUT(outbox->buf, field16, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET); | ||
1191 | |||
1161 | return 0; | 1192 | return 0; |
1162 | } | 1193 | } |
1163 | 1194 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index f44f7f6017ed..863655bd3947 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h | |||
@@ -127,6 +127,7 @@ struct mlx4_dev_cap { | |||
127 | u32 max_counters; | 127 | u32 max_counters; |
128 | u32 dmfs_high_rate_qpn_base; | 128 | u32 dmfs_high_rate_qpn_base; |
129 | u32 dmfs_high_rate_qpn_range; | 129 | u32 dmfs_high_rate_qpn_range; |
130 | struct mlx4_rate_limit_caps rl_caps; | ||
130 | struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1]; | 131 | struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1]; |
131 | }; | 132 | }; |
132 | 133 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 7e487223489a..43aa76775b5f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -489,6 +489,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
489 | dev->caps.dmfs_high_rate_qpn_range = MLX4_A0_STEERING_TABLE_SIZE; | 489 | dev->caps.dmfs_high_rate_qpn_range = MLX4_A0_STEERING_TABLE_SIZE; |
490 | } | 490 | } |
491 | 491 | ||
492 | dev->caps.rl_caps = dev_cap->rl_caps; | ||
493 | |||
492 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_RSS_RAW_ETH] = | 494 | dev->caps.reserved_qps_cnt[MLX4_QP_REGION_RSS_RAW_ETH] = |
493 | dev->caps.dmfs_high_rate_qpn_range; | 495 | dev->caps.dmfs_high_rate_qpn_range; |
494 | 496 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index eda29dbbfcd2..69e4462e4ee4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c | |||
@@ -442,6 +442,11 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, | |||
442 | cmd->qp_context.param3 |= cpu_to_be32(MLX4_STRIP_VLAN); | 442 | cmd->qp_context.param3 |= cpu_to_be32(MLX4_STRIP_VLAN); |
443 | } | 443 | } |
444 | 444 | ||
445 | if (attr & MLX4_UPDATE_QP_RATE_LIMIT) { | ||
446 | qp_mask |= 1ULL << MLX4_UPD_QP_MASK_RATE_LIMIT; | ||
447 | cmd->qp_context.rate_limit_params = cpu_to_be16((params->rate_unit << 14) | params->rate_val); | ||
448 | } | ||
449 | |||
445 | cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask); | 450 | cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask); |
446 | cmd->qp_mask = cpu_to_be64(qp_mask); | 451 | cmd->qp_mask = cpu_to_be64(qp_mask); |
447 | 452 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index d43e25914d19..c258f8625aac 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -2947,8 +2947,12 @@ static int verify_qp_parameters(struct mlx4_dev *dev, | |||
2947 | qp_type = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff; | 2947 | qp_type = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff; |
2948 | optpar = be32_to_cpu(*(__be32 *) inbox->buf); | 2948 | optpar = be32_to_cpu(*(__be32 *) inbox->buf); |
2949 | 2949 | ||
2950 | if (slave != mlx4_master_func_num(dev)) | 2950 | if (slave != mlx4_master_func_num(dev)) { |
2951 | qp_ctx->params2 &= ~MLX4_QP_BIT_FPP; | 2951 | qp_ctx->params2 &= ~MLX4_QP_BIT_FPP; |
2952 | /* setting QP rate-limit is disallowed for VFs */ | ||
2953 | if (qp_ctx->rate_limit_params) | ||
2954 | return -EPERM; | ||
2955 | } | ||
2952 | 2956 | ||
2953 | switch (qp_type) { | 2957 | switch (qp_type) { |
2954 | case MLX4_QP_ST_RC: | 2958 | case MLX4_QP_ST_RC: |
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 1cc54822b931..4550c67b92e4 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h | |||
@@ -205,6 +205,7 @@ enum { | |||
205 | MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT = 1LL << 20, | 205 | MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT = 1LL << 20, |
206 | MLX4_DEV_CAP_FLAG2_PORT_REMAP = 1LL << 21, | 206 | MLX4_DEV_CAP_FLAG2_PORT_REMAP = 1LL << 21, |
207 | MLX4_DEV_CAP_FLAG2_QCN = 1LL << 22, | 207 | MLX4_DEV_CAP_FLAG2_QCN = 1LL << 22, |
208 | MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT = 1LL << 23 | ||
208 | }; | 209 | }; |
209 | 210 | ||
210 | enum { | 211 | enum { |
@@ -450,6 +451,21 @@ enum mlx4_module_id { | |||
450 | MLX4_MODULE_ID_QSFP28 = 0x11, | 451 | MLX4_MODULE_ID_QSFP28 = 0x11, |
451 | }; | 452 | }; |
452 | 453 | ||
454 | enum { /* rl */ | ||
455 | MLX4_QP_RATE_LIMIT_NONE = 0, | ||
456 | MLX4_QP_RATE_LIMIT_KBS = 1, | ||
457 | MLX4_QP_RATE_LIMIT_MBS = 2, | ||
458 | MLX4_QP_RATE_LIMIT_GBS = 3 | ||
459 | }; | ||
460 | |||
461 | struct mlx4_rate_limit_caps { | ||
462 | u16 num_rates; /* Number of different rates */ | ||
463 | u8 min_unit; | ||
464 | u16 min_val; | ||
465 | u8 max_unit; | ||
466 | u16 max_val; | ||
467 | }; | ||
468 | |||
453 | static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) | 469 | static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) |
454 | { | 470 | { |
455 | return (major << 32) | (minor << 16) | subminor; | 471 | return (major << 32) | (minor << 16) | subminor; |
@@ -565,6 +581,7 @@ struct mlx4_caps { | |||
565 | u32 dmfs_high_rate_qpn_base; | 581 | u32 dmfs_high_rate_qpn_base; |
566 | u32 dmfs_high_rate_qpn_range; | 582 | u32 dmfs_high_rate_qpn_range; |
567 | u32 vf_caps; | 583 | u32 vf_caps; |
584 | struct mlx4_rate_limit_caps rl_caps; | ||
568 | }; | 585 | }; |
569 | 586 | ||
570 | struct mlx4_buf_list { | 587 | struct mlx4_buf_list { |
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 551f85456c11..1023ebe035b7 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h | |||
@@ -207,14 +207,16 @@ struct mlx4_qp_context { | |||
207 | __be32 msn; | 207 | __be32 msn; |
208 | __be16 rq_wqe_counter; | 208 | __be16 rq_wqe_counter; |
209 | __be16 sq_wqe_counter; | 209 | __be16 sq_wqe_counter; |
210 | u32 reserved3[2]; | 210 | u32 reserved3; |
211 | __be16 rate_limit_params; | ||
212 | __be16 reserved4; | ||
211 | __be32 param3; | 213 | __be32 param3; |
212 | __be32 nummmcpeers_basemkey; | 214 | __be32 nummmcpeers_basemkey; |
213 | u8 log_page_size; | 215 | u8 log_page_size; |
214 | u8 reserved4[2]; | 216 | u8 reserved5[2]; |
215 | u8 mtt_base_addr_h; | 217 | u8 mtt_base_addr_h; |
216 | __be32 mtt_base_addr_l; | 218 | __be32 mtt_base_addr_l; |
217 | u32 reserved5[10]; | 219 | u32 reserved6[10]; |
218 | }; | 220 | }; |
219 | 221 | ||
220 | struct mlx4_update_qp_context { | 222 | struct mlx4_update_qp_context { |
@@ -229,6 +231,7 @@ struct mlx4_update_qp_context { | |||
229 | enum { | 231 | enum { |
230 | MLX4_UPD_QP_MASK_PM_STATE = 32, | 232 | MLX4_UPD_QP_MASK_PM_STATE = 32, |
231 | MLX4_UPD_QP_MASK_VSD = 33, | 233 | MLX4_UPD_QP_MASK_VSD = 33, |
234 | MLX4_UPD_QP_MASK_RATE_LIMIT = 35, | ||
232 | }; | 235 | }; |
233 | 236 | ||
234 | enum { | 237 | enum { |
@@ -428,7 +431,8 @@ struct mlx4_wqe_inline_seg { | |||
428 | enum mlx4_update_qp_attr { | 431 | enum mlx4_update_qp_attr { |
429 | MLX4_UPDATE_QP_SMAC = 1 << 0, | 432 | MLX4_UPDATE_QP_SMAC = 1 << 0, |
430 | MLX4_UPDATE_QP_VSD = 1 << 1, | 433 | MLX4_UPDATE_QP_VSD = 1 << 1, |
431 | MLX4_UPDATE_QP_SUPPORTED_ATTRS = (1 << 2) - 1 | 434 | MLX4_UPDATE_QP_RATE_LIMIT = 1 << 2, |
435 | MLX4_UPDATE_QP_SUPPORTED_ATTRS = (1 << 3) - 1 | ||
432 | }; | 436 | }; |
433 | 437 | ||
434 | enum mlx4_update_qp_params_flags { | 438 | enum mlx4_update_qp_params_flags { |
@@ -438,6 +442,8 @@ enum mlx4_update_qp_params_flags { | |||
438 | struct mlx4_update_qp_params { | 442 | struct mlx4_update_qp_params { |
439 | u8 smac_index; | 443 | u8 smac_index; |
440 | u32 flags; | 444 | u32 flags; |
445 | u16 rate_unit; | ||
446 | u16 rate_val; | ||
441 | }; | 447 | }; |
442 | 448 | ||
443 | int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, | 449 | int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index dd1d069758be..76c5de4978a8 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -587,6 +587,7 @@ struct netdev_queue { | |||
587 | #ifdef CONFIG_BQL | 587 | #ifdef CONFIG_BQL |
588 | struct dql dql; | 588 | struct dql dql; |
589 | #endif | 589 | #endif |
590 | unsigned long tx_maxrate; | ||
590 | } ____cacheline_aligned_in_smp; | 591 | } ____cacheline_aligned_in_smp; |
591 | 592 | ||
592 | static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) | 593 | static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) |
@@ -1022,6 +1023,10 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev, | |||
1022 | * be otherwise expressed by feature flags. The check is called with | 1023 | * be otherwise expressed by feature flags. The check is called with |
1023 | * the set of features that the stack has calculated and it returns | 1024 | * the set of features that the stack has calculated and it returns |
1024 | * those the driver believes to be appropriate. | 1025 | * those the driver believes to be appropriate. |
1026 | * int (*ndo_set_tx_maxrate)(struct net_device *dev, | ||
1027 | * int queue_index, u32 maxrate); | ||
1028 | * Called when a user wants to set a max-rate limitation of specific | ||
1029 | * TX queue. | ||
1025 | */ | 1030 | */ |
1026 | struct net_device_ops { | 1031 | struct net_device_ops { |
1027 | int (*ndo_init)(struct net_device *dev); | 1032 | int (*ndo_init)(struct net_device *dev); |
@@ -1178,6 +1183,9 @@ struct net_device_ops { | |||
1178 | netdev_features_t (*ndo_features_check) (struct sk_buff *skb, | 1183 | netdev_features_t (*ndo_features_check) (struct sk_buff *skb, |
1179 | struct net_device *dev, | 1184 | struct net_device *dev, |
1180 | netdev_features_t features); | 1185 | netdev_features_t features); |
1186 | int (*ndo_set_tx_maxrate)(struct net_device *dev, | ||
1187 | int queue_index, | ||
1188 | u32 maxrate); | ||
1181 | }; | 1189 | }; |
1182 | 1190 | ||
1183 | /** | 1191 | /** |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index cf30620a88e1..7e58bd7ec232 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -951,6 +951,60 @@ static ssize_t show_trans_timeout(struct netdev_queue *queue, | |||
951 | return sprintf(buf, "%lu", trans_timeout); | 951 | return sprintf(buf, "%lu", trans_timeout); |
952 | } | 952 | } |
953 | 953 | ||
954 | #ifdef CONFIG_XPS | ||
955 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) | ||
956 | { | ||
957 | struct net_device *dev = queue->dev; | ||
958 | int i; | ||
959 | |||
960 | for (i = 0; i < dev->num_tx_queues; i++) | ||
961 | if (queue == &dev->_tx[i]) | ||
962 | break; | ||
963 | |||
964 | BUG_ON(i >= dev->num_tx_queues); | ||
965 | |||
966 | return i; | ||
967 | } | ||
968 | |||
969 | static ssize_t show_tx_maxrate(struct netdev_queue *queue, | ||
970 | struct netdev_queue_attribute *attribute, | ||
971 | char *buf) | ||
972 | { | ||
973 | return sprintf(buf, "%lu\n", queue->tx_maxrate); | ||
974 | } | ||
975 | |||
976 | static ssize_t set_tx_maxrate(struct netdev_queue *queue, | ||
977 | struct netdev_queue_attribute *attribute, | ||
978 | const char *buf, size_t len) | ||
979 | { | ||
980 | struct net_device *dev = queue->dev; | ||
981 | int err, index = get_netdev_queue_index(queue); | ||
982 | u32 rate = 0; | ||
983 | |||
984 | err = kstrtou32(buf, 10, &rate); | ||
985 | if (err < 0) | ||
986 | return err; | ||
987 | |||
988 | if (!rtnl_trylock()) | ||
989 | return restart_syscall(); | ||
990 | |||
991 | err = -EOPNOTSUPP; | ||
992 | if (dev->netdev_ops->ndo_set_tx_maxrate) | ||
993 | err = dev->netdev_ops->ndo_set_tx_maxrate(dev, index, rate); | ||
994 | |||
995 | rtnl_unlock(); | ||
996 | if (!err) { | ||
997 | queue->tx_maxrate = rate; | ||
998 | return len; | ||
999 | } | ||
1000 | return err; | ||
1001 | } | ||
1002 | |||
1003 | static struct netdev_queue_attribute queue_tx_maxrate = | ||
1004 | __ATTR(tx_maxrate, S_IRUGO | S_IWUSR, | ||
1005 | show_tx_maxrate, set_tx_maxrate); | ||
1006 | #endif | ||
1007 | |||
954 | static struct netdev_queue_attribute queue_trans_timeout = | 1008 | static struct netdev_queue_attribute queue_trans_timeout = |
955 | __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); | 1009 | __ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL); |
956 | 1010 | ||
@@ -1065,18 +1119,6 @@ static struct attribute_group dql_group = { | |||
1065 | #endif /* CONFIG_BQL */ | 1119 | #endif /* CONFIG_BQL */ |
1066 | 1120 | ||
1067 | #ifdef CONFIG_XPS | 1121 | #ifdef CONFIG_XPS |
1068 | static unsigned int get_netdev_queue_index(struct netdev_queue *queue) | ||
1069 | { | ||
1070 | struct net_device *dev = queue->dev; | ||
1071 | unsigned int i; | ||
1072 | |||
1073 | i = queue - dev->_tx; | ||
1074 | BUG_ON(i >= dev->num_tx_queues); | ||
1075 | |||
1076 | return i; | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | static ssize_t show_xps_map(struct netdev_queue *queue, | 1122 | static ssize_t show_xps_map(struct netdev_queue *queue, |
1081 | struct netdev_queue_attribute *attribute, char *buf) | 1123 | struct netdev_queue_attribute *attribute, char *buf) |
1082 | { | 1124 | { |
@@ -1153,6 +1195,7 @@ static struct attribute *netdev_queue_default_attrs[] = { | |||
1153 | &queue_trans_timeout.attr, | 1195 | &queue_trans_timeout.attr, |
1154 | #ifdef CONFIG_XPS | 1196 | #ifdef CONFIG_XPS |
1155 | &xps_cpus_attribute.attr, | 1197 | &xps_cpus_attribute.attr, |
1198 | &queue_tx_maxrate.attr, | ||
1156 | #endif | 1199 | #endif |
1157 | NULL | 1200 | NULL |
1158 | }; | 1201 | }; |