aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatan Barak <matanb@mellanox.com>2014-12-11 03:57:57 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-11 14:47:35 -0500
commitd57febe1a47801ef8a55dbf10672850523dfaa60 (patch)
treed5a9cfb4c5c57c147e8ce61f5738337b03ea458a
parent7a89399ffad7b7c47b43afda010309b3b88538c0 (diff)
net/mlx4: Add A0 hybrid steering
A0 hybrid steering is a form of high performance flow steering. By using this mode, mlx4 cards use a fast limited table based steering, in order to enable fast steering of unicast packets to a QP. In order to implement A0 hybrid steering we allocate resources from different zones: (1) General range (2) Special MAC-assigned QPs [RSS, Raw-Ethernet] each has its own region. When we create a rss QP or a raw ethernet (A0 steerable and BF ready) QP, we try hard to allocate the QP from range (2). Otherwise, we try hard not to allocate from this range. However, when the system is pushed to its limits and one needs every resource, the allocator uses every region it can. Meaning, when we run out of raw-eth qps, the allocator allocates from the general range (and the special-A0 area is no longer active). If we run out of RSS qps, the mechanism tries to allocate from the raw-eth QP zone. If that is also exhausted, the allocator will allocate from the general range (and the A0 region is no longer active). Note that if a raw-eth qp is allocated from the general range, it attempts to allocate the range such that bits 6 and 7 (blueflame bits) in the QP number are not set. When the feature is used in SRIOV, the VF has to notify the PF what kind of QP attributes it needs. In order to do that, along with the "Eth QP blueflame" bit, we reserve a new "A0 steerable QP". According to the combination of these bits, the PF tries to allocate a suitable QP. In order to maintain backward compatibility (with older PFs), the PF notifies which QP attributes it supports via QUERY_FUNC_CAP command. Signed-off-by: Matan Barak <matanb@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_rx.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h13
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/qp.c277
-rw-r--r--include/linux/mlx4/device.h10
8 files changed, 300 insertions, 25 deletions
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 506d1bdad227..cf000b7ad64f 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -807,8 +807,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
807 * VLAN insertion. */ 807 * VLAN insertion. */
808 if (init_attr->qp_type == IB_QPT_RAW_PACKET) 808 if (init_attr->qp_type == IB_QPT_RAW_PACKET)
809 err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn, 809 err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn,
810 init_attr->cap.max_send_wr ? 810 (init_attr->cap.max_send_wr ?
811 MLX4_RESERVE_ETH_BF_QP : 0); 811 MLX4_RESERVE_ETH_BF_QP : 0) |
812 (init_attr->cap.max_recv_wr ?
813 MLX4_RESERVE_A0_QP : 0));
812 else 814 else
813 if (qp->flags & MLX4_IB_QP_NETIF) 815 if (qp->flags & MLX4_IB_QP_NETIF)
814 err = mlx4_ib_steer_qp_alloc(dev, 1, &qpn); 816 err = mlx4_ib_steer_qp_alloc(dev, 1, &qpn);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index c67effb05b2f..568e1f41fdd4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -595,7 +595,7 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
595 return 0; 595 return 0;
596 } 596 }
597 597
598 err = mlx4_qp_reserve_range(dev, 1, 1, qpn, 0); 598 err = mlx4_qp_reserve_range(dev, 1, 1, qpn, MLX4_RESERVE_A0_QP);
599 en_dbg(DRV, priv, "Reserved qp %d\n", *qpn); 599 en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
600 if (err) { 600 if (err) {
601 en_err(priv, "Failed to reserve qp for mac registration\n"); 601 en_err(priv, "Failed to reserve qp for mac registration\n");
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index a850f24fabdf..a0474eb94aa3 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -1131,7 +1131,8 @@ int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv)
1131 int err; 1131 int err;
1132 u32 qpn; 1132 u32 qpn;
1133 1133
1134 err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn, 0); 1134 err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn,
1135 MLX4_RESERVE_A0_QP);
1135 if (err) { 1136 if (err) {
1136 en_err(priv, "Failed reserving drop qpn\n"); 1137 en_err(priv, "Failed reserving drop qpn\n");
1137 return err; 1138 return err;
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 1469b5b5be64..622bffaa9d78 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -275,6 +275,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
275#define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX 0x04 275#define QUERY_FUNC_CAP_FLAG_VALID_MAILBOX 0x04
276 276
277#define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG (1UL << 31) 277#define QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG (1UL << 31)
278#define QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG (1UL << 30)
278 279
279/* when opcode modifier = 1 */ 280/* when opcode modifier = 1 */
280#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 281#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3
@@ -406,7 +407,8 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
406 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); 407 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
407 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP); 408 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
408 409
409 size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG; 410 size = QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG |
411 QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG;
410 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); 412 MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET);
411 } else 413 } else
412 err = -EINVAL; 414 err = -EINVAL;
@@ -509,6 +511,8 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u8 gen_or_port,
509 MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET); 511 MLX4_GET(size, outbox, QUERY_FUNC_CAP_EXTRA_FLAGS_OFFSET);
510 if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG) 512 if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_BF_QP_ALLOC_FLAG)
511 func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP; 513 func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_BF_RES_QP;
514 if (size & QUERY_FUNC_CAP_EXTRA_FLAGS_A0_QP_ALLOC_FLAG)
515 func_cap->extra_flags |= MLX4_QUERY_FUNC_FLAGS_A0_RES_QP;
512 } 516 }
513 517
514 goto out; 518 goto out;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 6a9a941ddf58..3bfe90b95f96 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -436,6 +436,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
436 (1 << dev->caps.log_num_vlans) * 436 (1 << dev->caps.log_num_vlans) *
437 dev->caps.num_ports; 437 dev->caps.num_ports;
438 dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH; 438 dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH] = MLX4_NUM_FEXCH;
439 dev->caps.reserved_qps_cnt[MLX4_QP_REGION_RSS_RAW_ETH] =
440 MLX4_A0_STEERING_TABLE_SIZE;
439 441
440 dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] + 442 dev->caps.reserved_qps = dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] +
441 dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] + 443 dev->caps.reserved_qps_cnt[MLX4_QP_REGION_ETH_ADDR] +
@@ -469,7 +471,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
469 if (!mlx4_is_slave(dev)) { 471 if (!mlx4_is_slave(dev)) {
470 mlx4_enable_cqe_eqe_stride(dev); 472 mlx4_enable_cqe_eqe_stride(dev);
471 dev->caps.alloc_res_qp_mask = 473 dev->caps.alloc_res_qp_mask =
472 (dev->caps.bf_reg_size ? MLX4_RESERVE_ETH_BF_QP : 0); 474 (dev->caps.bf_reg_size ? MLX4_RESERVE_ETH_BF_QP : 0) |
475 MLX4_RESERVE_A0_QP;
473 } else { 476 } else {
474 dev->caps.alloc_res_qp_mask = 0; 477 dev->caps.alloc_res_qp_mask = 0;
475 } 478 }
@@ -826,6 +829,9 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
826 dev->caps.bf_reg_size) 829 dev->caps.bf_reg_size)
827 dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_ETH_BF_QP; 830 dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_ETH_BF_QP;
828 831
832 if (func_cap.extra_flags & MLX4_QUERY_FUNC_FLAGS_A0_RES_QP)
833 dev->caps.alloc_res_qp_mask |= MLX4_RESERVE_A0_QP;
834
829 return 0; 835 return 0;
830 836
831err_mem: 837err_mem:
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
index bc1505efa436..cebd1180702b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
@@ -682,8 +682,19 @@ struct mlx4_srq_table {
682 struct mlx4_icm_table cmpt_table; 682 struct mlx4_icm_table cmpt_table;
683}; 683};
684 684
685enum mlx4_qp_table_zones {
686 MLX4_QP_TABLE_ZONE_GENERAL,
687 MLX4_QP_TABLE_ZONE_RSS,
688 MLX4_QP_TABLE_ZONE_RAW_ETH,
689 MLX4_QP_TABLE_ZONE_NUM
690};
691
692#define MLX4_A0_STEERING_TABLE_SIZE 256
693
685struct mlx4_qp_table { 694struct mlx4_qp_table {
686 struct mlx4_bitmap bitmap; 695 struct mlx4_bitmap *bitmap_gen;
696 struct mlx4_zone_allocator *zones;
697 u32 zones_uids[MLX4_QP_TABLE_ZONE_NUM];
687 u32 rdmarc_base; 698 u32 rdmarc_base;
688 int rdmarc_shift; 699 int rdmarc_shift;
689 spinlock_t lock; 700 spinlock_t lock;
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c
index 8720428c9807..d8d040c366f4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -213,6 +213,7 @@ EXPORT_SYMBOL_GPL(mlx4_qp_modify);
213int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, 213int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
214 int *base, u8 flags) 214 int *base, u8 flags)
215{ 215{
216 u32 uid;
216 int bf_qp = !!(flags & (u8)MLX4_RESERVE_ETH_BF_QP); 217 int bf_qp = !!(flags & (u8)MLX4_RESERVE_ETH_BF_QP);
217 218
218 struct mlx4_priv *priv = mlx4_priv(dev); 219 struct mlx4_priv *priv = mlx4_priv(dev);
@@ -221,8 +222,16 @@ int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
221 if (cnt > MLX4_MAX_BF_QP_RANGE && bf_qp) 222 if (cnt > MLX4_MAX_BF_QP_RANGE && bf_qp)
222 return -ENOMEM; 223 return -ENOMEM;
223 224
224 *base = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align, 225 uid = MLX4_QP_TABLE_ZONE_GENERAL;
225 bf_qp ? MLX4_BF_QP_SKIP_MASK : 0); 226 if (flags & (u8)MLX4_RESERVE_A0_QP) {
227 if (bf_qp)
228 uid = MLX4_QP_TABLE_ZONE_RAW_ETH;
229 else
230 uid = MLX4_QP_TABLE_ZONE_RSS;
231 }
232
233 *base = mlx4_zone_alloc_entries(qp_table->zones, uid, cnt, align,
234 bf_qp ? MLX4_BF_QP_SKIP_MASK