0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/mlx5/driver.h>
0034 #include "mlx5_core.h"
0035 #include <linux/mlx5/transobj.h>
0036
0037 int mlx5_core_alloc_transport_domain(struct mlx5_core_dev *dev, u32 *tdn)
0038 {
0039 u32 out[MLX5_ST_SZ_DW(alloc_transport_domain_out)] = {};
0040 u32 in[MLX5_ST_SZ_DW(alloc_transport_domain_in)] = {};
0041 int err;
0042
0043 MLX5_SET(alloc_transport_domain_in, in, opcode,
0044 MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN);
0045
0046 err = mlx5_cmd_exec_inout(dev, alloc_transport_domain, in, out);
0047 if (!err)
0048 *tdn = MLX5_GET(alloc_transport_domain_out, out,
0049 transport_domain);
0050
0051 return err;
0052 }
0053 EXPORT_SYMBOL(mlx5_core_alloc_transport_domain);
0054
0055 void mlx5_core_dealloc_transport_domain(struct mlx5_core_dev *dev, u32 tdn)
0056 {
0057 u32 in[MLX5_ST_SZ_DW(dealloc_transport_domain_in)] = {};
0058
0059 MLX5_SET(dealloc_transport_domain_in, in, opcode,
0060 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
0061 MLX5_SET(dealloc_transport_domain_in, in, transport_domain, tdn);
0062 mlx5_cmd_exec_in(dev, dealloc_transport_domain, in);
0063 }
0064 EXPORT_SYMBOL(mlx5_core_dealloc_transport_domain);
0065
0066 int mlx5_core_create_rq(struct mlx5_core_dev *dev, u32 *in, int inlen, u32 *rqn)
0067 {
0068 u32 out[MLX5_ST_SZ_DW(create_rq_out)] = {};
0069 int err;
0070
0071 MLX5_SET(create_rq_in, in, opcode, MLX5_CMD_OP_CREATE_RQ);
0072 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
0073 if (!err)
0074 *rqn = MLX5_GET(create_rq_out, out, rqn);
0075
0076 return err;
0077 }
0078 EXPORT_SYMBOL(mlx5_core_create_rq);
0079
0080 int mlx5_core_modify_rq(struct mlx5_core_dev *dev, u32 rqn, u32 *in)
0081 {
0082 MLX5_SET(modify_rq_in, in, rqn, rqn);
0083 MLX5_SET(modify_rq_in, in, opcode, MLX5_CMD_OP_MODIFY_RQ);
0084
0085 return mlx5_cmd_exec_in(dev, modify_rq, in);
0086 }
0087 EXPORT_SYMBOL(mlx5_core_modify_rq);
0088
0089 void mlx5_core_destroy_rq(struct mlx5_core_dev *dev, u32 rqn)
0090 {
0091 u32 in[MLX5_ST_SZ_DW(destroy_rq_in)] = {};
0092
0093 MLX5_SET(destroy_rq_in, in, opcode, MLX5_CMD_OP_DESTROY_RQ);
0094 MLX5_SET(destroy_rq_in, in, rqn, rqn);
0095 mlx5_cmd_exec_in(dev, destroy_rq, in);
0096 }
0097 EXPORT_SYMBOL(mlx5_core_destroy_rq);
0098
0099 int mlx5_core_query_rq(struct mlx5_core_dev *dev, u32 rqn, u32 *out)
0100 {
0101 u32 in[MLX5_ST_SZ_DW(query_rq_in)] = {};
0102
0103 MLX5_SET(query_rq_in, in, opcode, MLX5_CMD_OP_QUERY_RQ);
0104 MLX5_SET(query_rq_in, in, rqn, rqn);
0105
0106 return mlx5_cmd_exec_inout(dev, query_rq, in, out);
0107 }
0108 EXPORT_SYMBOL(mlx5_core_query_rq);
0109
0110 int mlx5_core_create_sq(struct mlx5_core_dev *dev, u32 *in, int inlen, u32 *sqn)
0111 {
0112 u32 out[MLX5_ST_SZ_DW(create_sq_out)] = {};
0113 int err;
0114
0115 MLX5_SET(create_sq_in, in, opcode, MLX5_CMD_OP_CREATE_SQ);
0116 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
0117 if (!err)
0118 *sqn = MLX5_GET(create_sq_out, out, sqn);
0119
0120 return err;
0121 }
0122
0123 int mlx5_core_modify_sq(struct mlx5_core_dev *dev, u32 sqn, u32 *in)
0124 {
0125 MLX5_SET(modify_sq_in, in, sqn, sqn);
0126 MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ);
0127 return mlx5_cmd_exec_in(dev, modify_sq, in);
0128 }
0129 EXPORT_SYMBOL(mlx5_core_modify_sq);
0130
0131 void mlx5_core_destroy_sq(struct mlx5_core_dev *dev, u32 sqn)
0132 {
0133 u32 in[MLX5_ST_SZ_DW(destroy_sq_in)] = {};
0134
0135 MLX5_SET(destroy_sq_in, in, opcode, MLX5_CMD_OP_DESTROY_SQ);
0136 MLX5_SET(destroy_sq_in, in, sqn, sqn);
0137 mlx5_cmd_exec_in(dev, destroy_sq, in);
0138 }
0139
0140 int mlx5_core_query_sq(struct mlx5_core_dev *dev, u32 sqn, u32 *out)
0141 {
0142 u32 in[MLX5_ST_SZ_DW(query_sq_in)] = {};
0143
0144 MLX5_SET(query_sq_in, in, opcode, MLX5_CMD_OP_QUERY_SQ);
0145 MLX5_SET(query_sq_in, in, sqn, sqn);
0146 return mlx5_cmd_exec_inout(dev, query_sq, in, out);
0147 }
0148 EXPORT_SYMBOL(mlx5_core_query_sq);
0149
0150 int mlx5_core_query_sq_state(struct mlx5_core_dev *dev, u32 sqn, u8 *state)
0151 {
0152 void *out;
0153 void *sqc;
0154 int inlen;
0155 int err;
0156
0157 inlen = MLX5_ST_SZ_BYTES(query_sq_out);
0158 out = kvzalloc(inlen, GFP_KERNEL);
0159 if (!out)
0160 return -ENOMEM;
0161
0162 err = mlx5_core_query_sq(dev, sqn, out);
0163 if (err)
0164 goto out;
0165
0166 sqc = MLX5_ADDR_OF(query_sq_out, out, sq_context);
0167 *state = MLX5_GET(sqc, sqc, state);
0168
0169 out:
0170 kvfree(out);
0171 return err;
0172 }
0173 EXPORT_SYMBOL_GPL(mlx5_core_query_sq_state);
0174
0175 int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, u32 *tirn)
0176 {
0177 u32 out[MLX5_ST_SZ_DW(create_tir_out)] = {};
0178 int err;
0179
0180 MLX5_SET(create_tir_in, in, opcode, MLX5_CMD_OP_CREATE_TIR);
0181 err = mlx5_cmd_exec_inout(dev, create_tir, in, out);
0182 if (!err)
0183 *tirn = MLX5_GET(create_tir_out, out, tirn);
0184
0185 return err;
0186 }
0187 EXPORT_SYMBOL(mlx5_core_create_tir);
0188
0189 int mlx5_core_modify_tir(struct mlx5_core_dev *dev, u32 tirn, u32 *in)
0190 {
0191 MLX5_SET(modify_tir_in, in, tirn, tirn);
0192 MLX5_SET(modify_tir_in, in, opcode, MLX5_CMD_OP_MODIFY_TIR);
0193 return mlx5_cmd_exec_in(dev, modify_tir, in);
0194 }
0195
0196 void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn)
0197 {
0198 u32 in[MLX5_ST_SZ_DW(destroy_tir_in)] = {};
0199
0200 MLX5_SET(destroy_tir_in, in, opcode, MLX5_CMD_OP_DESTROY_TIR);
0201 MLX5_SET(destroy_tir_in, in, tirn, tirn);
0202 mlx5_cmd_exec_in(dev, destroy_tir, in);
0203 }
0204 EXPORT_SYMBOL(mlx5_core_destroy_tir);
0205
0206 int mlx5_core_create_tis(struct mlx5_core_dev *dev, u32 *in, u32 *tisn)
0207 {
0208 u32 out[MLX5_ST_SZ_DW(create_tis_out)] = {};
0209 int err;
0210
0211 MLX5_SET(create_tis_in, in, opcode, MLX5_CMD_OP_CREATE_TIS);
0212 err = mlx5_cmd_exec_inout(dev, create_tis, in, out);
0213 if (!err)
0214 *tisn = MLX5_GET(create_tis_out, out, tisn);
0215
0216 return err;
0217 }
0218 EXPORT_SYMBOL(mlx5_core_create_tis);
0219
0220 int mlx5_core_modify_tis(struct mlx5_core_dev *dev, u32 tisn, u32 *in)
0221 {
0222 MLX5_SET(modify_tis_in, in, tisn, tisn);
0223 MLX5_SET(modify_tis_in, in, opcode, MLX5_CMD_OP_MODIFY_TIS);
0224
0225 return mlx5_cmd_exec_in(dev, modify_tis, in);
0226 }
0227 EXPORT_SYMBOL(mlx5_core_modify_tis);
0228
0229 void mlx5_core_destroy_tis(struct mlx5_core_dev *dev, u32 tisn)
0230 {
0231 u32 in[MLX5_ST_SZ_DW(destroy_tis_in)] = {};
0232
0233 MLX5_SET(destroy_tis_in, in, opcode, MLX5_CMD_OP_DESTROY_TIS);
0234 MLX5_SET(destroy_tis_in, in, tisn, tisn);
0235 mlx5_cmd_exec_in(dev, destroy_tis, in);
0236 }
0237 EXPORT_SYMBOL(mlx5_core_destroy_tis);
0238
0239 int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen,
0240 u32 *rqtn)
0241 {
0242 u32 out[MLX5_ST_SZ_DW(create_rqt_out)] = {};
0243 int err;
0244
0245 MLX5_SET(create_rqt_in, in, opcode, MLX5_CMD_OP_CREATE_RQT);
0246 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
0247 if (!err)
0248 *rqtn = MLX5_GET(create_rqt_out, out, rqtn);
0249
0250 return err;
0251 }
0252 EXPORT_SYMBOL(mlx5_core_create_rqt);
0253
0254 int mlx5_core_modify_rqt(struct mlx5_core_dev *dev, u32 rqtn, u32 *in,
0255 int inlen)
0256 {
0257 u32 out[MLX5_ST_SZ_DW(modify_rqt_out)] = {};
0258
0259 MLX5_SET(modify_rqt_in, in, rqtn, rqtn);
0260 MLX5_SET(modify_rqt_in, in, opcode, MLX5_CMD_OP_MODIFY_RQT);
0261 return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
0262 }
0263
0264 void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn)
0265 {
0266 u32 in[MLX5_ST_SZ_DW(destroy_rqt_in)] = {};
0267
0268 MLX5_SET(destroy_rqt_in, in, opcode, MLX5_CMD_OP_DESTROY_RQT);
0269 MLX5_SET(destroy_rqt_in, in, rqtn, rqtn);
0270 mlx5_cmd_exec_in(dev, destroy_rqt, in);
0271 }
0272 EXPORT_SYMBOL(mlx5_core_destroy_rqt);
0273
0274 static int mlx5_hairpin_create_rq(struct mlx5_core_dev *mdev,
0275 struct mlx5_hairpin_params *params, u32 *rqn)
0276 {
0277 u32 in[MLX5_ST_SZ_DW(create_rq_in)] = {0};
0278 void *rqc, *wq;
0279
0280 rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
0281 wq = MLX5_ADDR_OF(rqc, rqc, wq);
0282
0283 MLX5_SET(rqc, rqc, hairpin, 1);
0284 MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST);
0285 MLX5_SET(rqc, rqc, counter_set_id, params->q_counter);
0286
0287 MLX5_SET(wq, wq, log_hairpin_data_sz, params->log_data_size);
0288 MLX5_SET(wq, wq, log_hairpin_num_packets, params->log_num_packets);
0289
0290 return mlx5_core_create_rq(mdev, in, MLX5_ST_SZ_BYTES(create_rq_in), rqn);
0291 }
0292
0293 static int mlx5_hairpin_create_sq(struct mlx5_core_dev *mdev,
0294 struct mlx5_hairpin_params *params, u32 *sqn)
0295 {
0296 u32 in[MLX5_ST_SZ_DW(create_sq_in)] = {0};
0297 void *sqc, *wq;
0298
0299 sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
0300 wq = MLX5_ADDR_OF(sqc, sqc, wq);
0301
0302 MLX5_SET(sqc, sqc, hairpin, 1);
0303 MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST);
0304
0305 MLX5_SET(wq, wq, log_hairpin_data_sz, params->log_data_size);
0306 MLX5_SET(wq, wq, log_hairpin_num_packets, params->log_num_packets);
0307
0308 return mlx5_core_create_sq(mdev, in, MLX5_ST_SZ_BYTES(create_sq_in), sqn);
0309 }
0310
0311 static int mlx5_hairpin_create_queues(struct mlx5_hairpin *hp,
0312 struct mlx5_hairpin_params *params)
0313 {
0314 int i, j, err;
0315
0316 for (i = 0; i < hp->num_channels; i++) {
0317 err = mlx5_hairpin_create_rq(hp->func_mdev, params, &hp->rqn[i]);
0318 if (err)
0319 goto out_err_rq;
0320 }
0321
0322 for (i = 0; i < hp->num_channels; i++) {
0323 err = mlx5_hairpin_create_sq(hp->peer_mdev, params, &hp->sqn[i]);
0324 if (err)
0325 goto out_err_sq;
0326 }
0327
0328 return 0;
0329
0330 out_err_sq:
0331 for (j = 0; j < i; j++)
0332 mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[j]);
0333 i = hp->num_channels;
0334 out_err_rq:
0335 for (j = 0; j < i; j++)
0336 mlx5_core_destroy_rq(hp->func_mdev, hp->rqn[j]);
0337 return err;
0338 }
0339
0340 static void mlx5_hairpin_destroy_queues(struct mlx5_hairpin *hp)
0341 {
0342 int i;
0343
0344 for (i = 0; i < hp->num_channels; i++) {
0345 mlx5_core_destroy_rq(hp->func_mdev, hp->rqn[i]);
0346 if (!hp->peer_gone)
0347 mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[i]);
0348 }
0349 }
0350
0351 static int mlx5_hairpin_modify_rq(struct mlx5_core_dev *func_mdev, u32 rqn,
0352 int curr_state, int next_state,
0353 u16 peer_vhca, u32 peer_sq)
0354 {
0355 u32 in[MLX5_ST_SZ_DW(modify_rq_in)] = {};
0356 void *rqc;
0357
0358 rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
0359
0360 if (next_state == MLX5_RQC_STATE_RDY) {
0361 MLX5_SET(rqc, rqc, hairpin_peer_sq, peer_sq);
0362 MLX5_SET(rqc, rqc, hairpin_peer_vhca, peer_vhca);
0363 }
0364
0365 MLX5_SET(modify_rq_in, in, rq_state, curr_state);
0366 MLX5_SET(rqc, rqc, state, next_state);
0367
0368 return mlx5_core_modify_rq(func_mdev, rqn, in);
0369 }
0370
0371 static int mlx5_hairpin_modify_sq(struct mlx5_core_dev *peer_mdev, u32 sqn,
0372 int curr_state, int next_state,
0373 u16 peer_vhca, u32 peer_rq)
0374 {
0375 u32 in[MLX5_ST_SZ_DW(modify_sq_in)] = {0};
0376 void *sqc;
0377
0378 sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
0379
0380 if (next_state == MLX5_SQC_STATE_RDY) {
0381 MLX5_SET(sqc, sqc, hairpin_peer_rq, peer_rq);
0382 MLX5_SET(sqc, sqc, hairpin_peer_vhca, peer_vhca);
0383 }
0384
0385 MLX5_SET(modify_sq_in, in, sq_state, curr_state);
0386 MLX5_SET(sqc, sqc, state, next_state);
0387
0388 return mlx5_core_modify_sq(peer_mdev, sqn, in);
0389 }
0390
0391 static int mlx5_hairpin_pair_queues(struct mlx5_hairpin *hp)
0392 {
0393 int i, j, err;
0394
0395
0396 for (i = 0; i < hp->num_channels; i++) {
0397 err = mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i],
0398 MLX5_SQC_STATE_RST, MLX5_SQC_STATE_RDY,
0399 MLX5_CAP_GEN(hp->func_mdev, vhca_id), hp->rqn[i]);
0400 if (err)
0401 goto err_modify_sq;
0402 }
0403
0404
0405 for (i = 0; i < hp->num_channels; i++) {
0406 err = mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[i],
0407 MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY,
0408 MLX5_CAP_GEN(hp->peer_mdev, vhca_id), hp->sqn[i]);
0409 if (err)
0410 goto err_modify_rq;
0411 }
0412
0413 return 0;
0414
0415 err_modify_rq:
0416 for (j = 0; j < i; j++)
0417 mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[j], MLX5_RQC_STATE_RDY,
0418 MLX5_RQC_STATE_RST, 0, 0);
0419 i = hp->num_channels;
0420 err_modify_sq:
0421 for (j = 0; j < i; j++)
0422 mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[j], MLX5_SQC_STATE_RDY,
0423 MLX5_SQC_STATE_RST, 0, 0);
0424 return err;
0425 }
0426
0427 static void mlx5_hairpin_unpair_peer_sq(struct mlx5_hairpin *hp)
0428 {
0429 int i;
0430
0431 for (i = 0; i < hp->num_channels; i++)
0432 mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i], MLX5_SQC_STATE_RDY,
0433 MLX5_SQC_STATE_RST, 0, 0);
0434 }
0435
0436 static void mlx5_hairpin_unpair_queues(struct mlx5_hairpin *hp)
0437 {
0438 int i;
0439
0440
0441 for (i = 0; i < hp->num_channels; i++)
0442 mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[i], MLX5_RQC_STATE_RDY,
0443 MLX5_RQC_STATE_RST, 0, 0);
0444
0445 if (!hp->peer_gone)
0446 mlx5_hairpin_unpair_peer_sq(hp);
0447 }
0448
0449 struct mlx5_hairpin *
0450 mlx5_core_hairpin_create(struct mlx5_core_dev *func_mdev,
0451 struct mlx5_core_dev *peer_mdev,
0452 struct mlx5_hairpin_params *params)
0453 {
0454 struct mlx5_hairpin *hp;
0455 int size, err;
0456
0457 size = sizeof(*hp) + params->num_channels * 2 * sizeof(u32);
0458 hp = kzalloc(size, GFP_KERNEL);
0459 if (!hp)
0460 return ERR_PTR(-ENOMEM);
0461
0462 hp->func_mdev = func_mdev;
0463 hp->peer_mdev = peer_mdev;
0464 hp->num_channels = params->num_channels;
0465
0466 hp->rqn = (void *)hp + sizeof(*hp);
0467 hp->sqn = hp->rqn + params->num_channels;
0468
0469
0470 err = mlx5_hairpin_create_queues(hp, params);
0471 if (err)
0472 goto err_create_queues;
0473
0474 err = mlx5_hairpin_pair_queues(hp);
0475 if (err)
0476 goto err_pair_queues;
0477
0478 return hp;
0479
0480 err_pair_queues:
0481 mlx5_hairpin_destroy_queues(hp);
0482 err_create_queues:
0483 kfree(hp);
0484 return ERR_PTR(err);
0485 }
0486
0487 void mlx5_core_hairpin_destroy(struct mlx5_hairpin *hp)
0488 {
0489 mlx5_hairpin_unpair_queues(hp);
0490 mlx5_hairpin_destroy_queues(hp);
0491 kfree(hp);
0492 }
0493
0494 void mlx5_core_hairpin_clear_dead_peer(struct mlx5_hairpin *hp)
0495 {
0496 int i;
0497
0498 mlx5_hairpin_unpair_peer_sq(hp);
0499
0500
0501 for (i = 0; i < hp->num_channels; i++)
0502 mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[i]);
0503
0504 hp->peer_gone = true;
0505 }