Skip to content

Commit c490850

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Adapt partitioned XRI lists to efficient sharing
The XRI get/put lists were partitioned per hardware queue. However, the adapter rarely had sufficient resources to give a large number of resources per queue. As such, it became common for a cpu to encounter a lack of XRI resource and request the upper io stack to retry after returning a BUSY condition. This occurred even though other cpus were idle and not using their resources. Create as efficient a scheme as possible to move resources to the cpus that need them. Each cpu maintains a small private pool which it allocates from for io. There is a watermark that the cpu attempts to keep in the private pool. The private pool, when empty, pulls from a global pool from the cpu. When the cpu's global pool is empty it will pull from other cpu's global pool. As there many cpu global pools (1 per cpu or hardware queue count) and as each cpu selects what cpu to pull from at different rates and at different times, it creates a radomizing effect that minimizes the number of cpu's that will contend with each other when the steal XRI's from another cpu's global pool. On io completion, a cpu will push the XRI back on to its private pool. A watermark level is maintained for the private pool such that when it is exceeded it will move XRI's to the CPU global pool so that other cpu's may allocate them. On NVME, as heartbeat commands are critical to get placed on the wire, a single expedite pool is maintained. When a heartbeat is to be sent, it will allocate an XRI from the expedite pool rather than the normal cpu private/global pools. On any io completion, if a reduction in the expedite pools is seen, it will be replenished before the XRI is placed on the cpu private pool. Statistics are added to aid understanding the XRI levels on each cpu and their behaviors. Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent ace44e4 commit c490850

File tree

13 files changed

+1527
-327
lines changed

13 files changed

+1527
-327
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,6 @@ typedef struct lpfc_vpd {
235235
} sli3Feat;
236236
} lpfc_vpd_t;
237237

238-
struct lpfc_scsi_buf;
239-
240238

