mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 05:56:54 +07:00
[SCSI] libfc: adds can_queue ramp up
Adds last_can_queue_ramp_down_time and updates this on every ramp down. If last_can_queue_ramp_down_time is not zero then do ramp up on any IO completion in added fc_fcp_can_queue_ramp_up. Reset last_can_queue_ramp_down_time to zero once can_queue is ramped up to added max_can_queue limit, this is to avoid any more ramp up attempts on subsequent IO completion. The ramp down and up are skipped for FC_CAN_QUEUE_PERIOD to avoid infrequent changes to can_queue, this required keeping track of ramp up time also in last_can_queue_ramp_up_time. Adds code to ramp down can_queue if lp->qfull is set, with added new ramp up code the can_queue will be increased after FC_CAN_QUEUE_PERIOD, therefore it is safe to do ramp down without fsp in this case and will avoid thrash. This required fc_fcp_can_queue_ramp_down locking change so that it can be called with Scsi_Host lock held. Removes si->throttled and fsp state FC_SRB_NOMEM, not needed with added ramp up code. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
c46be11a68
commit
84c3e1ad08
@ -52,7 +52,6 @@ struct kmem_cache *scsi_pkt_cachep;
|
||||
#define FC_SRB_DISCONTIG (1 << 4) /* non-sequential data recvd */
|
||||
#define FC_SRB_COMPL (1 << 5) /* fc_io_compl has been run */
|
||||
#define FC_SRB_FCP_PROCESSING_TMO (1 << 6) /* timer function processing */
|
||||
#define FC_SRB_NOMEM (1 << 7) /* dropped to out of mem */
|
||||
|
||||
#define FC_SRB_READ (1 << 1)
|
||||
#define FC_SRB_WRITE (1 << 0)
|
||||
@ -71,12 +70,16 @@ struct kmem_cache *scsi_pkt_cachep;
|
||||
* struct fc_fcp_internal - FCP layer internal data
|
||||
* @scsi_pkt_pool: Memory pool to draw FCP packets from
|
||||
* @scsi_pkt_queue: Current FCP packets
|
||||
* @throttled: The FCP packet queue is throttled
|
||||
* @last_can_queue_ramp_down_time: ramp down time
|
||||
* @last_can_queue_ramp_up_time: ramp up time
|
||||
* @max_can_queue: max can_queue size
|
||||
*/
|
||||
struct fc_fcp_internal {
|
||||
mempool_t *scsi_pkt_pool;
|
||||
struct list_head scsi_pkt_queue;
|
||||
u8 throttled;
|
||||
unsigned long last_can_queue_ramp_down_time;
|
||||
unsigned long last_can_queue_ramp_up_time;
|
||||
int max_can_queue;
|
||||
};
|
||||
|
||||
#define fc_get_scsi_internal(x) ((struct fc_fcp_internal *)(x)->scsi_priv)
|
||||
@ -124,6 +127,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
|
||||
#define FC_SCSI_TM_TOV (10 * HZ)
|
||||
#define FC_SCSI_REC_TOV (2 * HZ)
|
||||
#define FC_HOST_RESET_TIMEOUT (30 * HZ)
|
||||
#define FC_CAN_QUEUE_PERIOD (60 * HZ)
|
||||
|
||||
#define FC_MAX_ERROR_CNT 5
|
||||
#define FC_MAX_RECOV_RETRY 3
|
||||
@ -326,6 +330,38 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fc_fcp_can_queue_ramp_up() - increases can_queue
|
||||
* @lport: lport to ramp up can_queue
|
||||
*
|
||||
* Locking notes: Called with Scsi_Host lock held
|
||||
*/
|
||||
static void fc_fcp_can_queue_ramp_up(struct fc_lport *lport)
|
||||
{
|
||||
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
|
||||
int can_queue;
|
||||
|
||||
if (si->last_can_queue_ramp_up_time &&
|
||||
(time_before(jiffies, si->last_can_queue_ramp_up_time +
|
||||
FC_CAN_QUEUE_PERIOD)))
|
||||
return;
|
||||
|
||||
if (time_before(jiffies, si->last_can_queue_ramp_down_time +
|
||||
FC_CAN_QUEUE_PERIOD))
|
||||
return;
|
||||
|
||||
si->last_can_queue_ramp_up_time = jiffies;
|
||||
|
||||
can_queue = lport->host->can_queue << 1;
|
||||
if (can_queue >= si->max_can_queue) {
|
||||
can_queue = si->max_can_queue;
|
||||
si->last_can_queue_ramp_down_time = 0;
|
||||
}
|
||||
lport->host->can_queue = can_queue;
|
||||
shost_printk(KERN_ERR, lport->host, "libfc: increased "
|
||||
"can_queue to %d.\n", can_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* fc_fcp_can_queue_ramp_down() - reduces can_queue
|
||||
* @lport: lport to reduce can_queue
|
||||
@ -335,17 +371,20 @@ static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
|
||||
* commands complete or timeout, then try again with a reduced
|
||||
* can_queue. Eventually we will hit the point where we run
|
||||
* on all reserved structs.
|
||||
*
|
||||
* Locking notes: Called with Scsi_Host lock held
|
||||
*/
|
||||
static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
|
||||
{
|
||||
struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
|
||||
unsigned long flags;
|
||||
int can_queue;
|
||||
|
||||
spin_lock_irqsave(lport->host->host_lock, flags);
|
||||
if (si->throttled)
|
||||
goto done;
|
||||
si->throttled = 1;
|
||||
if (si->last_can_queue_ramp_down_time &&
|
||||
(time_before(jiffies, si->last_can_queue_ramp_down_time +
|
||||
FC_CAN_QUEUE_PERIOD)))
|
||||
return;
|
||||
|
||||
si->last_can_queue_ramp_down_time = jiffies;
|
||||
|
||||
can_queue = lport->host->can_queue;
|
||||
can_queue >>= 1;
|
||||
@ -354,8 +393,6 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
|
||||
lport->host->can_queue = can_queue;
|
||||
shost_printk(KERN_ERR, lport->host, "libfc: Could not allocate frame.\n"
|
||||
"Reducing can_queue to %d.\n", can_queue);
|
||||
done:
|
||||
spin_unlock_irqrestore(lport->host->host_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -370,10 +407,14 @@ static inline struct fc_frame *fc_fcp_frame_alloc(struct fc_lport *lport,
|
||||
size_t len)
|
||||
{
|
||||
struct fc_frame *fp;
|
||||
unsigned long flags;
|
||||
|
||||
fp = fc_frame_alloc(lport, len);
|
||||
if (!fp)
|
||||
if (!fp) {
|
||||
spin_lock_irqsave(lport->host->host_lock, flags);
|
||||
fc_fcp_can_queue_ramp_down(lport);
|
||||
spin_unlock_irqrestore(lport->host->host_lock, flags);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
@ -720,8 +761,6 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
|
||||
(size_t) ntohl(dd->ft_burst_len));
|
||||
if (!rc)
|
||||
seq->rec_data = fsp->xfer_len;
|
||||
else if (rc == -ENOMEM)
|
||||
fsp->state |= FC_SRB_NOMEM;
|
||||
} else if (r_ctl == FC_RCTL_DD_SOL_DATA) {
|
||||
/*
|
||||
* received a DATA frame
|
||||
@ -1734,6 +1773,8 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
|
||||
rpriv = rport->dd_data;
|
||||
|
||||
if (!fc_fcp_lport_queue_ready(lport)) {
|
||||
if (lport->qfull)
|
||||
fc_fcp_can_queue_ramp_down(lport);
|
||||
rc = SCSI_MLQUEUE_HOST_BUSY;
|
||||
goto out;
|
||||
}
|
||||
@ -1830,13 +1871,11 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
|
||||
}
|
||||
|
||||
/*
|
||||
* if a command timed out while we had to try and throttle IO
|
||||
* and it is now getting cleaned up, then we are about to
|
||||
* try again so clear the throttled flag incase we get more
|
||||
* time outs.
|
||||
* if can_queue ramp down is done then try can_queue ramp up
|
||||
* since commands are completing now.
|
||||
*/
|
||||
if (si->throttled && fsp->state & FC_SRB_NOMEM)
|
||||
si->throttled = 0;
|
||||
if (si->last_can_queue_ramp_down_time)
|
||||
fc_fcp_can_queue_ramp_up(lport);
|
||||
|
||||
sc_cmd = fsp->cmd;
|
||||
fsp->cmd = NULL;
|
||||
@ -2176,6 +2215,7 @@ int fc_fcp_init(struct fc_lport *lport)
|
||||
if (!si)
|
||||
return -ENOMEM;
|
||||
lport->scsi_priv = si;
|
||||
si->max_can_queue = lport->host->can_queue;
|
||||
INIT_LIST_HEAD(&si->scsi_pkt_queue);
|
||||
|
||||
si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep);
|
||||
|
Loading…
Reference in New Issue
Block a user