aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>2017-04-27 19:06:02 -0400
committerDoug Ledford <dledford@redhat.com>2017-05-01 14:39:02 -0400
commit4c33bd1926ccbfad362d22208c23cc045c5c82af (patch)
tree1ef1b624919d61e743d19b4950abb5bf65db2fb4
parent57520751445b837c20a8e658e3dae3a7e7ddf45c (diff)
IB/SA: Add support to query OPA path records
When the bit 26 of capmask2 field in OPA classport info query is set, SA will query for OPA path records instead of querying for IB path records. Note that OPA path records can only be queried by kernel ULPs. Userspace clients continue to query IB path records. Reviewed-by: Don Hiatt <don.hiatt@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/core/cma.c6
-rw-r--r--drivers/infiniband/core/sa_query.c274
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c5
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c6
-rw-r--r--include/rdma/ib_mad.h13
5 files changed, 285 insertions, 19 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 653e0051d328..91b7a2fe5a55 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2335,7 +2335,11 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
2335 struct sockaddr_ib *sib; 2335 struct sockaddr_ib *sib;
2336 2336
2337 memset(&path_rec, 0, sizeof path_rec); 2337 memset(&path_rec, 0, sizeof path_rec);
2338 path_rec.rec_type = SA_PATH_REC_TYPE_IB; 2338
2339 if (rdma_cap_opa_ah(id_priv->id.device, id_priv->id.port_num))
2340 path_rec.rec_type = SA_PATH_REC_TYPE_OPA;
2341 else
2342 path_rec.rec_type = SA_PATH_REC_TYPE_IB;
2339 rdma_addr_get_sgid(dev_addr, &path_rec.sgid); 2343 rdma_addr_get_sgid(dev_addr, &path_rec.sgid);
2340 rdma_addr_get_dgid(dev_addr, &path_rec.dgid); 2344 rdma_addr_get_dgid(dev_addr, &path_rec.dgid);
2341 path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); 2345 path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 249247609b60..e335b09c022e 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -132,6 +132,7 @@ struct ib_sa_path_query {
132 void (*callback)(int, struct sa_path_rec *, void *); 132 void (*callback)(int, struct sa_path_rec *, void *);
133 void *context; 133 void *context;
134 struct ib_sa_query sa_query; 134 struct ib_sa_query sa_query;
135 struct sa_path_rec *conv_pr;
135}; 136};
136 137
137struct ib_sa_guidinfo_query { 138struct ib_sa_guidinfo_query {
@@ -287,6 +288,136 @@ static const struct ib_field path_rec_table[] = {
287 .size_bits = 48 }, 288 .size_bits = 48 },
288}; 289};
289 290
291#define OPA_PATH_REC_FIELD(field) \
292 .struct_offset_bytes = \
293 offsetof(struct sa_path_rec, field), \
294 .struct_size_bytes = \
295 sizeof((struct sa_path_rec *)0)->field, \
296 .field_name = "sa_path_rec:" #field
297
298static const struct ib_field opa_path_rec_table[] = {
299 { OPA_PATH_REC_FIELD(opa.service_id),
300 .offset_words = 0,
301 .offset_bits = 0,
302 .size_bits = 64 },
303 { OPA_PATH_REC_FIELD(dgid),
304 .offset_words = 2,
305 .offset_bits = 0,
306 .size_bits = 128 },
307 { OPA_PATH_REC_FIELD(sgid),
308 .offset_words = 6,
309 .offset_bits = 0,
310 .size_bits = 128 },
311 { OPA_PATH_REC_FIELD(opa.dlid),
312 .offset_words = 10,
313 .offset_bits = 0,
314 .size_bits = 32 },
315 { OPA_PATH_REC_FIELD(opa.slid),
316 .offset_words = 11,
317 .offset_bits = 0,
318 .size_bits = 32 },
319 { OPA_PATH_REC_FIELD(opa.raw_traffic),
320 .offset_words = 12,
321 .offset_bits = 0,
322 .size_bits = 1 },
323 { RESERVED,
324 .offset_words = 12,
325 .offset_bits = 1,
326 .size_bits = 3 },
327 { OPA_PATH_REC_FIELD(flow_label),
328 .offset_words = 12,
329 .offset_bits = 4,
330 .size_bits = 20 },
331 { OPA_PATH_REC_FIELD(hop_limit),
332 .offset_words = 12,
333 .offset_bits = 24,
334 .size_bits = 8 },
335 { OPA_PATH_REC_FIELD(traffic_class),
336 .offset_words = 13,
337 .offset_bits = 0,
338 .size_bits = 8 },
339 { OPA_PATH_REC_FIELD(reversible),
340 .offset_words = 13,
341 .offset_bits = 8,
342 .size_bits = 1 },
343 { OPA_PATH_REC_FIELD(numb_path),
344 .offset_words = 13,
345 .offset_bits = 9,
346 .size_bits = 7 },
347 { OPA_PATH_REC_FIELD(pkey),
348 .offset_words = 13,
349 .offset_bits = 16,
350 .size_bits = 16 },
351 { OPA_PATH_REC_FIELD(opa.l2_8B),
352 .offset_words = 14,
353 .offset_bits = 0,
354 .size_bits = 1 },
355 { OPA_PATH_REC_FIELD(opa.l2_10B),
356 .offset_words = 14,
357 .offset_bits = 1,
358 .size_bits = 1 },
359 { OPA_PATH_REC_FIELD(opa.l2_9B),
360 .offset_words = 14,
361 .offset_bits = 2,
362 .size_bits = 1 },
363 { OPA_PATH_REC_FIELD(opa.l2_16B),
364 .offset_words = 14,
365 .offset_bits = 3,
366 .size_bits = 1 },
367 { RESERVED,
368 .offset_words = 14,
369 .offset_bits = 4,
370 .size_bits = 2 },
371 { OPA_PATH_REC_FIELD(opa.qos_type),
372 .offset_words = 14,
373 .offset_bits = 6,
374 .size_bits = 2 },
375 { OPA_PATH_REC_FIELD(opa.qos_priority),
376 .offset_words = 14,
377 .offset_bits = 8,
378 .size_bits = 8 },
379 { RESERVED,
380 .offset_words = 14,
381 .offset_bits = 16,
382 .size_bits = 3 },
383 { OPA_PATH_REC_FIELD(sl),
384 .offset_words = 14,
385 .offset_bits = 19,
386 .size_bits = 5 },
387 { RESERVED,
388 .offset_words = 14,
389 .offset_bits = 24,
390 .size_bits = 8 },
391 { OPA_PATH_REC_FIELD(mtu_selector),
392 .offset_words = 15,
393 .offset_bits = 0,
394 .size_bits = 2 },
395 { OPA_PATH_REC_FIELD(mtu),
396 .offset_words = 15,
397 .offset_bits = 2,
398 .size_bits = 6 },
399 { OPA_PATH_REC_FIELD(rate_selector),
400 .offset_words = 15,
401 .offset_bits = 8,
402 .size_bits = 2 },
403 { OPA_PATH_REC_FIELD(rate),
404 .offset_words = 15,
405 .offset_bits = 10,
406 .size_bits = 6 },
407 { OPA_PATH_REC_FIELD(packet_life_time_selector),
408 .offset_words = 15,
409 .offset_bits = 16,
410 .size_bits = 2 },
411 { OPA_PATH_REC_FIELD(packet_life_time),
412 .offset_words = 15,
413 .offset_bits = 18,
414 .size_bits = 6 },
415 { OPA_PATH_REC_FIELD(preference),
416 .offset_words = 15,
417 .offset_bits = 24,
418 .size_bits = 8 },
419};
420
290#define MCMEMBER_REC_FIELD(field) \ 421#define MCMEMBER_REC_FIELD(field) \
291 .struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field), \ 422 .struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field), \
292 .struct_size_bytes = sizeof ((struct ib_sa_mcmember_rec *) 0)->field, \ 423 .struct_size_bytes = sizeof ((struct ib_sa_mcmember_rec *) 0)->field, \
@@ -1288,7 +1419,8 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
1288 query->mad_buf->context[0] = query; 1419 query->mad_buf->context[0] = query;
1289 query->id = id; 1420 query->id = id;
1290 1421
1291 if (query->flags & IB_SA_ENABLE_LOCAL_SERVICE) { 1422 if ((query->flags & IB_SA_ENABLE_LOCAL_SERVICE) &&
1423 (!(query->flags & IB_SA_QUERY_OPA))) {
1292 if (!ibnl_chk_listeners(RDMA_NL_GROUP_LS)) { 1424 if (!ibnl_chk_listeners(RDMA_NL_GROUP_LS)) {
1293 if (!ib_nl_make_request(query, gfp_mask)) 1425 if (!ib_nl_make_request(query, gfp_mask))
1294 return id; 1426 return id;
@@ -1323,6 +1455,63 @@ void ib_sa_pack_path(struct sa_path_rec *rec, void *attribute)
1323} 1455}
1324EXPORT_SYMBOL(ib_sa_pack_path); 1456EXPORT_SYMBOL(ib_sa_pack_path);
1325 1457
1458static bool ib_sa_opa_pathrecord_support(struct ib_sa_client *client,
1459 struct ib_device *device,
1460 u8 port_num)
1461{
1462 struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
1463 struct ib_sa_port *port;
1464 unsigned long flags;
1465 bool ret = false;
1466
1467 if (!sa_dev)
1468 return ret;
1469
1470 port = &sa_dev->port[port_num - sa_dev->start_port];
1471 spin_lock_irqsave(&port->classport_lock, flags);
1472 if (!port->classport_info.valid)
1473 goto ret;
1474
1475 if (port->classport_info.data.type == RDMA_CLASS_PORT_INFO_OPA)
1476 ret = opa_get_cpi_capmask2(&port->classport_info.data.opa) &
1477 OPA_CLASS_PORT_INFO_PR_SUPPORT;
1478ret:
1479 spin_unlock_irqrestore(&port->classport_lock, flags);
1480 return ret;
1481}
1482
1483enum opa_pr_supported {
1484 PR_NOT_SUPPORTED,
1485 PR_OPA_SUPPORTED,
1486 PR_IB_SUPPORTED
1487};
1488
1489/**
1490 * Check if current PR query can be an OPA query.
1491 * Retuns PR_NOT_SUPPORTED if a path record query is not
1492 * possible, PR_OPA_SUPPORTED if an OPA path record query
1493 * is possible and PR_IB_SUPPORTED if an IB path record
1494 * query is possible.
1495 */
1496static int opa_pr_query_possible(struct ib_sa_client *client,
1497 struct ib_device *device,
1498 u8 port_num,
1499 struct sa_path_rec *rec)
1500{
1501 struct ib_port_attr port_attr;
1502
1503 if (ib_query_port(device, port_num, &port_attr))
1504 return PR_NOT_SUPPORTED;
1505
1506 if (ib_sa_opa_pathrecord_support(client, device, port_num))
1507 return PR_OPA_SUPPORTED;
1508
1509 if (port_attr.lid >= be16_to_cpu(IB_MULTICAST_LID_BASE))
1510 return PR_NOT_SUPPORTED;
1511 else
1512 return PR_IB_SUPPORTED;
1513}
1514
1326static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, 1515static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
1327 int status, 1516 int status,
1328 struct ib_sa_mad *mad) 1517 struct ib_sa_mad *mad)
@@ -1333,20 +1522,42 @@ static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
1333 if (mad) { 1522 if (mad) {
1334 struct sa_path_rec rec; 1523 struct sa_path_rec rec;
1335 1524
1336 ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), 1525 if (sa_query->flags & IB_SA_QUERY_OPA) {
1337 mad->data, &rec); 1526 ib_unpack(opa_path_rec_table,
1338 rec.rec_type = SA_PATH_REC_TYPE_IB; 1527 ARRAY_SIZE(opa_path_rec_table),
1339 sa_path_set_ndev(&rec, NULL); 1528 mad->data, &rec);
1340 sa_path_set_ifindex(&rec, 0); 1529 rec.rec_type = SA_PATH_REC_TYPE_OPA;
1341 sa_path_set_dmac_zero(&rec); 1530 query->callback(status, &rec, query->context);
1342 query->callback(status, &rec, query->context); 1531 } else {
1532 ib_unpack(path_rec_table,
1533 ARRAY_SIZE(path_rec_table),
1534 mad->data, &rec);
1535 rec.rec_type = SA_PATH_REC_TYPE_IB;
1536 sa_path_set_ndev(&rec, NULL);
1537 sa_path_set_ifindex(&rec, 0);
1538 sa_path_set_dmac_zero(&rec);
1539
1540 if (query->conv_pr) {
1541 struct sa_path_rec opa;
1542
1543 memset(&opa, 0, sizeof(struct sa_path_rec));
1544 sa_convert_path_ib_to_opa(&opa, &rec);
1545 query->callback(status, &opa, query->context);
1546 } else {
1547 query->callback(status, &rec, query->context);
1548 }
1549 }
1343 } else 1550 } else
1344 query->callback(status, NULL, query->context); 1551 query->callback(status, NULL, query->context);
1345} 1552}
1346 1553
1347static void ib_sa_path_rec_release(struct ib_sa_query *sa_query) 1554static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
1348{ 1555{
1349 kfree(container_of(sa_query, struct ib_sa_path_query, sa_query)); 1556 struct ib_sa_path_query *query =
1557 container_of(sa_query, struct ib_sa_path_query, sa_query);
1558
1559 kfree(query->conv_pr);
1560 kfree(query);
1350} 1561}
1351 1562
1352/** 1563/**
@@ -1390,12 +1601,14 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
1390 struct ib_sa_port *port; 1601 struct ib_sa_port *port;
1391 struct ib_mad_agent *agent; 1602 struct ib_mad_agent *agent;
1392 struct ib_sa_mad *mad; 1603 struct ib_sa_mad *mad;
1604 enum opa_pr_supported status;
1393 int ret; 1605 int ret;
1394 1606
1395 if (!sa_dev) 1607 if (!sa_dev)
1396 return -ENODEV; 1608 return -ENODEV;
1397 1609
1398 if (rec->rec_type != SA_PATH_REC_TYPE_IB) 1610 if ((rec->rec_type != SA_PATH_REC_TYPE_IB) &&
1611 (rec->rec_type != SA_PATH_REC_TYPE_OPA))
1399 return -EINVAL; 1612 return -EINVAL;
1400 1613
1401 port = &sa_dev->port[port_num - sa_dev->start_port]; 1614 port = &sa_dev->port[port_num - sa_dev->start_port];
@@ -1406,9 +1619,26 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
1406 return -ENOMEM; 1619 return -ENOMEM;
1407 1620
1408 query->sa_query.port = port; 1621 query->sa_query.port = port;
1622 if (rec->rec_type == SA_PATH_REC_TYPE_OPA) {
1623 status = opa_pr_query_possible(client, device, port_num, rec);
1624 if (status == PR_NOT_SUPPORTED) {
1625 ret = -EINVAL;
1626 goto err1;
1627 } else if (status == PR_OPA_SUPPORTED) {
1628 query->sa_query.flags |= IB_SA_QUERY_OPA;
1629 } else {
1630 query->conv_pr =
1631 kmalloc(sizeof(*query->conv_pr), gfp_mask);
1632 if (!query->conv_pr) {
1633 ret = -ENOMEM;
1634 goto err1;
1635 }
1636 }
1637 }
1638
1409 ret = alloc_mad(&query->sa_query, gfp_mask); 1639 ret = alloc_mad(&query->sa_query, gfp_mask);
1410 if (ret) 1640 if (ret)
1411 goto err1; 1641 goto err2;
1412 1642
1413 ib_sa_client_get(client); 1643 ib_sa_client_get(client);
1414 query->sa_query.client = client; 1644 query->sa_query.client = client;
@@ -1424,24 +1654,36 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
1424 mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC); 1654 mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC);
1425 mad->sa_hdr.comp_mask = comp_mask; 1655 mad->sa_hdr.comp_mask = comp_mask;
1426 1656
1427 ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data); 1657 if (query->sa_query.flags & IB_SA_QUERY_OPA) {
1658 ib_pack(opa_path_rec_table, ARRAY_SIZE(opa_path_rec_table),
1659 rec, mad->data);
1660 } else if (query->conv_pr) {
1661 sa_convert_path_opa_to_ib(query->conv_pr, rec);
1662 ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),
1663 query->conv_pr, mad->data);
1664 } else {
1665 ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table),
1666 rec, mad->data);
1667 }
1428 1668
1429 *sa_query = &query->sa_query; 1669 *sa_query = &query->sa_query;
1430 1670
1431 query->sa_query.flags |= IB_SA_ENABLE_LOCAL_SERVICE; 1671 query->sa_query.flags |= IB_SA_ENABLE_LOCAL_SERVICE;
1432 query->sa_query.mad_buf->context[1] = rec; 1672 query->sa_query.mad_buf->context[1] = (query->conv_pr) ?
1673 query->conv_pr : rec;
1433 1674
1434 ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); 1675 ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
1435 if (ret < 0) 1676 if (ret < 0)
1436 goto err2; 1677 goto err3;
1437 1678
1438 return ret; 1679 return ret;
1439 1680
1440err2: 1681err3:
1441 *sa_query = NULL; 1682 *sa_query = NULL;
1442 ib_sa_client_put(query->sa_query.client); 1683 ib_sa_client_put(query->sa_query.client);
1443 free_mad(&query->sa_query); 1684 free_mad(&query->sa_query);
1444 1685err2:
1686 kfree(query->conv_pr);
1445err1: 1687err1:
1446 kfree(query); 1688 kfree(query);
1447 return ret; 1689 return ret;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2aab637f9d0a..2869d1adb1de 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -832,7 +832,10 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
832 832
833 INIT_LIST_HEAD(&path->neigh_list); 833 INIT_LIST_HEAD(&path->neigh_list);
834 834
835 path->pathrec.rec_type = SA_PATH_REC_TYPE_IB; 835 if (rdma_cap_opa_ah(priv->ca, priv->port))
836 path->pathrec.rec_type = SA_PATH_REC_TYPE_OPA;
837 else
838 path->pathrec.rec_type = SA_PATH_REC_TYPE_IB;
836 memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid)); 839 memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid));
837 path->pathrec.sgid = priv->local_gid; 840 path->pathrec.sgid = priv->local_gid;
838 path->pathrec.pkey = cpu_to_be16(priv->pkey); 841 path->pathrec.pkey = cpu_to_be16(priv->pkey);
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 07877a88475d..def723a5df29 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -312,7 +312,11 @@ static int srp_new_cm_id(struct srp_rdma_ch *ch)
312 if (ch->cm_id) 312 if (ch->cm_id)
313 ib_destroy_cm_id(ch->cm_id); 313 ib_destroy_cm_id(ch->cm_id);
314 ch->cm_id = new_cm_id; 314 ch->cm_id = new_cm_id;
315 ch->path.rec_type = SA_PATH_REC_TYPE_IB; 315 if (rdma_cap_opa_ah(target->srp_host->srp_dev->dev,
316 target->srp_host->port))
317 ch->path.rec_type = SA_PATH_REC_TYPE_OPA;
318 else
319 ch->path.rec_type = SA_PATH_REC_TYPE_IB;
316 ch->path.sgid = target->sgid; 320 ch->path.sgid = target->sgid;
317 ch->path.dgid = target->orig_dgid; 321 ch->path.dgid = target->orig_dgid;
318 ch->path.pkey = target->pkey; 322 ch->path.pkey = target->pkey;
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 3d5f5d6031ec..d67b11b72029 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -262,6 +262,8 @@ struct ib_class_port_info {
262 __be32 trap_qkey; 262 __be32 trap_qkey;
263}; 263};
264 264
265#define OPA_CLASS_PORT_INFO_PR_SUPPORT BIT(26)
266
265struct opa_class_port_info { 267struct opa_class_port_info {
266 u8 base_version; 268 u8 base_version;
267 u8 class_version; 269 u8 class_version;
@@ -340,6 +342,17 @@ static inline void ib_set_cpi_capmask2(struct ib_class_port_info *cpi,
340 IB_CLASS_PORT_INFO_RESP_TIME_FIELD_SIZE); 342 IB_CLASS_PORT_INFO_RESP_TIME_FIELD_SIZE);
341} 343}
342 344
345/**
346 * opa_get_cpi_capmask2 - Returns the capmask2 value from
347 * cap_mask2_resp_time in ib_class_port_info.
348 * @cpi: A struct opa_class_port_info mad.
349 */
350static inline u32 opa_get_cpi_capmask2(struct opa_class_port_info *cpi)
351{
352 return (be32_to_cpu(cpi->cap_mask2_resp_time) >>
353 IB_CLASS_PORT_INFO_RESP_TIME_FIELD_SIZE);
354}
355
343struct ib_mad_notice_attr { 356struct ib_mad_notice_attr {
344 u8 generic_type; 357 u8 generic_type;
345 u8 prod_type_msb; 358 u8 prod_type_msb;