scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
commit 6a87679626b51b53fbb6be417ad8eb083030b617 upstream. Task management command failed with status 2Ch which is a result of too many task management commands sent to the same target. Hence limit task management commands to 8 per target. Reported-by: kernel test robot <lkp@intel.com> Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@intel.com/ Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran <qutran@marvell.com> Signed-off-by: Nilesh Javali <njavali@marvell.com> Link: https://lore.kernel.org/r/20230428075339.32551-4-njavali@marvell.com Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
843665c426
commit
35985b0741
@ -2535,6 +2535,7 @@ enum rscn_addr_format {
|
|||||||
typedef struct fc_port {
|
typedef struct fc_port {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct scsi_qla_host *vha;
|
struct scsi_qla_host *vha;
|
||||||
|
struct list_head tmf_pending;
|
||||||
|
|
||||||
unsigned int conf_compl_supported:1;
|
unsigned int conf_compl_supported:1;
|
||||||
unsigned int deleted:2;
|
unsigned int deleted:2;
|
||||||
@ -2555,6 +2556,8 @@ typedef struct fc_port {
|
|||||||
unsigned int do_prli_nvme:1;
|
unsigned int do_prli_nvme:1;
|
||||||
|
|
||||||
uint8_t nvme_flag;
|
uint8_t nvme_flag;
|
||||||
|
uint8_t active_tmf;
|
||||||
|
#define MAX_ACTIVE_TMF 8
|
||||||
|
|
||||||
uint8_t node_name[WWN_SIZE];
|
uint8_t node_name[WWN_SIZE];
|
||||||
uint8_t port_name[WWN_SIZE];
|
uint8_t port_name[WWN_SIZE];
|
||||||
|
@ -2150,6 +2150,54 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg)
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void qla_put_tmf(fc_port_t *fcport)
|
||||||
|
{
|
||||||
|
struct scsi_qla_host *vha = fcport->vha;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||||
|
fcport->active_tmf--;
|
||||||
|
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int qla_get_tmf(fc_port_t *fcport)
|
||||||
|
{
|
||||||
|
struct scsi_qla_host *vha = fcport->vha;
|
||||||
|
struct qla_hw_data *ha = vha->hw;
|
||||||
|
unsigned long flags;
|
||||||
|
int rc = 0;
|
||||||
|
LIST_HEAD(tmf_elem);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||||
|
list_add_tail(&tmf_elem, &fcport->tmf_pending);
|
||||||
|
|
||||||
|
while (fcport->active_tmf >= MAX_ACTIVE_TMF) {
|
||||||
|
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||||
|
|
||||||
|
msleep(1);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
|
||||||
|
if (fcport->deleted) {
|
||||||
|
rc = EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fcport->active_tmf < MAX_ACTIVE_TMF &&
|
||||||
|
list_is_first(&tmf_elem, &fcport->tmf_pending))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_del(&tmf_elem);
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
fcport->active_tmf++;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
|
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
|
||||||
uint32_t tag)
|
uint32_t tag)
|
||||||
@ -2157,18 +2205,19 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
|
|||||||
struct scsi_qla_host *vha = fcport->vha;
|
struct scsi_qla_host *vha = fcport->vha;
|
||||||
struct qla_qpair *qpair;
|
struct qla_qpair *qpair;
|
||||||
struct tmf_arg a;
|
struct tmf_arg a;
|
||||||
struct completion comp;
|
|
||||||
int i, rval;
|
int i, rval;
|
||||||
|
|
||||||
init_completion(&comp);
|
|
||||||
a.vha = fcport->vha;
|
a.vha = fcport->vha;
|
||||||
a.fcport = fcport;
|
a.fcport = fcport;
|
||||||
a.lun = lun;
|
a.lun = lun;
|
||||||
|
if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
|
||||||
if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA))
|
|
||||||
a.modifier = MK_SYNC_ID_LUN;
|
a.modifier = MK_SYNC_ID_LUN;
|
||||||
else
|
|
||||||
|
if (qla_get_tmf(fcport))
|
||||||
|
return QLA_FUNCTION_FAILED;
|
||||||
|
} else {
|
||||||
a.modifier = MK_SYNC_ID;
|
a.modifier = MK_SYNC_ID;
|
||||||
|
}
|
||||||
|
|
||||||
if (vha->hw->mqenable) {
|
if (vha->hw->mqenable) {
|
||||||
for (i = 0; i < vha->hw->num_qpairs; i++) {
|
for (i = 0; i < vha->hw->num_qpairs; i++) {
|
||||||
@ -2187,6 +2236,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
|
|||||||
a.flags = flags;
|
a.flags = flags;
|
||||||
rval = __qla2x00_async_tm_cmd(&a);
|
rval = __qla2x00_async_tm_cmd(&a);
|
||||||
|
|
||||||
|
if (a.modifier == MK_SYNC_ID_LUN)
|
||||||
|
qla_put_tmf(fcport);
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5422,6 +5474,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
|
|||||||
INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
|
INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
|
||||||
INIT_LIST_HEAD(&fcport->gnl_entry);
|
INIT_LIST_HEAD(&fcport->gnl_entry);
|
||||||
INIT_LIST_HEAD(&fcport->list);
|
INIT_LIST_HEAD(&fcport->list);
|
||||||
|
INIT_LIST_HEAD(&fcport->tmf_pending);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&fcport->sess_cmd_list);
|
INIT_LIST_HEAD(&fcport->sess_cmd_list);
|
||||||
spin_lock_init(&fcport->sess_cmd_lock);
|
spin_lock_init(&fcport->sess_cmd_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user