Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /*
0003  * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved.
0004  */
0005 
0006 #include <linux/gfp.h>
0007 #include <linux/mlx5/qp.h>
0008 #include <linux/mlx5/driver.h>
0009 #include "mlx5_ib.h"
0010 #include "qp.h"
0011 
0012 static int mlx5_core_drain_dct(struct mlx5_ib_dev *dev,
0013                    struct mlx5_core_dct *dct);
0014 
0015 static struct mlx5_core_rsc_common *
0016 mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn)
0017 {
0018     struct mlx5_core_rsc_common *common;
0019     unsigned long flags;
0020 
0021     spin_lock_irqsave(&table->lock, flags);
0022 
0023     common = radix_tree_lookup(&table->tree, rsn);
0024     if (common)
0025         refcount_inc(&common->refcount);
0026 
0027     spin_unlock_irqrestore(&table->lock, flags);
0028 
0029     return common;
0030 }
0031 
0032 void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common)
0033 {
0034     if (refcount_dec_and_test(&common->refcount))
0035         complete(&common->free);
0036 }
0037 
0038 static u64 qp_allowed_event_types(void)
0039 {
0040     u64 mask;
0041 
0042     mask = BIT(MLX5_EVENT_TYPE_PATH_MIG) |
0043            BIT(MLX5_EVENT_TYPE_COMM_EST) |
0044            BIT(MLX5_EVENT_TYPE_SQ_DRAINED) |
0045            BIT(MLX5_EVENT_TYPE_SRQ_LAST_WQE) |
0046            BIT(MLX5_EVENT_TYPE_WQ_CATAS_ERROR) |
0047            BIT(MLX5_EVENT_TYPE_PATH_MIG_FAILED) |
0048            BIT(MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR) |
0049            BIT(MLX5_EVENT_TYPE_WQ_ACCESS_ERROR);
0050 
0051     return mask;
0052 }
0053 
0054 static u64 rq_allowed_event_types(void)
0055 {
0056     u64 mask;
0057 
0058     mask = BIT(MLX5_EVENT_TYPE_SRQ_LAST_WQE) |
0059            BIT(MLX5_EVENT_TYPE_WQ_CATAS_ERROR);
0060 
0061     return mask;
0062 }
0063 
0064 static u64 sq_allowed_event_types(void)
0065 {
0066     return BIT(MLX5_EVENT_TYPE_WQ_CATAS_ERROR);
0067 }
0068 
0069 static u64 dct_allowed_event_types(void)
0070 {
0071     return BIT(MLX5_EVENT_TYPE_DCT_DRAINED);
0072 }
0073 
0074 static bool is_event_type_allowed(int rsc_type, int event_type)
0075 {
0076     switch (rsc_type) {
0077     case MLX5_EVENT_QUEUE_TYPE_QP:
0078         return BIT(event_type) & qp_allowed_event_types();
0079     case MLX5_EVENT_QUEUE_TYPE_RQ:
0080         return BIT(event_type) & rq_allowed_event_types();
0081     case MLX5_EVENT_QUEUE_TYPE_SQ:
0082         return BIT(event_type) & sq_allowed_event_types();
0083     case MLX5_EVENT_QUEUE_TYPE_DCT:
0084         return BIT(event_type) & dct_allowed_event_types();
0085     default:
0086         WARN(1, "Event arrived for unknown resource type");
0087         return false;
0088     }
0089 }
0090 
0091 static int rsc_event_notifier(struct notifier_block *nb,
0092                   unsigned long type, void *data)
0093 {
0094     struct mlx5_core_rsc_common *common;
0095     struct mlx5_qp_table *table;
0096     struct mlx5_core_dct *dct;
0097     u8 event_type = (u8)type;
0098     struct mlx5_core_qp *qp;
0099     struct mlx5_eqe *eqe;
0100     u32 rsn;
0101 
0102     switch (event_type) {
0103     case MLX5_EVENT_TYPE_DCT_DRAINED:
0104         eqe = data;
0105         rsn = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
0106         rsn |= (MLX5_RES_DCT << MLX5_USER_INDEX_LEN);
0107         break;
0108     case MLX5_EVENT_TYPE_PATH_MIG:
0109     case MLX5_EVENT_TYPE_COMM_EST:
0110     case MLX5_EVENT_TYPE_SQ_DRAINED:
0111     case MLX5_EVENT_TYPE_SRQ_LAST_WQE:
0112     case MLX5_EVENT_TYPE_WQ_CATAS_ERROR:
0113     case MLX5_EVENT_TYPE_PATH_MIG_FAILED:
0114     case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
0115     case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
0116         eqe = data;
0117         rsn = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff;
0118         rsn |= (eqe->data.qp_srq.type << MLX5_USER_INDEX_LEN);
0119         break;
0120     default:
0121         return NOTIFY_DONE;
0122     }
0123 
0124     table = container_of(nb, struct mlx5_qp_table, nb);
0125     common = mlx5_get_rsc(table, rsn);
0126     if (!common)
0127         return NOTIFY_OK;
0128 
0129     if (!is_event_type_allowed((rsn >> MLX5_USER_INDEX_LEN), event_type))
0130         goto out;
0131 
0132     switch (common->res) {
0133     case MLX5_RES_QP:
0134     case MLX5_RES_RQ:
0135     case MLX5_RES_SQ:
0136         qp = (struct mlx5_core_qp *)common;
0137         qp->event(qp, event_type);
0138         break;
0139     case MLX5_RES_DCT:
0140         dct = (struct mlx5_core_dct *)common;
0141         if (event_type == MLX5_EVENT_TYPE_DCT_DRAINED)
0142             complete(&dct->drained);
0143         break;
0144     default:
0145         break;
0146     }
0147 out:
0148     mlx5_core_put_rsc(common);
0149 
0150     return NOTIFY_OK;
0151 }
0152 
0153 static int create_resource_common(struct mlx5_ib_dev *dev,
0154                   struct mlx5_core_qp *qp, int rsc_type)
0155 {
0156     struct mlx5_qp_table *table = &dev->qp_table;
0157     int err;
0158 
0159     qp->common.res = rsc_type;
0160     spin_lock_irq(&table->lock);
0161     err = radix_tree_insert(&table->tree,
0162                 qp->qpn | (rsc_type << MLX5_USER_INDEX_LEN),
0163                 qp);
0164     spin_unlock_irq(&table->lock);
0165     if (err)
0166         return err;
0167 
0168     refcount_set(&qp->common.refcount, 1);
0169     init_completion(&qp->common.free);
0170     qp->pid = current->pid;
0171 
0172     return 0;
0173 }
0174 
0175 static void destroy_resource_common(struct mlx5_ib_dev *dev,
0176                     struct mlx5_core_qp *qp)
0177 {
0178     struct mlx5_qp_table *table = &dev->qp_table;
0179     unsigned long flags;
0180 
0181     spin_lock_irqsave(&table->lock, flags);
0182     radix_tree_delete(&table->tree,
0183               qp->qpn | (qp->common.res << MLX5_USER_INDEX_LEN));
0184     spin_unlock_irqrestore(&table->lock, flags);
0185     mlx5_core_put_rsc((struct mlx5_core_rsc_common *)qp);
0186     wait_for_completion(&qp->common.free);
0187 }
0188 
0189 static int _mlx5_core_destroy_dct(struct mlx5_ib_dev *dev,
0190                   struct mlx5_core_dct *dct, bool need_cleanup)
0191 {
0192     u32 in[MLX5_ST_SZ_DW(destroy_dct_in)] = {};
0193     struct mlx5_core_qp *qp = &dct->mqp;
0194     int err;
0195 
0196     err = mlx5_core_drain_dct(dev, dct);
0197     if (err) {
0198         if (dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
0199             goto destroy;
0200 
0201         return err;
0202     }
0203     wait_for_completion(&dct->drained);
0204 destroy:
0205     if (need_cleanup)
0206         destroy_resource_common(dev, &dct->mqp);
0207     MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT);
0208     MLX5_SET(destroy_dct_in, in, dctn, qp->qpn);
0209     MLX5_SET(destroy_dct_in, in, uid, qp->uid);
0210     err = mlx5_cmd_exec_in(dev->mdev, destroy_dct, in);
0211     return err;
0212 }
0213 
0214 int mlx5_core_create_dct(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct,
0215              u32 *in, int inlen, u32 *out, int outlen)
0216 {
0217     struct mlx5_core_qp *qp = &dct->mqp;
0218     int err;
0219 
0220     init_completion(&dct->drained);
0221     MLX5_SET(create_dct_in, in, opcode, MLX5_CMD_OP_CREATE_DCT);
0222 
0223     err = mlx5_cmd_do(dev->mdev, in, inlen, out, outlen);
0224     if (err)
0225         return err;
0226 
0227     qp->qpn = MLX5_GET(create_dct_out, out, dctn);
0228     qp->uid = MLX5_GET(create_dct_in, in, uid);
0229     err = create_resource_common(dev, qp, MLX5_RES_DCT);
0230     if (err)
0231         goto err_cmd;
0232 
0233     return 0;
0234 err_cmd:
0235     _mlx5_core_destroy_dct(dev, dct, false);
0236     return err;
0237 }
0238 
0239 int mlx5_qpc_create_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp,
0240                u32 *in, int inlen, u32 *out)
0241 {
0242     u32 din[MLX5_ST_SZ_DW(destroy_qp_in)] = {};
0243     int err;
0244 
0245     MLX5_SET(create_qp_in, in, opcode, MLX5_CMD_OP_CREATE_QP);
0246 
0247     err = mlx5_cmd_exec(dev->mdev, in, inlen, out,
0248                 MLX5_ST_SZ_BYTES(create_qp_out));
0249     if (err)
0250         return err;
0251 
0252     qp->uid = MLX5_GET(create_qp_in, in, uid);
0253     qp->qpn = MLX5_GET(create_qp_out, out, qpn);
0254 
0255     err = create_resource_common(dev, qp, MLX5_RES_QP);
0256     if (err)
0257         goto err_cmd;
0258 
0259     mlx5_debug_qp_add(dev->mdev, qp);
0260 
0261     return 0;
0262 
0263 err_cmd:
0264     MLX5_SET(destroy_qp_in, din, opcode, MLX5_CMD_OP_DESTROY_QP);
0265     MLX5_SET(destroy_qp_in, din, qpn, qp->qpn);
0266     MLX5_SET(destroy_qp_in, din, uid, qp->uid);
0267     mlx5_cmd_exec_in(dev->mdev, destroy_qp, din);
0268     return err;
0269 }
0270 
0271 static int mlx5_core_drain_dct(struct mlx5_ib_dev *dev,
0272                    struct mlx5_core_dct *dct)
0273 {
0274     u32 in[MLX5_ST_SZ_DW(drain_dct_in)] = {};
0275     struct mlx5_core_qp *qp = &dct->mqp;
0276 
0277     MLX5_SET(drain_dct_in, in, opcode, MLX5_CMD_OP_DRAIN_DCT);
0278     MLX5_SET(drain_dct_in, in, dctn, qp->qpn);
0279     MLX5_SET(drain_dct_in, in, uid, qp->uid);
0280     return mlx5_cmd_exec_in(dev->mdev, drain_dct, in);
0281 }
0282 
0283 int mlx5_core_destroy_dct(struct mlx5_ib_dev *dev,
0284               struct mlx5_core_dct *dct)
0285 {
0286     return _mlx5_core_destroy_dct(dev, dct, true);
0287 }
0288 
0289 int mlx5_core_destroy_qp(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp)
0290 {
0291     u32 in[MLX5_ST_SZ_DW(destroy_qp_in)] = {};
0292 
0293     mlx5_debug_qp_remove(dev->mdev, qp);
0294 
0295     destroy_resource_common(dev, qp);
0296 
0297     MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP);
0298     MLX5_SET(destroy_qp_in, in, qpn, qp->qpn);
0299     MLX5_SET(destroy_qp_in, in, uid, qp->uid);
0300     mlx5_cmd_exec_in(dev->mdev, destroy_qp, in);
0301     return 0;
0302 }
0303 
0304 int mlx5_core_set_delay_drop(struct mlx5_ib_dev *dev,
0305                  u32 timeout_usec)
0306 {
0307     u32 in[MLX5_ST_SZ_DW(set_delay_drop_params_in)] = {};
0308 
0309     MLX5_SET(set_delay_drop_params_in, in, opcode,
0310          MLX5_CMD_OP_SET_DELAY_DROP_PARAMS);
0311     MLX5_SET(set_delay_drop_params_in, in, delay_drop_timeout,
0312          timeout_usec / 100);
0313     return mlx5_cmd_exec_in(dev->mdev, set_delay_drop_params, in);
0314 }
0315 
0316 struct mbox_info {
0317     u32 *in;
0318     u32 *out;
0319     int inlen;
0320     int outlen;
0321 };
0322 
0323 static int mbox_alloc(struct mbox_info *mbox, int inlen, int outlen)
0324 {
0325     mbox->inlen  = inlen;
0326     mbox->outlen = outlen;
0327     mbox->in = kzalloc(mbox->inlen, GFP_KERNEL);
0328     mbox->out = kzalloc(mbox->outlen, GFP_KERNEL);
0329     if (!mbox->in || !mbox->out) {
0330         kfree(mbox->in);
0331         kfree(mbox->out);
0332         return -ENOMEM;
0333     }
0334 
0335     return 0;
0336 }
0337 
0338 static void mbox_free(struct mbox_info *mbox)
0339 {
0340     kfree(mbox->in);
0341     kfree(mbox->out);
0342 }
0343 
0344 static int get_ece_from_mbox(void *out, u16 opcode)
0345 {
0346     int ece = 0;
0347 
0348     switch (opcode) {
0349     case MLX5_CMD_OP_INIT2INIT_QP:
0350         ece = MLX5_GET(init2init_qp_out, out, ece);
0351         break;
0352     case MLX5_CMD_OP_INIT2RTR_QP:
0353         ece = MLX5_GET(init2rtr_qp_out, out, ece);
0354         break;
0355     case MLX5_CMD_OP_RTR2RTS_QP:
0356         ece = MLX5_GET(rtr2rts_qp_out, out, ece);
0357         break;
0358     case MLX5_CMD_OP_RTS2RTS_QP:
0359         ece = MLX5_GET(rts2rts_qp_out, out, ece);
0360         break;
0361     case MLX5_CMD_OP_RST2INIT_QP:
0362         ece = MLX5_GET(rst2init_qp_out, out, ece);
0363         break;
0364     default:
0365         break;
0366     }
0367 
0368     return ece;
0369 }
0370 
0371 static int modify_qp_mbox_alloc(struct mlx5_core_dev *dev, u16 opcode, int qpn,
0372                 u32 opt_param_mask, void *qpc,
0373                 struct mbox_info *mbox, u16 uid, u32 ece)
0374 {
0375     mbox->out = NULL;
0376     mbox->in = NULL;
0377 
0378 #define MBOX_ALLOC(mbox, typ)  \
0379     mbox_alloc(mbox, MLX5_ST_SZ_BYTES(typ##_in), MLX5_ST_SZ_BYTES(typ##_out))
0380 
0381 #define MOD_QP_IN_SET(typ, in, _opcode, _qpn, _uid)                            \
0382     do {                                                                   \
0383         MLX5_SET(typ##_in, in, opcode, _opcode);                       \
0384         MLX5_SET(typ##_in, in, qpn, _qpn);                             \
0385         MLX5_SET(typ##_in, in, uid, _uid);                             \
0386     } while (0)
0387 
0388 #define MOD_QP_IN_SET_QPC(typ, in, _opcode, _qpn, _opt_p, _qpc, _uid)          \
0389     do {                                                                   \
0390         MOD_QP_IN_SET(typ, in, _opcode, _qpn, _uid);                   \
0391         MLX5_SET(typ##_in, in, opt_param_mask, _opt_p);                \
0392         memcpy(MLX5_ADDR_OF(typ##_in, in, qpc), _qpc,                  \
0393                MLX5_ST_SZ_BYTES(qpc));                                 \
0394     } while (0)
0395 
0396     switch (opcode) {
0397     /* 2RST & 2ERR */
0398     case MLX5_CMD_OP_2RST_QP:
0399         if (MBOX_ALLOC(mbox, qp_2rst))
0400             return -ENOMEM;
0401         MOD_QP_IN_SET(qp_2rst, mbox->in, opcode, qpn, uid);
0402         break;
0403     case MLX5_CMD_OP_2ERR_QP:
0404         if (MBOX_ALLOC(mbox, qp_2err))
0405             return -ENOMEM;
0406         MOD_QP_IN_SET(qp_2err, mbox->in, opcode, qpn, uid);
0407         break;
0408 
0409     /* MODIFY with QPC */
0410     case MLX5_CMD_OP_RST2INIT_QP:
0411         if (MBOX_ALLOC(mbox, rst2init_qp))
0412             return -ENOMEM;
0413         MOD_QP_IN_SET_QPC(rst2init_qp, mbox->in, opcode, qpn,
0414                   opt_param_mask, qpc, uid);
0415         MLX5_SET(rst2init_qp_in, mbox->in, ece, ece);
0416         break;
0417     case MLX5_CMD_OP_INIT2RTR_QP:
0418         if (MBOX_ALLOC(mbox, init2rtr_qp))
0419             return -ENOMEM;
0420         MOD_QP_IN_SET_QPC(init2rtr_qp, mbox->in, opcode, qpn,
0421                   opt_param_mask, qpc, uid);
0422         MLX5_SET(init2rtr_qp_in, mbox->in, ece, ece);
0423         break;
0424     case MLX5_CMD_OP_RTR2RTS_QP:
0425         if (MBOX_ALLOC(mbox, rtr2rts_qp))
0426             return -ENOMEM;
0427         MOD_QP_IN_SET_QPC(rtr2rts_qp, mbox->in, opcode, qpn,
0428                   opt_param_mask, qpc, uid);
0429         MLX5_SET(rtr2rts_qp_in, mbox->in, ece, ece);
0430         break;
0431     case MLX5_CMD_OP_RTS2RTS_QP:
0432         if (MBOX_ALLOC(mbox, rts2rts_qp))
0433             return -ENOMEM;
0434         MOD_QP_IN_SET_QPC(rts2rts_qp, mbox->in, opcode, qpn,
0435                   opt_param_mask, qpc, uid);
0436         MLX5_SET(rts2rts_qp_in, mbox->in, ece, ece);
0437         break;
0438     case MLX5_CMD_OP_SQERR2RTS_QP:
0439         if (MBOX_ALLOC(mbox, sqerr2rts_qp))
0440             return -ENOMEM;
0441         MOD_QP_IN_SET_QPC(sqerr2rts_qp, mbox->in, opcode, qpn,
0442                   opt_param_mask, qpc, uid);
0443         break;
0444     case MLX5_CMD_OP_SQD_RTS_QP:
0445         if (MBOX_ALLOC(mbox, sqd2rts_qp))
0446             return -ENOMEM;
0447         MOD_QP_IN_SET_QPC(sqd2rts_qp, mbox->in, opcode, qpn,
0448                   opt_param_mask, qpc, uid);
0449         break;
0450     case MLX5_CMD_OP_INIT2INIT_QP:
0451         if (MBOX_ALLOC(mbox, init2init_qp))
0452             return -ENOMEM;
0453         MOD_QP_IN_SET_QPC(init2init_qp, mbox->in, opcode, qpn,
0454                   opt_param_mask, qpc, uid);
0455         MLX5_SET(init2init_qp_in, mbox->in, ece, ece);
0456         break;
0457     default:
0458         return -EINVAL;
0459     }
0460     return 0;
0461 }
0462 
0463 int mlx5_core_qp_modify(struct mlx5_ib_dev *dev, u16 opcode, u32 opt_param_mask,
0464             void *qpc, struct mlx5_core_qp *qp, u32 *ece)
0465 {
0466     struct mbox_info mbox;
0467     int err;
0468 
0469     err = modify_qp_mbox_alloc(dev->mdev, opcode, qp->qpn, opt_param_mask,
0470                    qpc, &mbox, qp->uid, (ece) ? *ece : 0);
0471     if (err)
0472         return err;
0473 
0474     err = mlx5_cmd_exec(dev->mdev, mbox.in, mbox.inlen, mbox.out,
0475                 mbox.outlen);
0476 
0477     if (ece)
0478         *ece = get_ece_from_mbox(mbox.out, opcode);
0479 
0480     mbox_free(&mbox);
0481     return err;
0482 }
0483 
0484 int mlx5_init_qp_table(struct mlx5_ib_dev *dev)
0485 {
0486     struct mlx5_qp_table *table = &dev->qp_table;
0487 
0488     spin_lock_init(&table->lock);
0489     INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
0490     mlx5_qp_debugfs_init(dev->mdev);
0491 
0492     table->nb.notifier_call = rsc_event_notifier;
0493     mlx5_notifier_register(dev->mdev, &table->nb);
0494 
0495     return 0;
0496 }
0497 
0498 void mlx5_cleanup_qp_table(struct mlx5_ib_dev *dev)
0499 {
0500     struct mlx5_qp_table *table = &dev->qp_table;
0501 
0502     mlx5_notifier_unregister(dev->mdev, &table->nb);
0503     mlx5_qp_debugfs_cleanup(dev->mdev);
0504 }
0505 
0506 int mlx5_core_qp_query(struct mlx5_ib_dev *dev, struct mlx5_core_qp *qp,
0507                u32 *out, int outlen)
0508 {
0509     u32 in[MLX5_ST_SZ_DW(query_qp_in)] = {};
0510 
0511     MLX5_SET(query_qp_in, in, opcode, MLX5_CMD_OP_QUERY_QP);
0512     MLX5_SET(query_qp_in, in, qpn, qp->qpn);
0513     return mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, outlen);
0514 }
0515 
0516 int mlx5_core_dct_query(struct mlx5_ib_dev *dev, struct mlx5_core_dct *dct,
0517             u32 *out, int outlen)
0518 {
0519     u32 in[MLX5_ST_SZ_DW(query_dct_in)] = {};
0520     struct mlx5_core_qp *qp = &dct->mqp;
0521 
0522     MLX5_SET(query_dct_in, in, opcode, MLX5_CMD_OP_QUERY_DCT);
0523     MLX5_SET(query_dct_in, in, dctn, qp->qpn);
0524 
0525     return mlx5_cmd_exec(dev->mdev, (void *)&in, sizeof(in), (void *)out,
0526                  outlen);
0527 }
0528 
0529 int mlx5_core_xrcd_alloc(struct mlx5_ib_dev *dev, u32 *xrcdn)
0530 {
0531     u32 out[MLX5_ST_SZ_DW(alloc_xrcd_out)] = {};
0532     u32 in[MLX5_ST_SZ_DW(alloc_xrcd_in)] = {};
0533     int err;
0534 
0535     MLX5_SET(alloc_xrcd_in, in, opcode, MLX5_CMD_OP_ALLOC_XRCD);
0536     err = mlx5_cmd_exec_inout(dev->mdev, alloc_xrcd, in, out);
0537     if (!err)
0538         *xrcdn = MLX5_GET(alloc_xrcd_out, out, xrcd);
0539     return err;
0540 }
0541 
0542 int mlx5_core_xrcd_dealloc(struct mlx5_ib_dev *dev, u32 xrcdn)
0543 {
0544     u32 in[MLX5_ST_SZ_DW(dealloc_xrcd_in)] = {};
0545 
0546     MLX5_SET(dealloc_xrcd_in, in, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
0547     MLX5_SET(dealloc_xrcd_in, in, xrcd, xrcdn);
0548     return mlx5_cmd_exec_in(dev->mdev, dealloc_xrcd, in);
0549 }
0550 
0551 static void destroy_rq_tracked(struct mlx5_ib_dev *dev, u32 rqn, u16 uid)
0552 {
0553     u32 in[MLX5_ST_SZ_DW(destroy_rq_in)] = {};
0554 
0555     MLX5_SET(destroy_rq_in, in, opcode, MLX5_CMD_OP_DESTROY_RQ);
0556     MLX5_SET(destroy_rq_in, in, rqn, rqn);
0557     MLX5_SET(destroy_rq_in, in, uid, uid);
0558     mlx5_cmd_exec_in(dev->mdev, destroy_rq, in);
0559 }
0560 
0561 int mlx5_core_create_rq_tracked(struct mlx5_ib_dev *dev, u32 *in, int inlen,
0562                 struct mlx5_core_qp *rq)
0563 {
0564     int err;
0565     u32 rqn;
0566 
0567     err = mlx5_core_create_rq(dev->mdev, in, inlen, &rqn);
0568     if (err)
0569         return err;
0570 
0571     rq->uid = MLX5_GET(create_rq_in, in, uid);
0572     rq->qpn = rqn;
0573     err = create_resource_common(dev, rq, MLX5_RES_RQ);
0574     if (err)
0575         goto err_destroy_rq;
0576 
0577     return 0;
0578 
0579 err_destroy_rq:
0580     destroy_rq_tracked(dev, rq->qpn, rq->uid);
0581 
0582     return err;
0583 }
0584 
0585 int mlx5_core_destroy_rq_tracked(struct mlx5_ib_dev *dev,
0586                  struct mlx5_core_qp *rq)
0587 {
0588     destroy_resource_common(dev, rq);
0589     destroy_rq_tracked(dev, rq->qpn, rq->uid);
0590     return 0;
0591 }
0592 
0593 static void destroy_sq_tracked(struct mlx5_ib_dev *dev, u32 sqn, u16 uid)
0594 {
0595     u32 in[MLX5_ST_SZ_DW(destroy_sq_in)] = {};
0596 
0597     MLX5_SET(destroy_sq_in, in, opcode, MLX5_CMD_OP_DESTROY_SQ);
0598     MLX5_SET(destroy_sq_in, in, sqn, sqn);
0599     MLX5_SET(destroy_sq_in, in, uid, uid);
0600     mlx5_cmd_exec_in(dev->mdev, destroy_sq, in);
0601 }
0602 
0603 int mlx5_core_create_sq_tracked(struct mlx5_ib_dev *dev, u32 *in, int inlen,
0604                 struct mlx5_core_qp *sq)
0605 {
0606     u32 out[MLX5_ST_SZ_DW(create_sq_out)] = {};
0607     int err;
0608 
0609     MLX5_SET(create_sq_in, in, opcode, MLX5_CMD_OP_CREATE_SQ);
0610     err = mlx5_cmd_exec(dev->mdev, in, inlen, out, sizeof(out));
0611     if (err)
0612         return err;
0613 
0614     sq->qpn = MLX5_GET(create_sq_out, out, sqn);
0615     sq->uid = MLX5_GET(create_sq_in, in, uid);
0616     err = create_resource_common(dev, sq, MLX5_RES_SQ);
0617     if (err)
0618         goto err_destroy_sq;
0619 
0620     return 0;
0621 
0622 err_destroy_sq:
0623     destroy_sq_tracked(dev, sq->qpn, sq->uid);
0624 
0625     return err;
0626 }
0627 
0628 void mlx5_core_destroy_sq_tracked(struct mlx5_ib_dev *dev,
0629                   struct mlx5_core_qp *sq)
0630 {
0631     destroy_resource_common(dev, sq);
0632     destroy_sq_tracked(dev, sq->qpn, sq->uid);
0633 }
0634 
0635 struct mlx5_core_rsc_common *mlx5_core_res_hold(struct mlx5_ib_dev *dev,
0636                         int res_num,
0637                         enum mlx5_res_type res_type)
0638 {
0639     u32 rsn = res_num | (res_type << MLX5_USER_INDEX_LEN);
0640     struct mlx5_qp_table *table = &dev->qp_table;
0641 
0642     return mlx5_get_rsc(table, rsn);
0643 }
0644 
0645 void mlx5_core_res_put(struct mlx5_core_rsc_common *res)
0646 {
0647     mlx5_core_put_rsc(res);
0648 }