aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/verbs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/core/verbs.c')
-rw-r--r--drivers/infiniband/core/verbs.c295
1 files changed, 202 insertions, 93 deletions
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index e1f2c9887f3f..043a60ee6836 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -41,6 +41,9 @@
41#include <linux/export.h> 41#include <linux/export.h>
42#include <linux/string.h> 42#include <linux/string.h>
43#include <linux/slab.h> 43#include <linux/slab.h>
44#include <linux/in.h>
45#include <linux/in6.h>
46#include <net/addrconf.h>
44 47
45#include <rdma/ib_verbs.h> 48#include <rdma/ib_verbs.h>
46#include <rdma/ib_cache.h> 49#include <rdma/ib_cache.h>
@@ -70,7 +73,7 @@ static const char * const ib_events[] = {
70 [IB_EVENT_GID_CHANGE] = "GID changed", 73 [IB_EVENT_GID_CHANGE] = "GID changed",
71}; 74};
72 75
73const char *ib_event_msg(enum ib_event_type event) 76const char *__attribute_const__ ib_event_msg(enum ib_event_type event)
74{ 77{
75 size_t index = event; 78 size_t index = event;
76 79
@@ -104,7 +107,7 @@ static const char * const wc_statuses[] = {
104 [IB_WC_GENERAL_ERR] = "general error", 107 [IB_WC_GENERAL_ERR] = "general error",
105}; 108};
106 109
107const char *ib_wc_status_msg(enum ib_wc_status status) 110const char *__attribute_const__ ib_wc_status_msg(enum ib_wc_status status)
108{ 111{
109 size_t index = status; 112 size_t index = status;
110 113
@@ -308,6 +311,35 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
308} 311}
309EXPORT_SYMBOL(ib_create_ah); 312EXPORT_SYMBOL(ib_create_ah);
310 313
314struct find_gid_index_context {
315 u16 vlan_id;
316};
317
318static bool find_gid_index(const union ib_gid *gid,
319 const struct ib_gid_attr *gid_attr,
320 void *context)
321{
322 struct find_gid_index_context *ctx =
323 (struct find_gid_index_context *)context;
324
325 if ((!!(ctx->vlan_id != 0xffff) == !is_vlan_dev(gid_attr->ndev)) ||
326 (is_vlan_dev(gid_attr->ndev) &&
327 vlan_dev_vlan_id(gid_attr->ndev) != ctx->vlan_id))
328 return false;
329
330 return true;
331}
332
333static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
334 u16 vlan_id, const union ib_gid *sgid,
335 u16 *gid_index)
336{
337 struct find_gid_index_context context = {.vlan_id = vlan_id};
338
339 return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index,
340 &context, gid_index);
341}
342
311int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, 343int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
312 const struct ib_wc *wc, const struct ib_grh *grh, 344 const struct ib_wc *wc, const struct ib_grh *grh,
313 struct ib_ah_attr *ah_attr) 345 struct ib_ah_attr *ah_attr)
@@ -318,21 +350,30 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
318 350
319 memset(ah_attr, 0, sizeof *ah_attr); 351 memset(ah_attr, 0, sizeof *ah_attr);
320 if (rdma_cap_eth_ah(device, port_num)) { 352 if (rdma_cap_eth_ah(device, port_num)) {
353 u16 vlan_id = wc->wc_flags & IB_WC_WITH_VLAN ?
354 wc->vlan_id : 0xffff;
355
321 if (!(wc->wc_flags & IB_WC_GRH)) 356 if (!(wc->wc_flags & IB_WC_GRH))
322 return -EPROTOTYPE; 357 return -EPROTOTYPE;
323 358
324 if (wc->wc_flags & IB_WC_WITH_SMAC && 359 if (!(wc->wc_flags & IB_WC_WITH_SMAC) ||
325 wc->wc_flags & IB_WC_WITH_VLAN) { 360 !(wc->wc_flags & IB_WC_WITH_VLAN)) {
326 memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
327 ah_attr->vlan_id = wc->vlan_id;
328 } else {
329 ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid, 361 ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
330 ah_attr->dmac, &ah_attr->vlan_id); 362 ah_attr->dmac,
363 wc->wc_flags & IB_WC_WITH_VLAN ?
364 NULL : &vlan_id,
365 0);
331 if (ret) 366 if (ret)
332 return ret; 367 return ret;
333 } 368 }
334 } else { 369
335 ah_attr->vlan_id = 0xffff; 370 ret = get_sgid_index_from_eth(device, port_num, vlan_id,
371 &grh->dgid, &gid_index);
372 if (ret)
373 return ret;
374
375 if (wc->wc_flags & IB_WC_WITH_SMAC)
376 memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
336 } 377 }
337 378
338 ah_attr->dlid = wc->slid; 379 ah_attr->dlid = wc->slid;
@@ -344,10 +385,13 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
344 ah_attr->ah_flags = IB_AH_GRH; 385 ah_attr->ah_flags = IB_AH_GRH;
345 ah_attr->grh.dgid = grh->sgid; 386 ah_attr->grh.dgid = grh->sgid;
346 387
347 ret = ib_find_cached_gid(device, &grh->dgid, &port_num, 388 if (!rdma_cap_eth_ah(device, port_num)) {
348 &gid_index); 389 ret = ib_find_cached_gid_by_port(device, &grh->dgid,
349 if (ret) 390 port_num, NULL,
350 return ret; 391 &gid_index);
392 if (ret)
393 return ret;
394 }
351 395
352 ah_attr->grh.sgid_index = (u8) gid_index; 396 ah_attr->grh.sgid_index = (u8) gid_index;
353 flow_class = be32_to_cpu(grh->version_tclass_flow); 397 flow_class = be32_to_cpu(grh->version_tclass_flow);
@@ -617,9 +661,7 @@ EXPORT_SYMBOL(ib_create_qp);
617static const struct { 661static const struct {
618 int valid; 662 int valid;
619 enum ib_qp_attr_mask req_param[IB_QPT_MAX]; 663 enum ib_qp_attr_mask req_param[IB_QPT_MAX];
620 enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX];
621 enum ib_qp_attr_mask opt_param[IB_QPT_MAX]; 664 enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
622 enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX];
623} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { 665} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
624 [IB_QPS_RESET] = { 666 [IB_QPS_RESET] = {
625 [IB_QPS_RESET] = { .valid = 1 }, 667 [IB_QPS_RESET] = { .valid = 1 },
@@ -700,12 +742,6 @@ static const struct {
700 IB_QP_MAX_DEST_RD_ATOMIC | 742 IB_QP_MAX_DEST_RD_ATOMIC |
701 IB_QP_MIN_RNR_TIMER), 743 IB_QP_MIN_RNR_TIMER),
702 }, 744 },
703 .req_param_add_eth = {
704 [IB_QPT_RC] = (IB_QP_SMAC),
705 [IB_QPT_UC] = (IB_QP_SMAC),
706 [IB_QPT_XRC_INI] = (IB_QP_SMAC),
707 [IB_QPT_XRC_TGT] = (IB_QP_SMAC)
708 },
709 .opt_param = { 745 .opt_param = {
710 [IB_QPT_UD] = (IB_QP_PKEY_INDEX | 746 [IB_QPT_UD] = (IB_QP_PKEY_INDEX |
711 IB_QP_QKEY), 747 IB_QP_QKEY),
@@ -726,21 +762,7 @@ static const struct {
726 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX | 762 [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
727 IB_QP_QKEY), 763 IB_QP_QKEY),
728 }, 764 },
729 .opt_param_add_eth = { 765 },
730 [IB_QPT_RC] = (IB_QP_ALT_SMAC |
731 IB_QP_VID |
732 IB_QP_ALT_VID),
733 [IB_QPT_UC] = (IB_QP_ALT_SMAC |
734 IB_QP_VID |
735 IB_QP_ALT_VID),
736 [IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC |
737 IB_QP_VID |
738 IB_QP_ALT_VID),
739 [IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC |
740 IB_QP_VID |
741 IB_QP_ALT_VID)
742 }
743 }
744 }, 766 },
745 [IB_QPS_RTR] = { 767 [IB_QPS_RTR] = {
746 [IB_QPS_RESET] = { .valid = 1 }, 768 [IB_QPS_RESET] = { .valid = 1 },
@@ -962,13 +984,6 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
962 req_param = qp_state_table[cur_state][next_state].req_param[type]; 984 req_param = qp_state_table[cur_state][next_state].req_param[type];
963 opt_param = qp_state_table[cur_state][next_state].opt_param[type]; 985 opt_param = qp_state_table[cur_state][next_state].opt_param[type];
964 986
965 if (ll == IB_LINK_LAYER_ETHERNET) {
966 req_param |= qp_state_table[cur_state][next_state].
967 req_param_add_eth[type];
968 opt_param |= qp_state_table[cur_state][next_state].
969 opt_param_add_eth[type];
970 }
971
972 if ((mask & req_param) != req_param) 987 if ((mask & req_param) != req_param)
973 return 0; 988 return 0;
974 989
@@ -979,40 +994,52 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
979} 994}
980EXPORT_SYMBOL(ib_modify_qp_is_ok); 995EXPORT_SYMBOL(ib_modify_qp_is_ok);
981 996
982int ib_resolve_eth_l2_attrs(struct ib_qp *qp, 997int ib_resolve_eth_dmac(struct ib_qp *qp,
983 struct ib_qp_attr *qp_attr, int *qp_attr_mask) 998 struct ib_qp_attr *qp_attr, int *qp_attr_mask)
984{ 999{
985 int ret = 0; 1000 int ret = 0;
986 union ib_gid sgid;
987 1001
988 if ((*qp_attr_mask & IB_QP_AV) && 1002 if (*qp_attr_mask & IB_QP_AV) {
989 (rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) { 1003 if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) ||
990 ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, 1004 qp_attr->ah_attr.port_num > rdma_end_port(qp->device))
991 qp_attr->ah_attr.grh.sgid_index, &sgid); 1005 return -EINVAL;
992 if (ret) 1006
993 goto out; 1007 if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))
1008 return 0;
1009
994 if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) { 1010 if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
995 rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac); 1011 rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw,
996 rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac); 1012 qp_attr->ah_attr.dmac);
997 if (!(*qp_attr_mask & IB_QP_VID))
998 qp_attr->vlan_id = rdma_get_vlan_id(&sgid);
999 } else { 1013 } else {
1000 ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid, 1014 union ib_gid sgid;
1001 qp_attr->ah_attr.dmac, &qp_attr->vlan_id); 1015 struct ib_gid_attr sgid_attr;
1002 if (ret) 1016 int ifindex;
1003 goto out; 1017
1004 ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL); 1018 ret = ib_query_gid(qp->device,
1005 if (ret) 1019 qp_attr->ah_attr.port_num,
1020 qp_attr->ah_attr.grh.sgid_index,
1021 &sgid, &sgid_attr);
1022
1023 if (ret || !sgid_attr.ndev) {
1024 if (!ret)
1025 ret = -ENXIO;
1006 goto out; 1026 goto out;
1027 }
1028
1029 ifindex = sgid_attr.ndev->ifindex;
1030
1031 ret = rdma_addr_find_dmac_by_grh(&sgid,
1032 &qp_attr->ah_attr.grh.dgid,
1033 qp_attr->ah_attr.dmac,
1034 NULL, ifindex);
1035
1036 dev_put(sgid_attr.ndev);
1007 } 1037 }
1008 *qp_attr_mask |= IB_QP_SMAC;
1009 if (qp_attr->vlan_id < 0xFFFF)
1010 *qp_attr_mask |= IB_QP_VID;
1011 } 1038 }
1012out: 1039out:
1013 return ret; 1040 return ret;
1014} 1041}
1015EXPORT_SYMBOL(ib_resolve_eth_l2_attrs); 1042EXPORT_SYMBOL(ib_resolve_eth_dmac);
1016 1043
1017 1044
1018int ib_modify_qp(struct ib_qp *qp, 1045int ib_modify_qp(struct ib_qp *qp,
@@ -1021,7 +1048,7 @@ int ib_modify_qp(struct ib_qp *qp,
1021{ 1048{
1022 int ret; 1049 int ret;
1023 1050
1024 ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask); 1051 ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask);
1025 if (ret) 1052 if (ret)
1026 return ret; 1053 return ret;
1027 1054
@@ -1253,31 +1280,6 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *pd,
1253} 1280}
1254EXPORT_SYMBOL(ib_alloc_mr); 1281EXPORT_SYMBOL(ib_alloc_mr);
1255 1282
1256struct ib_fast_reg_page_list *ib_alloc_fast_reg_page_list(struct ib_device *device,
1257 int max_page_list_len)
1258{
1259 struct ib_fast_reg_page_list *page_list;
1260
1261 if (!device->alloc_fast_reg_page_list)
1262 return ERR_PTR(-ENOSYS);
1263
1264 page_list = device->alloc_fast_reg_page_list(device, max_page_list_len);
1265
1266 if (!IS_ERR(page_list)) {
1267 page_list->device = device;
1268 page_list->max_page_list_len = max_page_list_len;
1269 }
1270
1271 return page_list;
1272}
1273EXPORT_SYMBOL(ib_alloc_fast_reg_page_list);
1274
1275void ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list)
1276{
1277 page_list->device->free_fast_reg_page_list(page_list);
1278}
1279EXPORT_SYMBOL(ib_free_fast_reg_page_list);
1280
1281/* Memory windows */ 1283/* Memory windows */
1282 1284
1283struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type) 1285struct ib_mw *ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type)
@@ -1469,3 +1471,110 @@ int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
1469 mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS; 1471 mr->device->check_mr_status(mr, check_mask, mr_status) : -ENOSYS;
1470} 1472}
1471EXPORT_SYMBOL(ib_check_mr_status); 1473EXPORT_SYMBOL(ib_check_mr_status);
1474
1475/**
1476 * ib_map_mr_sg() - Map the largest prefix of a dma mapped SG list
1477 * and set it the memory region.
1478 * @mr: memory region
1479 * @sg: dma mapped scatterlist
1480 * @sg_nents: number of entries in sg
1481 * @page_size: page vector desired page size
1482 *
1483 * Constraints:
1484 * - The first sg element is allowed to have an offset.
1485 * - Each sg element must be aligned to page_size (or physically
1486 * contiguous to the previous element). In case an sg element has a
1487 * non contiguous offset, the mapping prefix will not include it.
1488 * - The last sg element is allowed to have length less than page_size.
1489 * - If sg_nents total byte length exceeds the mr max_num_sge * page_size
1490 * then only max_num_sg entries will be mapped.
1491 *
1492 * Returns the number of sg elements that were mapped to the memory region.
1493 *
1494 * After this completes successfully, the memory region
1495 * is ready for registration.
1496 */
1497int ib_map_mr_sg(struct ib_mr *mr,
1498 struct scatterlist *sg,
1499 int sg_nents,
1500 unsigned int page_size)
1501{
1502 if (unlikely(!mr->device->map_mr_sg))
1503 return -ENOSYS;
1504
1505 mr->page_size = page_size;
1506
1507 return mr->device->map_mr_sg(mr, sg, sg_nents);
1508}
1509EXPORT_SYMBOL(ib_map_mr_sg);
1510
1511/**
1512 * ib_sg_to_pages() - Convert the largest prefix of a sg list
1513 * to a page vector
1514 * @mr: memory region
1515 * @sgl: dma mapped scatterlist
1516 * @sg_nents: number of entries in sg
1517 * @set_page: driver page assignment function pointer
1518 *
1519 * Core service helper for drivers to covert the largest
1520 * prefix of given sg list to a page vector. The sg list
1521 * prefix converted is the prefix that meet the requirements
1522 * of ib_map_mr_sg.
1523 *
1524 * Returns the number of sg elements that were assigned to
1525 * a page vector.
1526 */
1527int ib_sg_to_pages(struct ib_mr *mr,
1528 struct scatterlist *sgl,
1529 int sg_nents,
1530 int (*set_page)(struct ib_mr *, u64))
1531{
1532 struct scatterlist *sg;
1533 u64 last_end_dma_addr = 0, last_page_addr = 0;
1534 unsigned int last_page_off = 0;
1535 u64 page_mask = ~((u64)mr->page_size - 1);
1536 int i;
1537
1538 mr->iova = sg_dma_address(&sgl[0]);
1539 mr->length = 0;
1540
1541 for_each_sg(sgl, sg, sg_nents, i) {
1542 u64 dma_addr = sg_dma_address(sg);
1543 unsigned int dma_len = sg_dma_len(sg);
1544 u64 end_dma_addr = dma_addr + dma_len;
1545 u64 page_addr = dma_addr & page_mask;
1546
1547 if (i && page_addr != dma_addr) {
1548 if (last_end_dma_addr != dma_addr) {
1549 /* gap */
1550 goto done;
1551
1552 } else if (last_page_off + dma_len <= mr->page_size) {
1553 /* chunk this fragment with the last */
1554 mr->length += dma_len;
1555 last_end_dma_addr += dma_len;
1556 last_page_off += dma_len;
1557 continue;
1558 } else {
1559 /* map starting from the next page */
1560 page_addr = last_page_addr + mr->page_size;
1561 dma_len -= mr->page_size - last_page_off;
1562 }
1563 }
1564
1565 do {
1566 if (unlikely(set_page(mr, page_addr)))
1567 goto done;
1568 page_addr += mr->page_size;
1569 } while (page_addr < end_dma_addr);
1570
1571 mr->length += dma_len;
1572 last_end_dma_addr = end_dma_addr;
1573 last_page_addr = end_dma_addr & page_mask;
1574 last_page_off = end_dma_addr & ~page_mask;
1575 }
1576
1577done:
1578 return i;
1579}
1580EXPORT_SYMBOL(ib_sg_to_pages);