diff --git a/srpt/README b/srpt/README index 1f0c91594..4d002271d 100644 --- a/srpt/README +++ b/srpt/README @@ -68,6 +68,16 @@ The ib_srpt kernel module supports the following parameters: to 65536 bytes, which is sufficient to use the full bandwidth of low-latency HCAs. Increasing this value may decrease latency for applications transferring large amounts of data at once. +* srpt_irq_qd (number, default 1) + After the ib_srpt driver has received a SCSI command from an initiator + system an interrupt is triggered. The RDMA work completion can be processed + either in interrupt context or in thread context. This parameter controls + the maximum queue depth for which RDMA completions are processed in + interrupt context. If an RDMA completion has been processed in interrupt + context the associated SCSI command will be submitted to SCST from tasklet + context. This approach helps to reduce command processing latency for + low-latency storage devices (e.g. SSDs). WARNING: setting this parameter to + a high value can cause a system to lock up. * srpt_srq_size (number, default 4095) ib_srpt uses a shared receive queue (SRQ) for processing incoming SRP requests. This number may have to be increased when a large number of diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index d4fdcbe7a..ba740d499 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -148,6 +148,12 @@ module_param(srpt_sq_size, int, 0444); MODULE_PARM_DESC(srpt_sq_size, "Per-channel send queue (SQ) size."); +static int srpt_irq_qd = 1; +module_param(srpt_irq_qd, int, 0644); +MODULE_PARM_DESC(srpt_irq_qd, + "Maximum queue depth for submitting commands to SCST from IRQ context." + " WARNING: increasing this parameter may cause a system lockup."); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) \ || defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5 static int use_port_guid_in_session_name; @@ -190,9 +196,16 @@ MODULE_PARM_DESC(max_sge_delta, "Number to subtract from max_sge."); * dangerous because it might cause IB completions to be processed too late * ("IB completion for idx has not been received in time"). */ -static const enum scst_exec_context srpt_new_iu_context = SCST_CONTEXT_THREAD; -static const enum scst_exec_context srpt_xmt_rsp_context = SCST_CONTEXT_THREAD; -static const enum scst_exec_context srpt_send_context = SCST_CONTEXT_DIRECT; +static inline enum scst_exec_context +srpt_new_iu_context(struct srpt_rdma_ch *ch) +{ + return in_interrupt() && + atomic_read(&ch->sess->sess_cmd_count) <= ch->irq_qd ? + SCST_CONTEXT_TASKLET : SCST_CONTEXT_THREAD; +} +#define srpt_xmt_rsp_context SCST_CONTEXT_THREAD +#define srpt_send_context \ + (in_interrupt() ? SCST_CONTEXT_THREAD : SCST_CONTEXT_DIRECT) static struct ib_client srpt_client; static struct scst_tgt_template srpt_template; @@ -1954,7 +1967,7 @@ static void srpt_process_rcv_completion(struct ib_cq *cq, else ioctx = ch->ioctx_recv_ring[index]; ioctx->byte_len = wc->byte_len; - srpt_handle_new_iu(ch, ioctx, srpt_new_iu_context); + srpt_handle_new_iu(ch, ioctx, srpt_new_iu_context(ch)); } else if (ch->state <= CH_LIVE) { pr_info("receiving failed for idx %u with status %d\n", index, wc->status); @@ -1969,7 +1982,8 @@ static void srpt_process_wait_list(struct srpt_rdma_ch *ch) list_for_each_entry_safe(recv_ioctx, tmp, &ch->cmd_wait_list, wait_list) { - if (!srpt_handle_new_iu(ch, recv_ioctx, srpt_new_iu_context)) + if (!srpt_handle_new_iu(ch, recv_ioctx, + srpt_new_iu_context(ch))) break; } @@ -2098,7 +2112,13 @@ static void srpt_completion(struct ib_cq *cq, void *ctx) { struct srpt_rdma_ch *ch = ctx; - wake_up_process(ch->thread); + const int irq_qd = ch->irq_qd; + int processed = 0; + + if (atomic_read(&ch->sess->sess_cmd_count) <= irq_qd) + processed = srpt_process_completion(ch, irq_qd + 1, false); + if (processed == 0 || processed > irq_qd) + wake_up_process(ch->thread); } static void srpt_free_ch(struct kref *kref) @@ -2621,6 +2641,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, ch->rdma_cm.cm_id = rdma_cm_id; rdma_cm_id->context = ch; } + ch->irq_qd = srpt_irq_qd; /* * Avoid QUEUE_FULL conditions by limiting the number of buffers used * for the SRP protocol to the SCST SCSI command queue size. diff --git a/srpt/src/ib_srpt.h b/srpt/src/ib_srpt.h index 25f816593..9ea725c06 100644 --- a/srpt/src/ib_srpt.h +++ b/srpt/src/ib_srpt.h @@ -317,6 +317,7 @@ enum rdma_ch_state { * @qp: IB queue pair used for communicating over this channel. * @cq: IB completion queue for this channel. * @kref: Per-channel reference count. + * @irq_qd: Maximum queue depth processed in atomic context. * @rq_size: IB receive queue size. * @max_sge: Maximum length of RDMA scatter list. * @max_rsp_size: Maximum size of an SRP response message in bytes. @@ -361,6 +362,7 @@ struct srpt_rdma_ch { }; struct ib_cq *cq; struct kref kref; + int irq_qd; struct rcu_head rcu; int rq_size; int max_sge;