aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/iser
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2015-08-06 11:33:04 -0400
committerDoug Ledford <dledford@redhat.com>2015-08-30 18:12:32 -0400
commitdf749cdc45d9f97cb0a5e6ceab80e2e00ee9bf85 (patch)
treea32c5aed6ab27476a1ec3a5bf928a24b0276e0e5 /drivers/infiniband/ulp/iser
parentf8db651da29bcad213d43328ebf8ce8459f526a7 (diff)
IB/iser: Support up to 8MB data transfer in a single command
iser support up to 512KB data transfer in a single scsi command. This means that larger IOs will split to different request. While iser can easily saturate FDR/EDR wires, some arrays are fine tuned for 1MB (or larger) IO sizes, hence add an option to support larger transfers (up to 8MB) if the device allows it. Given that a few target implementations don't support data transfers of more than 512KB by default and the fact that larger IO sizes require more resources, we introduce a module parameter to determine the maximum number of 512B sectors in a single scsi command. Users that are interested in larger transfers can change this value given that the target supports larger transfers. At the moment, iser works in 4K pages granularity, In a later stage we will get it to work with system page size instead. IO operations that consists of N pages will need a page vector of size N+1 in case the first SG element contains an offset. Given that some devices allocates memory regions in powers of 2, this means that allocating a region with N+1 pages, will result in region resources allocation of the next power of 2. Since we don't want that to happen, in case we are in the limit of IO size supported and the first SG element has an offset, we align the SG list using a bounce buffer (which is OK given that this is not likely to happen a lot). Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/ulp/iser')
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c10
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h14
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c2
-rw-r--r--drivers/infiniband/ulp/iser/iser_memory.c14
-rw-r--r--drivers/infiniband/ulp/iser/iser_verbs.c27
5 files changed, 60 insertions, 7 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 169cc3e75018..0720bb46589f 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -93,6 +93,10 @@ static unsigned int iscsi_max_lun = 512;
93module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); 93module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
94MODULE_PARM_DESC(max_lun, "Max LUNs to allow per session (default:512"); 94MODULE_PARM_DESC(max_lun, "Max LUNs to allow per session (default:512");
95 95
96unsigned int iser_max_sectors = ISER_DEF_MAX_SECTORS;
97module_param_named(max_sectors, iser_max_sectors, uint, S_IRUGO | S_IWUSR);
98MODULE_PARM_DESC(max_sectors, "Max number of sectors in a single scsi command (default:1024");
99
96bool iser_pi_enable = false; 100bool iser_pi_enable = false;
97module_param_named(pi_enable, iser_pi_enable, bool, S_IRUGO); 101module_param_named(pi_enable, iser_pi_enable, bool, S_IRUGO);
98MODULE_PARM_DESC(pi_enable, "Enable T10-PI offload support (default:disabled)"); 102MODULE_PARM_DESC(pi_enable, "Enable T10-PI offload support (default:disabled)");
@@ -625,6 +629,8 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
625 if (ep) { 629 if (ep) {
626 iser_conn = ep->dd_data; 630 iser_conn = ep->dd_data;
627 max_cmds = iser_conn->max_cmds; 631 max_cmds = iser_conn->max_cmds;
632 shost->sg_tablesize = iser_conn->scsi_sg_tablesize;
633 shost->max_sectors = iser_conn->scsi_max_sectors;
628 634
629 mutex_lock(&iser_conn->state_mutex); 635 mutex_lock(&iser_conn->state_mutex);
630 if (iser_conn->state != ISER_CONN_UP) { 636 if (iser_conn->state != ISER_CONN_UP) {
@@ -966,8 +972,8 @@ static struct scsi_host_template iscsi_iser_sht = {
966 .name = "iSCSI Initiator over iSER", 972 .name = "iSCSI Initiator over iSER",
967 .queuecommand = iscsi_queuecommand, 973 .queuecommand = iscsi_queuecommand,
968 .change_queue_depth = scsi_change_queue_depth, 974 .change_queue_depth = scsi_change_queue_depth,
969 .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, 975 .sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE,
970 .max_sectors = 1024, 976 .max_sectors = ISER_DEF_MAX_SECTORS,
971 .cmd_per_lun = ISER_DEF_CMD_PER_LUN, 977 .cmd_per_lun = ISER_DEF_CMD_PER_LUN,
972 .eh_abort_handler = iscsi_eh_abort, 978 .eh_abort_handler = iscsi_eh_abort,
973 .eh_device_reset_handler= iscsi_eh_device_reset, 979 .eh_device_reset_handler= iscsi_eh_device_reset,
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index e9ebe0b2263d..0bdd7e77e5db 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -98,8 +98,13 @@
98#define SHIFT_4K 12 98#define SHIFT_4K 12
99#define SIZE_4K (1ULL << SHIFT_4K) 99#define SIZE_4K (1ULL << SHIFT_4K)
100#define MASK_4K (~(SIZE_4K-1)) 100#define MASK_4K (~(SIZE_4K-1))
101 /* support up to 512KB in one RDMA */ 101
102#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> SHIFT_4K) 102/* Default support is 512KB I/O size */
103#define ISER_DEF_MAX_SECTORS 1024
104#define ISCSI_ISER_DEF_SG_TABLESIZE ((ISER_DEF_MAX_SECTORS * 512) >> SHIFT_4K)
105/* Maximum support is 8MB I/O size */
106#define ISCSI_ISER_MAX_SG_TABLESIZE ((16384 * 512) >> SHIFT_4K)
107
103#define ISER_DEF_XMIT_CMDS_DEFAULT 512 108#define ISER_DEF_XMIT_CMDS_DEFAULT 512
104#if ISCSI_DEF_XMIT_CMDS_MAX > ISER_DEF_XMIT_CMDS_DEFAULT 109#if ISCSI_DEF_XMIT_CMDS_MAX > ISER_DEF_XMIT_CMDS_DEFAULT
105 #define ISER_DEF_XMIT_CMDS_MAX ISCSI_DEF_XMIT_CMDS_MAX 110 #define ISER_DEF_XMIT_CMDS_MAX ISCSI_DEF_XMIT_CMDS_MAX
@@ -504,6 +509,8 @@ struct ib_conn {
504 * @rx_desc_head: head of rx_descs cyclic buffer 509 * @rx_desc_head: head of rx_descs cyclic buffer
505 * @rx_descs: rx buffers array (cyclic buffer) 510 * @rx_descs: rx buffers array (cyclic buffer)
506 * @num_rx_descs: number of rx descriptors 511 * @num_rx_descs: number of rx descriptors
512 * @scsi_sg_tablesize: scsi host sg_tablesize
513 * @scsi_max_sectors: scsi host max sectors
507 */ 514 */
508struct iser_conn { 515struct iser_conn {
509 struct ib_conn ib_conn; 516 struct ib_conn ib_conn;
@@ -528,6 +535,8 @@ struct iser_conn {
528 unsigned int rx_desc_head; 535 unsigned int rx_desc_head;
529 struct iser_rx_desc *rx_descs; 536 struct iser_rx_desc *rx_descs;
530 u32 num_rx_descs; 537 u32 num_rx_descs;
538 unsigned short scsi_sg_tablesize;
539 unsigned int scsi_max_sectors;
531}; 540};
532 541
533/** 542/**
@@ -583,6 +592,7 @@ extern struct iser_global ig;
583extern int iser_debug_level; 592extern int iser_debug_level;
584extern bool iser_pi_enable; 593extern bool iser_pi_enable;
585extern int iser_pi_guard; 594extern int iser_pi_guard;
595extern unsigned int iser_max_sectors;
586 596
587int iser_assign_reg_ops(struct iser_device *device); 597int iser_assign_reg_ops(struct iser_device *device);
588 598
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index f1200f27b6a7..0b1f3b54a0c1 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -259,7 +259,7 @@ int iser_alloc_rx_descriptors(struct iser_conn *iser_conn,
259 iser_conn->min_posted_rx = iser_conn->qp_max_recv_dtos >> 2; 259 iser_conn->min_posted_rx = iser_conn->qp_max_recv_dtos >> 2;
260 260
261 if (device->reg_ops->alloc_reg_res(ib_conn, session->scsi_cmds_max, 261 if (device->reg_ops->alloc_reg_res(ib_conn, session->scsi_cmds_max,
262 ISCSI_ISER_SG_TABLESIZE + 1)) 262 iser_conn->scsi_sg_tablesize))
263 goto create_rdma_reg_res_failed; 263 goto create_rdma_reg_res_failed;
264 264
265 if (iser_alloc_login_buf(iser_conn)) 265 if (iser_alloc_login_buf(iser_conn))
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index b1261d5fbb9b..384fd0a49cca 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -363,7 +363,8 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
363 * consecutive SG elements are actually fragments of the same physcial page. 363 * consecutive SG elements are actually fragments of the same physcial page.
364 */ 364 */
365static int iser_data_buf_aligned_len(struct iser_data_buf *data, 365static int iser_data_buf_aligned_len(struct iser_data_buf *data,
366 struct ib_device *ibdev) 366 struct ib_device *ibdev,
367 unsigned sg_tablesize)
367{ 368{
368 struct scatterlist *sg, *sgl, *next_sg = NULL; 369 struct scatterlist *sg, *sgl, *next_sg = NULL;
369 u64 start_addr, end_addr; 370 u64 start_addr, end_addr;
@@ -375,6 +376,14 @@ static int iser_data_buf_aligned_len(struct iser_data_buf *data,
375 sgl = data->sg; 376 sgl = data->sg;
376 start_addr = ib_sg_dma_address(ibdev, sgl); 377 start_addr = ib_sg_dma_address(ibdev, sgl);
377 378
379 if (unlikely(sgl[0].offset &&
380 data->data_len >= sg_tablesize * PAGE_SIZE)) {
381 iser_dbg("can't register length %lx with offset %x "
382 "fall to bounce buffer\n", data->data_len,
383 sgl[0].offset);
384 return 0;
385 }
386
378 for_each_sg(sgl, sg, data->dma_nents, i) { 387 for_each_sg(sgl, sg, data->dma_nents, i) {
379 if (start_check && !IS_4K_ALIGNED(start_addr)) 388 if (start_check && !IS_4K_ALIGNED(start_addr))
380 break; 389 break;
@@ -790,7 +799,8 @@ iser_handle_unaligned_buf(struct iscsi_iser_task *task,
790 struct iser_device *device = iser_conn->ib_conn.device; 799 struct iser_device *device = iser_conn->ib_conn.device;
791 int err, aligned_len; 800 int err, aligned_len;
792 801
793 aligned_len = iser_data_buf_aligned_len(mem, device->ib_device); 802 aligned_len = iser_data_buf_aligned_len(mem, device->ib_device,
803 iser_conn->scsi_sg_tablesize);
794 if (aligned_len != mem->dma_nents) { 804 if (aligned_len != mem->dma_nents) {
795 err = fall_to_bounce_buf(task, mem, dir); 805 err = fall_to_bounce_buf(task, mem, dir);
796 if (err) 806 if (err)
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 0ade0e876c79..187c7125a4b9 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -756,6 +756,31 @@ static void iser_connect_error(struct rdma_cm_id *cma_id)
756 iser_conn->state = ISER_CONN_TERMINATING; 756 iser_conn->state = ISER_CONN_TERMINATING;
757} 757}
758 758
759static void
760iser_calc_scsi_params(struct iser_conn *iser_conn,
761 unsigned int max_sectors)
762{
763 struct iser_device *device = iser_conn->ib_conn.device;
764 unsigned short sg_tablesize, sup_sg_tablesize;
765
766 sg_tablesize = DIV_ROUND_UP(max_sectors * 512, SIZE_4K);
767 sup_sg_tablesize = min_t(unsigned, ISCSI_ISER_MAX_SG_TABLESIZE,
768 device->dev_attr.max_fast_reg_page_list_len);
769
770 if (sg_tablesize > sup_sg_tablesize) {
771 sg_tablesize = sup_sg_tablesize;
772 iser_conn->scsi_max_sectors = sg_tablesize * SIZE_4K / 512;
773 } else {
774 iser_conn->scsi_max_sectors = max_sectors;
775 }
776