diff options
Diffstat (limited to 'net/sunrpc/xprtrdma/verbs.c')
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 5f4c7b3bc711..80f8da344df5 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -144,6 +144,7 @@ rpcrdma_cq_async_error_upcall(struct ib_event *event, void *context) | |||
144 | static inline | 144 | static inline |
145 | void rpcrdma_event_process(struct ib_wc *wc) | 145 | void rpcrdma_event_process(struct ib_wc *wc) |
146 | { | 146 | { |
147 | struct rpcrdma_mw *frmr; | ||
147 | struct rpcrdma_rep *rep = | 148 | struct rpcrdma_rep *rep = |
148 | (struct rpcrdma_rep *)(unsigned long) wc->wr_id; | 149 | (struct rpcrdma_rep *)(unsigned long) wc->wr_id; |
149 | 150 | ||
@@ -154,15 +155,23 @@ void rpcrdma_event_process(struct ib_wc *wc) | |||
154 | return; | 155 | return; |
155 | 156 | ||
156 | if (IB_WC_SUCCESS != wc->status) { | 157 | if (IB_WC_SUCCESS != wc->status) { |
157 | dprintk("RPC: %s: %s WC status %X, connection lost\n", | 158 | dprintk("RPC: %s: WC opcode %d status %X, connection lost\n", |
158 | __func__, (wc->opcode & IB_WC_RECV) ? "recv" : "send", | 159 | __func__, wc->opcode, wc->status); |
159 | wc->status); | ||
160 | rep->rr_len = ~0U; | 160 | rep->rr_len = ~0U; |
161 | rpcrdma_schedule_tasklet(rep); | 161 | if (wc->opcode != IB_WC_FAST_REG_MR && wc->opcode != IB_WC_LOCAL_INV) |
162 | rpcrdma_schedule_tasklet(rep); | ||
162 | return; | 163 | return; |
163 | } | 164 | } |
164 | 165 | ||
165 | switch (wc->opcode) { | 166 | switch (wc->opcode) { |
167 | case IB_WC_FAST_REG_MR: | ||
168 | frmr = (struct rpcrdma_mw *)(unsigned long)wc->wr_id; | ||
169 | frmr->r.frmr.state = FRMR_IS_VALID; | ||
170 | break; | ||
171 | case IB_WC_LOCAL_INV: | ||
172 | frmr = (struct rpcrdma_mw *)(unsigned long)wc->wr_id; | ||
173 | frmr->r.frmr.state = FRMR_IS_INVALID; | ||
174 | break; | ||
166 | case IB_WC_RECV: | 175 | case IB_WC_RECV: |
167 | rep->rr_len = wc->byte_len; | 176 | rep->rr_len = wc->byte_len; |
168 | ib_dma_sync_single_for_cpu( | 177 | ib_dma_sync_single_for_cpu( |
@@ -378,7 +387,7 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, | |||
378 | 387 | ||
379 | init_completion(&ia->ri_done); | 388 | init_completion(&ia->ri_done); |
380 | 389 | ||
381 | id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP); | 390 | id = rdma_create_id(rpcrdma_conn_upcall, xprt, RDMA_PS_TCP, IB_QPT_RC); |
382 | if (IS_ERR(id)) { | 391 | if (IS_ERR(id)) { |
383 | rc = PTR_ERR(id); | 392 | rc = PTR_ERR(id); |
384 | dprintk("RPC: %s: rdma_create_id() failed %i\n", | 393 | dprintk("RPC: %s: rdma_create_id() failed %i\n", |
@@ -1450,6 +1459,12 @@ rpcrdma_map_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg, int writing) | |||
1450 | seg->mr_dma = ib_dma_map_single(ia->ri_id->device, | 1459 | seg->mr_dma = ib_dma_map_single(ia->ri_id->device, |
1451 | seg->mr_offset, | 1460 | seg->mr_offset, |
1452 | seg->mr_dmalen, seg->mr_dir); | 1461 | seg->mr_dmalen, seg->mr_dir); |
1462 | if (ib_dma_mapping_error(ia->ri_id->device, seg->mr_dma)) { | ||
1463 | dprintk("RPC: %s: mr_dma %llx mr_offset %p mr_dma_len %zu\n", | ||
1464 | __func__, | ||
1465 | (unsigned long long)seg->mr_dma, | ||
1466 | seg->mr_offset, seg->mr_dmalen); | ||
1467 | } | ||
1453 | } | 1468 | } |
1454 | 1469 | ||
1455 | static void | 1470 | static void |
@@ -1469,7 +1484,8 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1469 | struct rpcrdma_xprt *r_xprt) | 1484 | struct rpcrdma_xprt *r_xprt) |
1470 | { | 1485 | { |
1471 | struct rpcrdma_mr_seg *seg1 = seg; | 1486 | struct rpcrdma_mr_seg *seg1 = seg; |
1472 | struct ib_send_wr frmr_wr, *bad_wr; | 1487 | struct ib_send_wr invalidate_wr, frmr_wr, *bad_wr, *post_wr; |
1488 | |||
1473 | u8 key; | 1489 | u8 key; |
1474 | int len, pageoff; | 1490 | int len, pageoff; |
1475 | int i, rc; | 1491 | int i, rc; |
@@ -1484,6 +1500,7 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1484 | rpcrdma_map_one(ia, seg, writing); | 1500 | rpcrdma_map_one(ia, seg, writing); |
1485 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma; | 1501 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma; |
1486 | len += seg->mr_len; | 1502 | len += seg->mr_len; |
1503 | BUG_ON(seg->mr_len > PAGE_SIZE); | ||
1487 | ++seg; | 1504 | ++seg; |
1488 | ++i; | 1505 | ++i; |
1489 | /* Check for holes */ | 1506 | /* Check for holes */ |
@@ -1494,26 +1511,45 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1494 | dprintk("RPC: %s: Using frmr %p to map %d segments\n", | 1511 | dprintk("RPC: %s: Using frmr %p to map %d segments\n", |
1495 | __func__, seg1->mr_chunk.rl_mw, i); | 1512 | __func__, seg1->mr_chunk.rl_mw, i); |
1496 | 1513 | ||
1514 | if (unlikely(seg1->mr_chunk.rl_mw->r.frmr.state == FRMR_IS_VALID)) { | ||
1515 | dprintk("RPC: %s: frmr %x left valid, posting invalidate.\n", | ||
1516 | __func__, | ||
1517 | seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey); | ||
1518 | /* Invalidate before using. */ | ||
1519 | memset(&invalidate_wr, 0, sizeof invalidate_wr); | ||
1520 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; | ||
1521 | invalidate_wr.next = &frmr_wr; | ||
1522 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | ||
1523 | invalidate_wr.send_flags = IB_SEND_SIGNALED; | ||
1524 | invalidate_wr.ex.invalidate_rkey = | ||
1525 | seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | ||
1526 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
1527 | post_wr = &invalidate_wr; | ||
1528 | } else | ||
1529 | post_wr = &frmr_wr; | ||
1530 | |||
1497 | /* Bump the key */ | 1531 | /* Bump the key */ |
1498 | key = (u8)(seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey & 0x000000FF); | 1532 | key = (u8)(seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey & 0x000000FF); |
1499 | ib_update_fast_reg_key(seg1->mr_chunk.rl_mw->r.frmr.fr_mr, ++key); | 1533 | ib_update_fast_reg_key(seg1->mr_chunk.rl_mw->r.frmr.fr_mr, ++key); |
1500 | 1534 | ||
1501 | /* Prepare FRMR WR */ | 1535 | /* Prepare FRMR WR */ |
1502 | memset(&frmr_wr, 0, sizeof frmr_wr); | 1536 | memset(&frmr_wr, 0, sizeof frmr_wr); |
1537 | frmr_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; | ||
1503 | frmr_wr.opcode = IB_WR_FAST_REG_MR; | 1538 | frmr_wr.opcode = IB_WR_FAST_REG_MR; |
1504 | frmr_wr.send_flags = 0; /* unsignaled */ | 1539 | frmr_wr.send_flags = IB_SEND_SIGNALED; |
1505 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; | 1540 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; |
1506 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; | 1541 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; |
1507 | frmr_wr.wr.fast_reg.page_list_len = i; | 1542 | frmr_wr.wr.fast_reg.page_list_len = i; |
1508 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | 1543 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; |
1509 | frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT; | 1544 | frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT; |
1545 | BUG_ON(frmr_wr.wr.fast_reg.length < len); | ||
1510 | frmr_wr.wr.fast_reg.access_flags = (writing ? | 1546 | frmr_wr.wr.fast_reg.access_flags = (writing ? |
1511 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : | 1547 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : |
1512 | IB_ACCESS_REMOTE_READ); | 1548 | IB_ACCESS_REMOTE_READ); |
1513 | frmr_wr.wr.fast_reg.rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | 1549 | frmr_wr.wr.fast_reg.rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; |
1514 | DECR_CQCOUNT(&r_xprt->rx_ep); | 1550 | DECR_CQCOUNT(&r_xprt->rx_ep); |
1515 | 1551 | ||
1516 | rc = ib_post_send(ia->ri_id->qp, &frmr_wr, &bad_wr); | 1552 | rc = ib_post_send(ia->ri_id->qp, post_wr, &bad_wr); |
1517 | 1553 | ||
1518 | if (rc) { | 1554 | if (rc) { |
1519 | dprintk("RPC: %s: failed ib_post_send for register," | 1555 | dprintk("RPC: %s: failed ib_post_send for register," |
@@ -1542,8 +1578,9 @@ rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1542 | rpcrdma_unmap_one(ia, seg++); | 1578 | rpcrdma_unmap_one(ia, seg++); |
1543 | 1579 | ||
1544 | memset(&invalidate_wr, 0, sizeof invalidate_wr); | 1580 | memset(&invalidate_wr, 0, sizeof invalidate_wr); |
1581 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; | ||
1545 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | 1582 | invalidate_wr.opcode = IB_WR_LOCAL_INV; |
1546 | invalidate_wr.send_flags = 0; /* unsignaled */ | 1583 | invalidate_wr.send_flags = IB_SEND_SIGNALED; |
1547 | invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | 1584 | invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; |
1548 | DECR_CQCOUNT(&r_xprt->rx_ep); | 1585 | DECR_CQCOUNT(&r_xprt->rx_ep); |
1549 | 1586 | ||