Skip to content

Commit 77ffd34

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Mitigate high memory pre-allocation by SCSI-MQ
When SCSI-MQ is enabled, the SCSI-MQ layers will do pre-allocation of MQ resources based on shost values set by the driver. In newer cases of the driver, which attempts to set nr_hw_queues to the cpu count, the multipliers become excessive, with a single shost having SCSI-MQ pre-allocation reaching into the multiple GBytes range. NPIV, which creates additional shosts, only multiply this overhead. On lower-memory systems, this can exhaust system memory very quickly, resulting in a system crash or failures in the driver or elsewhere due to low memory conditions. After testing several scenarios, the situation can be mitigated by limiting the value set in shost->nr_hw_queues to 4. Although the shost values were changed, the driver still had per-cpu hardware queues of its own that allowed parallelization per-cpu. Testing revealed that even with the smallish number for nr_hw_queues for SCSI-MQ, performance levels remained near maximum with the within-driver affiinitization. A module parameter was created to allow the value set for the nr_hw_queues to be tunable. Signed-off-by: Dick Kennedy <[email protected]> Signed-off-by: James Smart <[email protected]> Reviewed-by: Ming Lei <[email protected]> Reviewed-by: Ewan D. Milne <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 7c7cfdc commit 77ffd34

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ struct lpfc_hba {
824824
uint32_t cfg_cq_poll_threshold;
825825
uint32_t cfg_cq_max_proc_limit;
826826
uint32_t cfg_fcp_cpu_map;
827+
uint32_t cfg_fcp_mq_threshold;
827828
uint32_t cfg_hdw_queue;
828829
uint32_t cfg_irq_chann;
829830
uint32_t cfg_suppress_rsp;

drivers/scsi/lpfc/lpfc_attr.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5708,6 +5708,19 @@ LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
57085708
LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
57095709
"Embed NVME Command in WQE");
57105710

5711+
/*
5712+
* lpfc_fcp_mq_threshold: Set the maximum number of Hardware Queues
5713+
* the driver will advertise it supports to the SCSI layer.
5714+
*
5715+
* 0 = Set nr_hw_queues by the number of CPUs or HW queues.
5716+
* 1,128 = Manually specify the maximum nr_hw_queue value to be set,
5717+
*
5718+
* Value range is [0,128]. Default value is 8.
5719+
*/
5720+
LPFC_ATTR_R(fcp_mq_threshold, LPFC_FCP_MQ_THRESHOLD_DEF,
5721+
LPFC_FCP_MQ_THRESHOLD_MIN, LPFC_FCP_MQ_THRESHOLD_MAX,
5722+
"Set the number of SCSI Queues advertised");
5723+
57115724
/*
57125725
* lpfc_hdw_queue: Set the number of Hardware Queues the driver
57135726
* will advertise it supports to the NVME and SCSI layers. This also
@@ -6030,6 +6043,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
60306043
&dev_attr_lpfc_cq_poll_threshold,
60316044
&dev_attr_lpfc_cq_max_proc_limit,
60326045
&dev_attr_lpfc_fcp_cpu_map,
6046+
&dev_attr_lpfc_fcp_mq_threshold,
60336047
&dev_attr_lpfc_hdw_queue,
60346048
&dev_attr_lpfc_irq_chann,
60356049
&dev_attr_lpfc_suppress_rsp,
@@ -7112,6 +7126,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
71127126
/* Initialize first burst. Target vs Initiator are different. */
71137127
lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
71147128
lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size);
7129+
lpfc_fcp_mq_threshold_init(phba, lpfc_fcp_mq_threshold);
71157130
lpfc_hdw_queue_init(phba, lpfc_hdw_queue);
71167131
lpfc_irq_chann_init(phba, lpfc_irq_chann);
71177132
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);

drivers/scsi/lpfc/lpfc_init.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4309,10 +4309,12 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
43094309
shost->max_cmd_len = 16;
43104310

43114311
if (phba->sli_rev == LPFC_SLI_REV4) {
4312-
if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ)
4313-
shost->nr_hw_queues = phba->cfg_hdw_queue;
4314-
else
4315-
shost->nr_hw_queues = phba->sli4_hba.num_present_cpu;
4312+
if (!phba->cfg_fcp_mq_threshold ||
4313+
phba->cfg_fcp_mq_threshold > phba->cfg_hdw_queue)
4314+
phba->cfg_fcp_mq_threshold = phba->cfg_hdw_queue;
4315+
4316+
shost->nr_hw_queues = min_t(int, 2 * num_possible_nodes(),
4317+
phba->cfg_fcp_mq_threshold);
43164318

43174319
shost->dma_boundary =
43184320
phba->sli4_hba.pc_sli4_params.sge_supp_len-1;

drivers/scsi/lpfc/lpfc_sli4.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
#define LPFC_HBA_HDWQ_MAX 128
4545
#define LPFC_HBA_HDWQ_DEF 0
4646

47+
/* FCP MQ queue count limiting */
48+
#define LPFC_FCP_MQ_THRESHOLD_MIN 0
49+
#define LPFC_FCP_MQ_THRESHOLD_MAX 128
50+
#define LPFC_FCP_MQ_THRESHOLD_DEF 8
51+
4752
/* Common buffer size to accomidate SCSI and NVME IO buffers */
4853
#define LPFC_COMMON_IO_BUF_SZ 768
4954

0 commit comments

Comments
 (0)