aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaeed Mahameed <saeedm@mellanox.com>2016-07-19 11:03:21 -0400
committerLeon Romanovsky <leon@kernel.org>2016-08-17 10:45:58 -0400
commit1a412fb1caa2c1b77719ccb5ed8b0c3c2bc65da7 (patch)
tree3932dca111e30df6cebae0a31679cddff00ce06e
parent09a7d9eca1a6cf5eb4f9abfdf8914db9dbd96f08 (diff)
{net,IB}/mlx5: Modify QP commands via mlx5 ifc
Prior to this patch we assumed that modify QP commands have the same layout. In ConnectX-4 for each QP transition there is a specific command and their layout can vary. e.g: 2err/2rst commands don't have QP context in their layout and before this patch we posted the QP context in those commands. Fortunately the FW only checks the suffix of the commands and executes them, while ignoring all invalid data sent after the valid command layout. This patch removes mlx5_modify_qp_mbox_in and changes mlx5_core_qp_modify to receive the required transition and QP context with opt_param_mask if needed. This way the caller is not required to provide the command inbox layout and it will be generated automatically. mlx5_core_qp_modify will generate the command inbox/outbox layouts according to the requested transition and will fill the requested parameters. Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org>
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/qp.c124
-rw-r--r--include/linux/mlx5/qp.h20
3 files changed, 124 insertions, 42 deletions
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index d22492ff863e..626173736749 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -1871,7 +1871,6 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
1871{ 1871{
1872 struct mlx5_ib_cq *send_cq, *recv_cq; 1872 struct mlx5_ib_cq *send_cq, *recv_cq;
1873 struct mlx5_ib_qp_base *base = &qp->trans_qp.base; 1873 struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
1874 struct mlx5_modify_qp_mbox_in *in;
1875 unsigned long flags; 1874 unsigned long flags;
1876 int err; 1875 int err;
1877 1876
@@ -1884,16 +1883,12 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
1884 &qp->raw_packet_qp.rq.base : 1883 &qp->raw_packet_qp.rq.base :
1885 &qp->trans_qp.base; 1884 &qp->trans_qp.base;
1886 1885
1887 in = kzalloc(sizeof(*in), GFP_KERNEL);
1888 if (!in)
1889 return;
1890
1891 if (qp->state != IB_QPS_RESET) { 1886 if (qp->state != IB_QPS_RESET) {
1892 if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET) { 1887 if (qp->ibqp.qp_type != IB_QPT_RAW_PACKET) {
1893 mlx5_ib_qp_disable_pagefaults(qp); 1888 mlx5_ib_qp_disable_pagefaults(qp);
1894 err = mlx5_core_qp_modify(dev->mdev, 1889 err = mlx5_core_qp_modify(dev->mdev,
1895 MLX5_CMD_OP_2RST_QP, in, 0, 1890 MLX5_CMD_OP_2RST_QP, 0,
1896 &base->mqp); 1891 NULL, &base->mqp);
1897 } else { 1892 } else {
1898 err = modify_raw_packet_qp(dev, qp, 1893 err = modify_raw_packet_qp(dev, qp,
1899 MLX5_CMD_OP_2RST_QP); 1894 MLX5_CMD_OP_2RST_QP);
@@ -1935,8 +1930,6 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
1935 base->mqp.qpn); 1930 base->mqp.qpn);
1936 } 1931 }
1937 1932
1938 kfree(in);
1939
1940 if (qp->create_type == MLX5_QP_KERNEL) 1933 if (qp->create_type == MLX5_QP_KERNEL)
1941 destroy_qp_kernel(dev, qp); 1934 destroy_qp_kernel(dev, qp);
1942 else if (qp->create_type == MLX5_QP_USER) 1935 else if (qp->create_type == MLX5_QP_USER)
@@ -2522,7 +2515,6 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
2522 struct mlx5_ib_qp_base *base = &qp->trans_qp.base; 2515 struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
2523 struct mlx5_ib_cq *send_cq, *recv_cq; 2516 struct mlx5_ib_cq *send_cq, *recv_cq;
2524 struct mlx5_qp_context *context; 2517 struct mlx5_qp_context *context;
2525 struct mlx5_modify_qp_mbox_in *in;
2526 struct mlx5_ib_pd *pd; 2518 struct mlx5_ib_pd *pd;
2527 enum mlx5_qp_state mlx5_cur, mlx5_new; 2519 enum mlx5_qp_state mlx5_cur, mlx5_new;
2528 enum mlx5_qp_optpar optpar; 2520 enum mlx5_qp_optpar optpar;
@@ -2531,11 +2523,10 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
2531 int err; 2523 int err;
2532 u16 op; 2524 u16 op;
2533 2525
2534 in = kzalloc(sizeof(*in), GFP_KERNEL); 2526 context = kzalloc(sizeof(*context), GFP_KERNEL);
2535 if (!in) 2527 if (!context)
2536 return -ENOMEM; 2528 return -ENOMEM;
2537 2529
2538 context = &in->ctx;
2539 err = to_mlx5_st(ibqp->qp_type); 2530 err = to_mlx5_st(ibqp->qp_type);
2540 if (err < 0) { 2531 if (err < 0) {
2541 mlx5_ib_dbg(dev, "unsupported qp type %d\n", ibqp->qp_type); 2532 mlx5_ib_dbg(dev, "unsupported qp type %d\n", ibqp->qp_type);
@@ -2700,12 +2691,11 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
2700 op = optab[mlx5_cur][mlx5_new]; 2691 op = optab[mlx5_cur][mlx5_new];
2701 optpar = ib_mask_to_mlx5_opt(attr_mask); 2692 optpar = ib_mask_to_mlx5_opt(attr_mask);
2702 optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st]; 2693 optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st];
2703 in->optparam = cpu_to_be32(optpar);
2704 2694
2705 if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) 2695 if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET)
2706 err = modify_raw_packet_qp(dev, qp, op); 2696 err = modify_raw_packet_qp(dev, qp, op);
2707 else 2697 else
2708 err = mlx5_core_qp_modify(dev->mdev, op, in, sqd_event, 2698 err = mlx5_core_qp_modify(dev->mdev, op, optpar, context,
2709 &base->mqp); 2699 &base->mqp);
2710 if (err) 2700 if (err)
2711 goto out; 2701 goto out;
@@ -2746,7 +2736,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
2746 } 2736 }
2747 2737
2748out: 2738out:
2749 kfree(in); 2739 kfree(context);
2750 return err; 2740 return err;
2751} 2741}
2752 2742
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
index 36d240c9d15f..50875a4e9d58 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
@@ -335,21 +335,127 @@ int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
335} 335}
336EXPORT_SYMBOL_GPL(mlx5_core_destroy_qp); 336EXPORT_SYMBOL_GPL(mlx5_core_destroy_qp);
337 337
338int mlx5_core_qp_modify(struct mlx5_core_dev *dev, u16 operation, 338struct mbox_info {
339 struct mlx5_modify_qp_mbox_in *in, int sqd_event, 339 u32 *in;
340 u32 *out;
341 int inlen;
342 int outlen;
343};
344
345static int mbox_alloc(struct mbox_info *mbox, int inlen, int outlen)
346{
347 mbox->inlen = inlen;
348 mbox->outlen = outlen;
349 mbox->in = kzalloc(mbox->inlen, GFP_KERNEL);
350 mbox->out = kzalloc(mbox->outlen, GFP_KERNEL);
351 if (!mbox->in || !mbox->out) {
352 kfree(mbox->in);
353 kfree(mbox->out);
354 return -ENOMEM;
355 }
356
357 return 0;
358}
359
360static void mbox_free(struct mbox_info *mbox)
361{
362 kfree(mbox->in);
363 kfree(mbox->out);
364}
365
366static int modify_qp_mbox_alloc(struct mlx5_core_dev *dev, u16 opcode, int qpn,
367 u32 opt_param_mask, void *qpc,
368 struct mbox_info *mbox)
369{
370 mbox->out = NULL;
371 mbox->in = NULL;
372
373#define MBOX_ALLOC(mbox, typ) \
374 mbox_alloc(mbox, MLX5_ST_SZ_BYTES(typ##_in), MLX5_ST_SZ_BYTES(typ##_out))
375
376#define MOD_QP_IN_SET(typ, in, _opcode, _qpn) \
377 MLX5_SET(typ##_in, in, opcode, _opcode); \
378 MLX5_SET(typ##_in, in, qpn, _qpn)
379
380#define MOD_QP_IN_SET_QPC(typ, in, _opcode, _qpn, _opt_p, _qpc) \
381 MOD_QP_IN_SET(typ, in, _opcode, _qpn); \
382 MLX5_SET(typ##_in, in, opt_param_mask, _opt_p); \
383 memcpy(MLX5_ADDR_OF(typ##_in, in, qpc), _qpc, MLX5_ST_SZ_BYTES(qpc))
384
385 switch (opcode) {
386 /* 2RST & 2ERR */
387 case MLX5_CMD_OP_2RST_QP:
388 if (MBOX_ALLOC(mbox, qp_2rst))
389 return -ENOMEM;
390 MOD_QP_IN_SET(qp_2rst, mbox->in, opcode, qpn);
391 break;
392 case MLX5_CMD_OP_2ERR_QP:
393 if (MBOX_ALLOC(mbox, qp_2err))
394 return -ENOMEM;
395 MOD_QP_IN_SET(qp_2err, mbox->in, opcode, qpn);
396 break;
397
398 /* MODIFY with QPC */
399 case MLX5_CMD_OP_RST2INIT_QP:
400 if (MBOX_ALLOC(mbox, rst2init_qp))
401 return -ENOMEM;
402 MOD_QP_IN_SET_QPC(rst2init_qp, mbox->in, opcode, qpn,
403 opt_param_mask, qpc);
404 break;
405 case MLX5_CMD_OP_INIT2RTR_QP:
406 if (MBOX_ALLOC(mbox, init2rtr_qp))
407 return -ENOMEM;
408 MOD_QP_IN_SET_QPC(init2rtr_qp, mbox->in, opcode, qpn,
409 opt_param_mask, qpc);
410 break;
411 case MLX5_CMD_OP_RTR2RTS_QP:
412 if (MBOX_ALLOC(mbox, rtr2rts_qp))
413 return -ENOMEM;
414 MOD_QP_IN_SET_QPC(rtr2rts_qp, mbox->in, opcode, qpn,
415 opt_param_mask, qpc);
416 break;
417 case MLX5_CMD_OP_RTS2RTS_QP:
418 if (MBOX_ALLOC(mbox, rts2rts_qp))
419 return -ENOMEM;
420 MOD_QP_IN_SET_QPC(rts2rts_qp, mbox->in, opcode, qpn,
421 opt_param_mask, qpc);
422 break;
423 case MLX5_CMD_OP_SQERR2RTS_QP:
424 if (MBOX_ALLOC(mbox, sqerr2rts_qp))
425 return -ENOMEM;
426 MOD_QP_IN_SET_QPC(sqerr2rts_qp, mbox->in, opcode, qpn,
427 opt_param_mask, qpc);
428 break;
429 case MLX5_CMD_OP_INIT2INIT_QP:
430 if (MBOX_ALLOC(mbox, init2init_qp))
431 return -ENOMEM;
432 MOD_QP_IN_SET_QPC(init2init_qp, mbox->in, opcode, qpn,
433 opt_param_mask, qpc);
434 break;
435 default:
436 mlx5_core_err(dev, "Unknown transition for modify QP: OP(0x%x) QPN(0x%x)\n",
437 opcode, qpn);
438 return -EINVAL;
439 }
440 return 0;
441}
442
443int mlx5_core_qp_modify(struct mlx5_core_dev *dev, u16 opcode,
444 u32 opt_param_mask, void *qpc,
340 struct mlx5_core_qp *qp) 445 struct mlx5_core_qp *qp)
341{ 446{
342 struct mlx5_modify_qp_mbox_out out; 447 struct mbox_info mbox;
343 int err = 0; 448 int err;
344 449
345 memset(&out, 0, sizeof(out)); 450 err = modify_qp_mbox_alloc(dev, opcode, qp->qpn,
346 in->hdr.opcode = cpu_to_be16(operation); 451 opt_param_mask, qpc, &mbox);
347 in->qpn = cpu_to_be32(qp->qpn);
348 err = mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out));
349 if (err) 452 if (err)
350 return err; 453 return err;
351 454
352 return mlx5_cmd_status_to_err(&out.hdr); 455 err = mlx5_cmd_exec(dev, mbox.in, mbox.inlen, mbox.out, mbox.outlen);
456 err = err ? : mlx5_cmd_status_to_err_v2(mbox.out);
457 mbox_free(&mbox);
458 return err;
353} 459}
354EXPORT_SYMBOL_GPL(mlx5_core_qp_modify); 460EXPORT_SYMBOL_GPL(mlx5_core_qp_modify);
355 461
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
index 16e1efecaf66..0aacb2a7480d 100644
--- a/include/linux/mlx5/qp.h
+++ b/include/linux/mlx5/qp.h
@@ -479,6 +479,7 @@ struct mlx5_qp_path {
479 u8 rmac[6]; 479 u8 rmac[6];
480}; 480};
481 481
482/* FIXME: use mlx5_ifc.h qpc */
482struct mlx5_qp_context { 483struct mlx5_qp_context {
483 __be32 flags; 484 __be32 flags;
484 __be32 flags_pd; 485 __be32 flags_pd;
@@ -520,21 +521,6 @@ struct mlx5_qp_context {
520 u8 rsvd1[24]; 521 u8 rsvd1[24];
521}; 522};
522 523
523struct mlx5_modify_qp_mbox_in {
524 struct mlx5_inbox_hdr hdr;
525 __be32 qpn;
526 u8 rsvd0[4];
527 __be32 optparam;
528 u8 rsvd1[4];
529 struct mlx5_qp_context ctx;
530 u8 rsvd2[16];
531};
532
533struct mlx5_modify_qp_mbox_out {
534 struct mlx5_outbox_hdr hdr;
535 u8 rsvd0[8];
536};
537
538static inline struct mlx5_core_qp *__mlx5_qp_lookup(struct mlx5_core_dev *dev, u32 qpn) 524static inline struct mlx5_core_qp *__mlx5_qp_lookup(struct mlx5_core_dev *dev, u32 qpn)
539{ 525{
540 return radix_tree_lookup(&dev->priv.qp_table.tree, qpn); 526 return radix_tree_lookup(&dev->priv.qp_table.tree, qpn);
@@ -549,8 +535,8 @@ int mlx5_core_create_qp(struct mlx5_core_dev *dev,
549 struct mlx5_core_qp *qp, 535 struct mlx5_core_qp *qp,
550 u32 *in, 536 u32 *in,
551 int inlen); 537 int inlen);
552int mlx5_core_qp_modify(struct mlx5_core_dev *dev, u16 operation, 538int mlx5_core_qp_modify(struct mlx5_core_dev *dev, u16 opcode,
553 struct mlx5_modify_qp_mbox_in *in, int sqd_event, 539 u32 opt_param_mask, void *qpc,
554 struct mlx5_core_qp *qp); 540 struct mlx5_core_qp *qp);
555int mlx5_core_destroy_qp(struct mlx5_core_dev *dev, 541int mlx5_core_destroy_qp(struct mlx5_core_dev *dev,
556 struct mlx5_core_qp *qp); 542 struct mlx5_core_qp *qp);