aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-queues8
-rw-r--r--Documentation/networking/scaling.txt9
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c29
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c33
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c6
-rw-r--r--include/linux/mlx4/device.h17
-rw-r--r--include/linux/mlx4/qp.h14
-rw-r--r--include/linux/netdevice.h8
-rw-r--r--net/core/net-sysfs.c67
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
27What: /sys/class/<iface>/queues/tx-<queue>/tx_maxrate
28Date: March 2015
29KernelVersion: 4.1
30Contact: netdev@vger.kernel.org
31Description:
32 A Mbps max-rate set for the queue, a value of zero means disabled,
33 default is disabled.
34
27What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus 35What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus
28Date: November 2010 36Date: November 2010
29KernelVersion: 2.6.38 37KernelVersion: 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
421with the CPU that processes transmit completions for that queue 421with the CPU that processes transmit completions for that queue
422(transmit interrupts). 422(transmit interrupts).
423 423
424Per TX Queue rate limitation:
425=============================
426
427These are rate-limitation mechanisms implemented by HW, where currently
428a max-rate attribute is supported, by setting a Mbps value to
429
430/sys/class/net/<dev>/queues/tx-<n>/tx_maxrate
431
432A value of zero means disabled, and this is the default.
424 433
425Further Information 434Further 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
2382int 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 &params);
2406 return err;
2407}
2408
2382static const struct net_device_ops mlx4_netdev_ops = { 2409static 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
2415static const struct net_device_ops mlx4_netdev_ops_master = { 2443static 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
2449struct mlx4_en_bond { 2478struct 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
210enum { 211enum {
@@ -450,6 +451,21 @@ enum mlx4_module_id {
450 MLX4_MODULE_ID_QSFP28 = 0x11, 451 MLX4_MODULE_ID_QSFP28 = 0x11,
451}; 452};
452 453
454enum { /* 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
461struct 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
453static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) 469static 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
570struct mlx4_buf_list { 587struct 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
220struct mlx4_update_qp_context { 222struct mlx4_update_qp_context {
@@ -229,6 +231,7 @@ struct mlx4_update_qp_context {
229enum { 231enum {
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
234enum { 237enum {
@@ -428,7 +431,8 @@ struct mlx4_wqe_inline_seg {
428enum mlx4_update_qp_attr { 431enum 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
434enum mlx4_update_qp_params_flags { 438enum mlx4_update_qp_params_flags {
@@ -438,6 +442,8 @@ enum mlx4_update_qp_params_flags {
438struct mlx4_update_qp_params { 442struct 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
443int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, 449int 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
592static inline int netdev_queue_numa_node_read(const struct netdev_queue *q) 593static 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 */
1026struct net_device_ops { 1031struct 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
955static 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
969static 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
976static 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
1003static 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
954static struct netdev_queue_attribute queue_trans_timeout = 1008static 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
1068static 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
1080static ssize_t show_xps_map(struct netdev_queue *queue, 1122static 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};