241239
/*
242240
* lpfc stat counters
@@ -597,6 +595,13 @@ struct lpfc_mbox_ext_buf_ctx {
597595
struct list_head ext_dmabuf_list;
598596
};
599597

598+
struct lpfc_epd_pool {
599+
/* Expedite pool */
600+
struct list_head list;
601+
u32 count;
602+
spinlock_t lock; /* lock for expedite pool */
603+
};
604+
600605
struct lpfc_ras_fwlog {
601606
uint8_t *fwlog_buff;
602607
uint32_t fw_buffcount; /* Buffer size posted to FW */
@@ -618,19 +623,19 @@ struct lpfc_ras_fwlog {
618623

619624
struct lpfc_hba {
620625
/* SCSI interface function jump table entries */
621-
struct lpfc_scsi_buf * (*lpfc_get_scsi_buf)
626+
struct lpfc_io_buf * (*lpfc_get_scsi_buf)
622627
(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
623628
struct scsi_cmnd *cmnd);
624629
int (*lpfc_scsi_prep_dma_buf)
625-
(struct lpfc_hba *, struct lpfc_scsi_buf *);
630+
(struct lpfc_hba *, struct lpfc_io_buf *);
626631
void (*lpfc_scsi_unprep_dma_buf)
627-
(struct lpfc_hba *, struct lpfc_scsi_buf *);
632+
(struct lpfc_hba *, struct lpfc_io_buf *);
628633
void (*lpfc_release_scsi_buf)
629-
(struct lpfc_hba *, struct lpfc_scsi_buf *);
634+
(struct lpfc_hba *, struct lpfc_io_buf *);
630635
void (*lpfc_rampdown_queue_depth)
631636
(struct lpfc_hba *);
632637
void (*lpfc_scsi_prep_cmnd)
633-
(struct lpfc_vport *, struct lpfc_scsi_buf *,
638+
(struct lpfc_vport *, struct lpfc_io_buf *,
634639
struct lpfc_nodelist *);
635640

636641
/* IOCB interface function jump table entries */
@@ -673,9 +678,12 @@ struct lpfc_hba {
673678
(struct lpfc_hba *);
674679

675680
int (*lpfc_bg_scsi_prep_dma_buf)
676-
(struct lpfc_hba *, struct lpfc_scsi_buf *);
681+
(struct lpfc_hba *, struct lpfc_io_buf *);
677682
/* Add new entries here */
678683

684+
/* expedite pool */
685+
struct lpfc_epd_pool epd_pool;
686+
679687
/* SLI4 specific HBA data structure */
680688
struct lpfc_sli4_hba sli4_hba;
681689

@@ -789,6 +797,7 @@ struct lpfc_hba {
789797

790798
/* HBA Config Parameters */
791799
uint32_t cfg_ack0;
800+
uint32_t cfg_xri_rebalancing;
792801
uint32_t cfg_enable_npiv;
793802
uint32_t cfg_enable_rrq;
794803
uint32_t cfg_topology;
@@ -1014,6 +1023,7 @@ struct lpfc_hba {
10141023
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
10151024
struct dentry *hba_debugfs_root;
10161025
atomic_t debugfs_vport_count;
1026+
struct dentry *debug_multixri_pools;
10171027
struct dentry *debug_hbqinfo;
10181028
struct dentry *debug_dumpHostSlim;
10191029
struct dentry *debug_dumpHBASlim;

drivers/scsi/lpfc/lpfc_attr.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5266,6 +5266,12 @@ static DEVICE_ATTR_RW(lpfc_max_scsicmpl_time);
52665266
*/
52675267
LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
52685268

5269+
/*
5270+
# lpfc_xri_rebalancing: enable or disable XRI rebalancing feature
5271+
# range is [0,1]. Default value is 1.
5272+
*/
5273+
LPFC_ATTR_R(xri_rebalancing, 1, 0, 1, "Enable/Disable XRI rebalancing");
5274+
52695275
/*
52705276
* lpfc_io_sched: Determine scheduling algrithmn for issuing FCP cmds
52715277
* range is [0,1]. Default value is 0.
@@ -5723,6 +5729,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
57235729
&dev_attr_lpfc_use_adisc,
57245730
&dev_attr_lpfc_first_burst_size,
57255731
&dev_attr_lpfc_ack0,
5732+
&dev_attr_lpfc_xri_rebalancing,
57265733
&dev_attr_lpfc_topology,
57275734
&dev_attr_lpfc_scan_down,
57285735
&dev_attr_lpfc_link_speed,
@@ -6788,6 +6795,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
67886795
lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl);
67896796
lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type);
67906797
lpfc_ack0_init(phba, lpfc_ack0);
6798+
lpfc_xri_rebalancing_init(phba, lpfc_xri_rebalancing);
67916799
lpfc_topology_init(phba, lpfc_topology);
67926800
lpfc_link_speed_init(phba, lpfc_link_speed);
67936801
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
@@ -6846,6 +6854,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
68466854
phba->nvmet_support = 0;
68476855
phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
68486856
phba->cfg_enable_bbcr = 0;
6857+
phba->cfg_xri_rebalancing = 0;
68496858
} else {
68506859
/* We MUST have FCP support */
68516860
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))

drivers/scsi/lpfc/lpfc_crtn.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ int lpfc_sli4_io_sgl_update(struct lpfc_hba *phba);
521521
int lpfc_sli4_post_io_sgl_list(struct lpfc_hba *phba,
522522
struct list_head *blist, int xricnt);
523523
int lpfc_new_io_buf(struct lpfc_hba *phba, int num_to_alloc);
524+
void lpfc_io_free(struct lpfc_hba *phba);
524525
void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
525526
uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *);
526527
int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t);
@@ -573,6 +574,21 @@ void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba);
573574
void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba,
574575
struct lpfc_iocbq *cmdiocb,
575576
struct lpfc_wcqe_complete *abts_cmpl);
577+
void lpfc_create_multixri_pools(struct lpfc_hba *phba);
578+
void lpfc_create_destroy_pools(struct lpfc_hba *phba);
579+
void lpfc_move_xri_pvt_to_pbl(struct lpfc_hba *phba, u32 hwqid);
580+
void lpfc_move_xri_pbl_to_pvt(struct lpfc_hba *phba, u32 hwqid, u32 cnt);
581+
void lpfc_adjust_high_watermark(struct lpfc_hba *phba, u32 hwqid);
582+
void lpfc_keep_pvt_pool_above_lowwm(struct lpfc_hba *phba, u32 hwqid);
583+
void lpfc_adjust_pvt_pool_count(struct lpfc_hba *phba, u32 hwqid);
584+
#ifdef LPFC_MXP_STAT
585+
void lpfc_snapshot_mxp(struct lpfc_hba *, u32);
586+
#endif
587+
struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
588+
struct lpfc_nodelist *ndlp, u32 hwqid,
589+
int);
590+
void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd,
591+
struct lpfc_sli4_hdw_queue *qp);
576592
void lpfc_nvme_cmd_template(void);
577593
void lpfc_nvmet_cmd_template(void);
578594
extern int lpfc_enable_nvmet_cnt;

0 commit comments

Comments
 (0)