mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
scsi: libiscsi: Add helper to calculate max SCSI cmds per session
This patch just breaks out the code that calculates the number of SCSI cmds that will be used for a SCSI session. It also adds a check that we don't go over the host's can_queue value. Link: https://lore.kernel.org/r/20210207044608.27585-6-michael.christie@oracle.com Reviewed-by: Lee Duncan <lduncan@suse.com> Signed-off-by: Mike Christie <michael.christie@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
committed by
Martin K. Petersen
parent
c435f0a9ec
commit
b4046922b3
@@ -2648,6 +2648,56 @@ void iscsi_pool_free(struct iscsi_pool *q)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
||||||
|
|
||||||
|
int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,
|
||||||
|
uint16_t requested_cmds_max)
|
||||||
|
{
|
||||||
|
int scsi_cmds, total_cmds = requested_cmds_max;
|
||||||
|
|
||||||
|
check:
|
||||||
|
if (!total_cmds)
|
||||||
|
total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
|
||||||
|
/*
|
||||||
|
* The iscsi layer needs some tasks for nop handling and tmfs,
|
||||||
|
* so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX
|
||||||
|
* + 1 command for scsi IO.
|
||||||
|
*/
|
||||||
|
if (total_cmds < ISCSI_TOTAL_CMDS_MIN) {
|
||||||
|
printk(KERN_ERR "iscsi: invalid max cmds of %d. Must be a power of two that is at least %d.\n",
|
||||||
|
total_cmds, ISCSI_TOTAL_CMDS_MIN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
|
||||||
|
printk(KERN_INFO "iscsi: invalid max cmds of %d. Must be a power of 2 less than or equal to %d. Using %d.\n",
|
||||||
|
requested_cmds_max, ISCSI_TOTAL_CMDS_MAX,
|
||||||
|
ISCSI_TOTAL_CMDS_MAX);
|
||||||
|
total_cmds = ISCSI_TOTAL_CMDS_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_power_of_2(total_cmds)) {
|
||||||
|
total_cmds = rounddown_pow_of_two(total_cmds);
|
||||||
|
if (total_cmds < ISCSI_TOTAL_CMDS_MIN) {
|
||||||
|
printk(KERN_ERR "iscsi: invalid max cmds of %d. Must be a power of 2 greater than %d.\n", requested_cmds_max, ISCSI_TOTAL_CMDS_MIN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(KERN_INFO "iscsi: invalid max cmds %d. Must be a power of 2. Rounding max cmds down to %d.\n",
|
||||||
|
requested_cmds_max, total_cmds);
|
||||||
|
}
|
||||||
|
|
||||||
|
scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX;
|
||||||
|
if (shost->can_queue && scsi_cmds > shost->can_queue) {
|
||||||
|
total_cmds = shost->can_queue;
|
||||||
|
|
||||||
|
printk(KERN_INFO "iscsi: requested max cmds %u is higher than driver limit. Using driver limit %u\n",
|
||||||
|
requested_cmds_max, shost->can_queue);
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scsi_cmds;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(iscsi_host_get_max_scsi_cmds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iscsi_host_add - add host to system
|
* iscsi_host_add - add host to system
|
||||||
* @shost: scsi host
|
* @shost: scsi host
|
||||||
@@ -2801,7 +2851,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
|
|||||||
struct iscsi_host *ihost = shost_priv(shost);
|
struct iscsi_host *ihost = shost_priv(shost);
|
||||||
struct iscsi_session *session;
|
struct iscsi_session *session;
|
||||||
struct iscsi_cls_session *cls_session;
|
struct iscsi_cls_session *cls_session;
|
||||||
int cmd_i, scsi_cmds, total_cmds = cmds_max;
|
int cmd_i, scsi_cmds;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&ihost->lock, flags);
|
spin_lock_irqsave(&ihost->lock, flags);
|
||||||
@@ -2812,37 +2862,9 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
|
|||||||
ihost->num_sessions++;
|
ihost->num_sessions++;
|
||||||
spin_unlock_irqrestore(&ihost->lock, flags);
|
spin_unlock_irqrestore(&ihost->lock, flags);
|
||||||
|
|
||||||
if (!total_cmds)
|
scsi_cmds = iscsi_host_get_max_scsi_cmds(shost, cmds_max);
|
||||||
total_cmds = ISCSI_DEF_XMIT_CMDS_MAX;
|
if (scsi_cmds < 0)
|
||||||
/*
|
|
||||||
* The iscsi layer needs some tasks for nop handling and tmfs,
|
|
||||||
* so the cmds_max must at least be greater than ISCSI_MGMT_CMDS_MAX
|
|
||||||
* + 1 command for scsi IO.
|
|
||||||
*/
|
|
||||||
if (total_cmds < ISCSI_TOTAL_CMDS_MIN) {
|
|
||||||
printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
|
|
||||||
"must be a power of two that is at least %d.\n",
|
|
||||||
total_cmds, ISCSI_TOTAL_CMDS_MIN);
|
|
||||||
goto dec_session_count;
|
goto dec_session_count;
|
||||||
}
|
|
||||||
|
|
||||||
if (total_cmds > ISCSI_TOTAL_CMDS_MAX) {
|
|
||||||
printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
|
|
||||||
"must be a power of 2 less than or equal to %d.\n",
|
|
||||||
cmds_max, ISCSI_TOTAL_CMDS_MAX);
|
|
||||||
total_cmds = ISCSI_TOTAL_CMDS_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_power_of_2(total_cmds)) {
|
|
||||||
printk(KERN_ERR "iscsi: invalid can_queue of %d. can_queue "
|
|
||||||
"must be a power of 2.\n", total_cmds);
|
|
||||||
total_cmds = rounddown_pow_of_two(total_cmds);
|
|
||||||
if (total_cmds < ISCSI_TOTAL_CMDS_MIN)
|
|
||||||
goto dec_session_count;
|
|
||||||
printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n",
|
|
||||||
total_cmds);
|
|
||||||
}
|
|
||||||
scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX;
|
|
||||||
|
|
||||||
cls_session = iscsi_alloc_session(shost, iscsit,
|
cls_session = iscsi_alloc_session(shost, iscsit,
|
||||||
sizeof(struct iscsi_session) +
|
sizeof(struct iscsi_session) +
|
||||||
@@ -2858,7 +2880,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
|
|||||||
session->lu_reset_timeout = 15;
|
session->lu_reset_timeout = 15;
|
||||||
session->abort_timeout = 10;
|
session->abort_timeout = 10;
|
||||||
session->scsi_cmds_max = scsi_cmds;
|
session->scsi_cmds_max = scsi_cmds;
|
||||||
session->cmds_max = total_cmds;
|
session->cmds_max = scsi_cmds + ISCSI_MGMT_CMDS_MAX;
|
||||||
session->queued_cmdsn = session->cmdsn = initial_cmdsn;
|
session->queued_cmdsn = session->cmdsn = initial_cmdsn;
|
||||||
session->exp_cmdsn = initial_cmdsn + 1;
|
session->exp_cmdsn = initial_cmdsn + 1;
|
||||||
session->max_cmdsn = initial_cmdsn + 1;
|
session->max_cmdsn = initial_cmdsn + 1;
|
||||||
|
@@ -395,6 +395,8 @@ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
|
|||||||
extern void iscsi_host_remove(struct Scsi_Host *shost);
|
extern void iscsi_host_remove(struct Scsi_Host *shost);
|
||||||
extern void iscsi_host_free(struct Scsi_Host *shost);
|
extern void iscsi_host_free(struct Scsi_Host *shost);
|
||||||
extern int iscsi_target_alloc(struct scsi_target *starget);
|
extern int iscsi_target_alloc(struct scsi_target *starget);
|
||||||
|
extern int iscsi_host_get_max_scsi_cmds(struct Scsi_Host *shost,
|
||||||
|
uint16_t requested_cmds_max);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* session management
|
* session management
|
||||||
|
Reference in New Issue
Block a user