Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/srp: Register the indirect data buffer descriptor

Instead of always using the global rkey for the indirect data
buffer descriptor, register that descriptor with the HCA if
the kernel module parameter register_always has been set to Y.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Bart Van Assche and committed by
Doug Ledford
330179f2 002f1567

+58 -3
+54 -3
drivers/infiniband/ulp/srp/ib_srp.c
··· 1453 1453 return ret; 1454 1454 } 1455 1455 1456 + /* 1457 + * Register the indirect data buffer descriptor with the HCA. 1458 + * 1459 + * Note: since the indirect data buffer descriptor has been allocated with 1460 + * kmalloc() it is guaranteed that this buffer is a physically contiguous 1461 + * memory buffer. 1462 + */ 1463 + static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req, 1464 + void **next_mr, void **end_mr, u32 idb_len, 1465 + __be32 *idb_rkey) 1466 + { 1467 + struct srp_target_port *target = ch->target; 1468 + struct srp_device *dev = target->srp_host->srp_dev; 1469 + struct srp_map_state state; 1470 + struct srp_direct_buf idb_desc; 1471 + u64 idb_pages[1]; 1472 + int ret; 1473 + 1474 + memset(&state, 0, sizeof(state)); 1475 + memset(&idb_desc, 0, sizeof(idb_desc)); 1476 + state.gen.next = next_mr; 1477 + state.gen.end = end_mr; 1478 + state.desc = &idb_desc; 1479 + state.pages = idb_pages; 1480 + state.pages[0] = (req->indirect_dma_addr & 1481 + dev->mr_page_mask); 1482 + state.npages = 1; 1483 + state.base_dma_addr = req->indirect_dma_addr; 1484 + state.dma_len = idb_len; 1485 + ret = srp_finish_mapping(&state, ch); 1486 + if (ret < 0) 1487 + goto out; 1488 + 1489 + *idb_rkey = idb_desc.key; 1490 + 1491 + out: 1492 + return ret; 1493 + } 1494 + 1456 1495 static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch, 1457 1496 struct srp_request *req) 1458 1497 { 1459 1498 struct srp_target_port *target = ch->target; 1460 1499 struct scatterlist *scat; 1461 1500 struct srp_cmd *cmd = req->cmd->buf; 1462 - int len, nents, count; 1501 + int len, nents, count, ret; 1463 1502 struct srp_device *dev; 1464 1503 struct ib_device *ibdev; 1465 1504 struct srp_map_state state; 1466 1505 struct srp_indirect_buf *indirect_hdr; 1467 - u32 table_len; 1506 + u32 idb_len, table_len; 1507 + __be32 idb_rkey; 1468 1508 u8 fmt; 1469 1509 1470 1510 if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE) ··· 1586 1546 1587 1547 count = min(state.ndesc, target->cmd_sg_cnt); 1588 1548 table_len = state.ndesc * sizeof (struct srp_direct_buf); 1549 + idb_len = sizeof(struct srp_indirect_buf) + table_len; 1589 1550 1590 1551 fmt = SRP_DATA_DESC_INDIRECT; 1591 1552 len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf); ··· 1595 1554 memcpy(indirect_hdr->desc_list, req->indirect_desc, 1596 1555 count * sizeof (struct srp_direct_buf)); 1597 1556 1557 + if (register_always && (dev->use_fast_reg || dev->use_fmr)) { 1558 + ret = srp_map_idb(ch, req, state.gen.next, state.gen.end, 1559 + idb_len, &idb_rkey); 1560 + if (ret < 0) 1561 + return ret; 1562 + req->nmdesc++; 1563 + } else { 1564 + idb_rkey = target->rkey; 1565 + } 1566 + 1598 1567 indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr); 1599 - indirect_hdr->table_desc.key = cpu_to_be32(target->rkey); 1568 + indirect_hdr->table_desc.key = idb_rkey; 1600 1569 indirect_hdr->table_desc.len = cpu_to_be32(table_len); 1601 1570 indirect_hdr->len = cpu_to_be32(state.total_len); 1602 1571
+4
drivers/infiniband/ulp/srp/ib_srp.h
··· 288 288 struct srp_fr_desc **next; 289 289 struct srp_fr_desc **end; 290 290 } fr; 291 + struct { 292 + void **next; 293 + void **end; 294 + } gen; 291 295 }; 292 296 struct srp_direct_buf *desc; 293 297 u64 *pages;