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/vport.h>
0034 #include <rdma/ib_mad.h>
0035 #include <rdma/ib_smi.h>
0036 #include <rdma/ib_pma.h>
0037 #include "mlx5_ib.h"
0038 #include "cmd.h"
0039
0040 enum {
0041 MLX5_IB_VENDOR_CLASS1 = 0x9,
0042 MLX5_IB_VENDOR_CLASS2 = 0xa
0043 };
0044
0045 static bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u32 port_num,
0046 struct ib_mad *in_mad)
0047 {
0048 if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED &&
0049 in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
0050 return true;
0051 return dev->port_caps[port_num - 1].has_smi;
0052 }
0053
0054 static int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey,
0055 int ignore_bkey, u32 port, const struct ib_wc *in_wc,
0056 const struct ib_grh *in_grh, const void *in_mad,
0057 void *response_mad)
0058 {
0059 u8 op_modifier = 0;
0060
0061 if (!can_do_mad_ifc(dev, port, (struct ib_mad *)in_mad))
0062 return -EPERM;
0063
0064
0065
0066
0067 if (ignore_mkey || !in_wc)
0068 op_modifier |= 0x1;
0069 if (ignore_bkey || !in_wc)
0070 op_modifier |= 0x2;
0071
0072 return mlx5_cmd_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier,
0073 port);
0074 }
0075
0076 static void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext,
0077 void *out)
0078 {
0079 #define MLX5_SUM_CNT(p, cntr1, cntr2) \
0080 (MLX5_GET64(query_vport_counter_out, p, cntr1) + \
0081 MLX5_GET64(query_vport_counter_out, p, cntr2))
0082
0083 pma_cnt_ext->port_xmit_data =
0084 cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets,
0085 transmitted_ib_multicast.octets) >> 2);
0086 pma_cnt_ext->port_rcv_data =
0087 cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets,
0088 received_ib_multicast.octets) >> 2);
0089 pma_cnt_ext->port_xmit_packets =
0090 cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.packets,
0091 transmitted_ib_multicast.packets));
0092 pma_cnt_ext->port_rcv_packets =
0093 cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.packets,
0094 received_ib_multicast.packets));
0095 pma_cnt_ext->port_unicast_xmit_packets =
0096 MLX5_GET64_BE(query_vport_counter_out,
0097 out, transmitted_ib_unicast.packets);
0098 pma_cnt_ext->port_unicast_rcv_packets =
0099 MLX5_GET64_BE(query_vport_counter_out,
0100 out, received_ib_unicast.packets);
0101 pma_cnt_ext->port_multicast_xmit_packets =
0102 MLX5_GET64_BE(query_vport_counter_out,
0103 out, transmitted_ib_multicast.packets);
0104 pma_cnt_ext->port_multicast_rcv_packets =
0105 MLX5_GET64_BE(query_vport_counter_out,
0106 out, received_ib_multicast.packets);
0107 }
0108
0109 static void pma_cnt_assign(struct ib_pma_portcounters *pma_cnt,
0110 void *out)
0111 {
0112
0113
0114
0115 void *out_pma = MLX5_ADDR_OF(ppcnt_reg, out,
0116 counter_set);
0117
0118 #define MLX5_ASSIGN_PMA_CNTR(counter_var, counter_name) { \
0119 counter_var = MLX5_GET_BE(typeof(counter_var), \
0120 ib_port_cntrs_grp_data_layout, \
0121 out_pma, counter_name); \
0122 }
0123
0124 MLX5_ASSIGN_PMA_CNTR(pma_cnt->symbol_error_counter,
0125 symbol_error_counter);
0126 MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_error_recovery_counter,
0127 link_error_recovery_counter);
0128 MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_downed_counter,
0129 link_downed_counter);
0130 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_errors,
0131 port_rcv_errors);
0132 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_remphys_errors,
0133 port_rcv_remote_physical_errors);
0134 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_switch_relay_errors,
0135 port_rcv_switch_relay_errors);
0136 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_discards,
0137 port_xmit_discards);
0138 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_constraint_errors,
0139 port_xmit_constraint_errors);
0140 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_xmit_wait,
0141 port_xmit_wait);
0142 MLX5_ASSIGN_PMA_CNTR(pma_cnt->port_rcv_constraint_errors,
0143 port_rcv_constraint_errors);
0144 MLX5_ASSIGN_PMA_CNTR(pma_cnt->link_overrun_errors,
0145 link_overrun_errors);
0146 MLX5_ASSIGN_PMA_CNTR(pma_cnt->vl15_dropped,
0147 vl_15_dropped);
0148 }
0149
0150 static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
0151 const struct ib_mad *in_mad, struct ib_mad *out_mad)
0152 {
0153 struct mlx5_core_dev *mdev;
0154 bool native_port = true;
0155 u32 mdev_port_num;
0156 void *out_cnt;
0157 int err;
0158
0159 mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
0160 if (!mdev) {
0161
0162
0163
0164
0165 native_port = false;
0166 mdev = dev->mdev;
0167 mdev_port_num = 1;
0168 }
0169 if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
0170
0171 mdev = dev->mdev;
0172 mdev_port_num = 1;
0173 }
0174
0175
0176 if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
0177 struct ib_class_port_info cpi = {};
0178
0179 cpi.capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;
0180 memcpy((out_mad->data + 40), &cpi, sizeof(cpi));
0181 err = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
0182 goto done;
0183 }
0184
0185 if (in_mad->mad_hdr.attr_id == IB_PMA_PORT_COUNTERS_EXT) {
0186 struct ib_pma_portcounters_ext *pma_cnt_ext =
0187 (struct ib_pma_portcounters_ext *)(out_mad->data + 40);
0188 int sz = MLX5_ST_SZ_BYTES(query_vport_counter_out);
0189
0190 out_cnt = kvzalloc(sz, GFP_KERNEL);
0191 if (!out_cnt) {
0192 err = IB_MAD_RESULT_FAILURE;
0193 goto done;
0194 }
0195
0196 err = mlx5_core_query_vport_counter(mdev, 0, 0, mdev_port_num,
0197 out_cnt);
0198 if (!err)
0199 pma_cnt_ext_assign(pma_cnt_ext, out_cnt);
0200 } else {
0201 struct ib_pma_portcounters *pma_cnt =
0202 (struct ib_pma_portcounters *)(out_mad->data + 40);
0203 int sz = MLX5_ST_SZ_BYTES(ppcnt_reg);
0204
0205 out_cnt = kvzalloc(sz, GFP_KERNEL);
0206 if (!out_cnt) {
0207 err = IB_MAD_RESULT_FAILURE;
0208 goto done;
0209 }
0210
0211 err = mlx5_core_query_ib_ppcnt(mdev, mdev_port_num,
0212 out_cnt, sz);
0213 if (!err)
0214 pma_cnt_assign(pma_cnt, out_cnt);
0215 }
0216 kvfree(out_cnt);
0217 err = err ? IB_MAD_RESULT_FAILURE :
0218 IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
0219 done:
0220 if (native_port)
0221 mlx5_ib_put_native_port_mdev(dev, port_num);
0222 return err;
0223 }
0224
0225 int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u32 port_num,
0226 const struct ib_wc *in_wc, const struct ib_grh *in_grh,
0227 const struct ib_mad *in, struct ib_mad *out,
0228 size_t *out_mad_size, u16 *out_mad_pkey_index)
0229 {
0230 struct mlx5_ib_dev *dev = to_mdev(ibdev);
0231 u8 mgmt_class = in->mad_hdr.mgmt_class;
0232 u8 method = in->mad_hdr.method;
0233 u16 slid;
0234 int err;
0235
0236 slid = in_wc ? ib_lid_cpu16(in_wc->slid) :
0237 be16_to_cpu(IB_LID_PERMISSIVE);
0238
0239 if (method == IB_MGMT_METHOD_TRAP && !slid)
0240 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
0241
0242 switch (mgmt_class) {
0243 case IB_MGMT_CLASS_SUBN_LID_ROUTED:
0244 case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE: {
0245 if (method != IB_MGMT_METHOD_GET &&
0246 method != IB_MGMT_METHOD_SET &&
0247 method != IB_MGMT_METHOD_TRAP_REPRESS)
0248 return IB_MAD_RESULT_SUCCESS;
0249
0250
0251
0252 if (in->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
0253 return IB_MAD_RESULT_SUCCESS;
0254 } break;
0255 case IB_MGMT_CLASS_PERF_MGMT:
0256 if (MLX5_CAP_GEN(dev->mdev, vport_counters) &&
0257 method == IB_MGMT_METHOD_GET)
0258 return process_pma_cmd(dev, port_num, in, out);
0259 fallthrough;
0260 case MLX5_IB_VENDOR_CLASS1:
0261 case MLX5_IB_VENDOR_CLASS2:
0262 case IB_MGMT_CLASS_CONG_MGMT: {
0263 if (method != IB_MGMT_METHOD_GET &&
0264 method != IB_MGMT_METHOD_SET)
0265 return IB_MAD_RESULT_SUCCESS;
0266 } break;
0267 default:
0268 return IB_MAD_RESULT_SUCCESS;
0269 }
0270
0271 err = mlx5_MAD_IFC(to_mdev(ibdev), mad_flags & IB_MAD_IGNORE_MKEY,
0272 mad_flags & IB_MAD_IGNORE_BKEY, port_num, in_wc,
0273 in_grh, in, out);
0274 if (err)
0275 return IB_MAD_RESULT_FAILURE;
0276
0277
0278 if (mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
0279 out->mad_hdr.status |= cpu_to_be16(1 << 15);
0280
0281 if (method == IB_MGMT_METHOD_TRAP_REPRESS)
0282
0283 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
0284
0285 return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
0286 }
0287
0288 int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, unsigned int port)
0289 {
0290 struct ib_smp *in_mad = NULL;
0291 struct ib_smp *out_mad = NULL;
0292 int err = -ENOMEM;
0293 u16 packet_error;
0294
0295 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0296 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0297 if (!in_mad || !out_mad)
0298 goto out;
0299
0300 ib_init_query_mad(in_mad);
0301 in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
0302 in_mad->attr_mod = cpu_to_be32(port);
0303
0304 err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
0305
0306 packet_error = be16_to_cpu(out_mad->status);
0307
0308 dev->port_caps[port - 1].ext_port_cap = (!err && !packet_error) ?
0309 MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0;
0310
0311 out:
0312 kfree(in_mad);
0313 kfree(out_mad);
0314 return err;
0315 }
0316
0317 static int mlx5_query_mad_ifc_smp_attr_node_info(struct ib_device *ibdev,
0318 struct ib_smp *out_mad)
0319 {
0320 struct ib_smp *in_mad = NULL;
0321 int err = -ENOMEM;
0322
0323 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0324 if (!in_mad)
0325 return -ENOMEM;
0326
0327 ib_init_query_mad(in_mad);
0328 in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
0329
0330 err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad,
0331 out_mad);
0332
0333 kfree(in_mad);
0334 return err;
0335 }
0336
0337 int mlx5_query_mad_ifc_system_image_guid(struct ib_device *ibdev,
0338 __be64 *sys_image_guid)
0339 {
0340 struct ib_smp *out_mad = NULL;
0341 int err = -ENOMEM;
0342
0343 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0344 if (!out_mad)
0345 return -ENOMEM;
0346
0347 err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
0348 if (err)
0349 goto out;
0350
0351 memcpy(sys_image_guid, out_mad->data + 4, 8);
0352
0353 out:
0354 kfree(out_mad);
0355
0356 return err;
0357 }
0358
0359 int mlx5_query_mad_ifc_max_pkeys(struct ib_device *ibdev,
0360 u16 *max_pkeys)
0361 {
0362 struct ib_smp *out_mad = NULL;
0363 int err = -ENOMEM;
0364
0365 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0366 if (!out_mad)
0367 return -ENOMEM;
0368
0369 err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
0370 if (err)
0371 goto out;
0372
0373 *max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28));
0374
0375 out:
0376 kfree(out_mad);
0377
0378 return err;
0379 }
0380
0381 int mlx5_query_mad_ifc_vendor_id(struct ib_device *ibdev,
0382 u32 *vendor_id)
0383 {
0384 struct ib_smp *out_mad = NULL;
0385 int err = -ENOMEM;
0386
0387 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0388 if (!out_mad)
0389 return -ENOMEM;
0390
0391 err = mlx5_query_mad_ifc_smp_attr_node_info(ibdev, out_mad);
0392 if (err)
0393 goto out;
0394
0395 *vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffff;
0396
0397 out:
0398 kfree(out_mad);
0399
0400 return err;
0401 }
0402
0403 int mlx5_query_mad_ifc_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
0404 {
0405 struct ib_smp *in_mad = NULL;
0406 struct ib_smp *out_mad = NULL;
0407 int err = -ENOMEM;
0408
0409 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0410 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0411 if (!in_mad || !out_mad)
0412 goto out;
0413
0414 ib_init_query_mad(in_mad);
0415 in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
0416
0417 err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
0418 if (err)
0419 goto out;
0420
0421 memcpy(node_desc, out_mad->data, IB_DEVICE_NODE_DESC_MAX);
0422 out:
0423 kfree(in_mad);
0424 kfree(out_mad);
0425 return err;
0426 }
0427
0428 int mlx5_query_mad_ifc_node_guid(struct mlx5_ib_dev *dev, __be64 *node_guid)
0429 {
0430 struct ib_smp *in_mad = NULL;
0431 struct ib_smp *out_mad = NULL;
0432 int err = -ENOMEM;
0433
0434 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0435 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0436 if (!in_mad || !out_mad)
0437 goto out;
0438
0439 ib_init_query_mad(in_mad);
0440 in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
0441
0442 err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
0443 if (err)
0444 goto out;
0445
0446 memcpy(node_guid, out_mad->data + 12, 8);
0447 out:
0448 kfree(in_mad);
0449 kfree(out_mad);
0450 return err;
0451 }
0452
0453 int mlx5_query_mad_ifc_pkey(struct ib_device *ibdev, u32 port, u16 index,
0454 u16 *pkey)
0455 {
0456 struct ib_smp *in_mad = NULL;
0457 struct ib_smp *out_mad = NULL;
0458 int err = -ENOMEM;
0459
0460 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0461 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0462 if (!in_mad || !out_mad)
0463 goto out;
0464
0465 ib_init_query_mad(in_mad);
0466 in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
0467 in_mad->attr_mod = cpu_to_be32(index / 32);
0468
0469 err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
0470 out_mad);
0471 if (err)
0472 goto out;
0473
0474 *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]);
0475
0476 out:
0477 kfree(in_mad);
0478 kfree(out_mad);
0479 return err;
0480 }
0481
0482 int mlx5_query_mad_ifc_gids(struct ib_device *ibdev, u32 port, int index,
0483 union ib_gid *gid)
0484 {
0485 struct ib_smp *in_mad = NULL;
0486 struct ib_smp *out_mad = NULL;
0487 int err = -ENOMEM;
0488
0489 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0490 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0491 if (!in_mad || !out_mad)
0492 goto out;
0493
0494 ib_init_query_mad(in_mad);
0495 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
0496 in_mad->attr_mod = cpu_to_be32(port);
0497
0498 err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
0499 out_mad);
0500 if (err)
0501 goto out;
0502
0503 memcpy(gid->raw, out_mad->data + 8, 8);
0504
0505 ib_init_query_mad(in_mad);
0506 in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
0507 in_mad->attr_mod = cpu_to_be32(index / 8);
0508
0509 err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad,
0510 out_mad);
0511 if (err)
0512 goto out;
0513
0514 memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
0515
0516 out:
0517 kfree(in_mad);
0518 kfree(out_mad);
0519 return err;
0520 }
0521
0522 int mlx5_query_mad_ifc_port(struct ib_device *ibdev, u32 port,
0523 struct ib_port_attr *props)
0524 {
0525 struct mlx5_ib_dev *dev = to_mdev(ibdev);
0526 struct mlx5_core_dev *mdev = dev->mdev;
0527 struct ib_smp *in_mad = NULL;
0528 struct ib_smp *out_mad = NULL;
0529 int ext_active_speed;
0530 int err = -ENOMEM;
0531
0532 in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);
0533 out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL);
0534 if (!in_mad || !out_mad)
0535 goto out;
0536
0537
0538
0539 ib_init_query_mad(in_mad);
0540 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
0541 in_mad->attr_mod = cpu_to_be32(port);
0542
0543 err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad);
0544 if (err) {
0545 mlx5_ib_warn(dev, "err %d\n", err);
0546 goto out;
0547 }
0548
0549 props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16));
0550 props->lmc = out_mad->data[34] & 0x7;
0551 props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18));
0552 props->sm_sl = out_mad->data[36] & 0xf;
0553 props->state = out_mad->data[32] & 0xf;
0554 props->phys_state = out_mad->data[33] >> 4;
0555 props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20));
0556 props->gid_tbl_len = out_mad->data[50];
0557 props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
0558 props->pkey_tbl_len = dev->pkey_table_len;
0559 props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46));
0560 props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48));
0561 props->active_width = out_mad->data[31] & 0xf;
0562 props->active_speed = out_mad->data[35] >> 4;
0563 props->max_mtu = out_mad->data[41] & 0xf;
0564 props->active_mtu = out_mad->data[36] >> 4;
0565 props->subnet_timeout = out_mad->data[51] & 0x1f;
0566 props->max_vl_num = out_mad->data[37] >> 4;
0567 props->init_type_reply = out_mad->data[41] >> 4;
0568
0569 if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP) {
0570 props->port_cap_flags2 =
0571 be16_to_cpup((__be16 *)(out_mad->data + 60));
0572
0573 if (props->port_cap_flags2 & IB_PORT_LINK_WIDTH_2X_SUP)
0574 props->active_width = out_mad->data[31] & 0x1f;
0575 }
0576
0577
0578 if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
0579 ext_active_speed = out_mad->data[62] >> 4;
0580
0581 switch (ext_active_speed) {
0582 case 1:
0583 props->active_speed = 16;
0584 break;
0585 case 2:
0586 props->active_speed = 32;
0587 break;
0588 case 4:
0589 if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
0590 props->port_cap_flags2 & IB_PORT_LINK_SPEED_HDR_SUP)
0591 props->active_speed = IB_SPEED_HDR;
0592 break;
0593 case 8:
0594 if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP &&
0595 props->port_cap_flags2 & IB_PORT_LINK_SPEED_NDR_SUP)
0596 props->active_speed = IB_SPEED_NDR;
0597 break;
0598 }
0599 }
0600
0601
0602 if (props->active_speed == 4) {
0603 if (dev->port_caps[port - 1].ext_port_cap &
0604 MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
0605 ib_init_query_mad(in_mad);
0606 in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO;
0607 in_mad->attr_mod = cpu_to_be32(port);
0608
0609 err = mlx5_MAD_IFC(dev, 1, 1, port,
0610 NULL, NULL, in_mad, out_mad);
0611 if (err)
0612 goto out;
0613
0614
0615 if (out_mad->data[15] & 0x1)
0616 props->active_speed = 8;
0617 }
0618 }
0619
0620 out:
0621 kfree(in_mad);
0622 kfree(out_mad);
0623
0624 return err;
0625 }