| From 7867b98dceb7741065c9c1b645136facad5c2e93 Mon Sep 17 00:00:00 2001 |
| From: "himanshu.madhani@cavium.com" <himanshu.madhani@cavium.com> |
| Date: Mon, 4 Dec 2017 14:45:16 -0800 |
| Subject: scsi: qla2xxx: Fix memory leak in dual/target mode |
| |
| From: himanshu.madhani@cavium.com <himanshu.madhani@cavium.com> |
| |
| commit 7867b98dceb7741065c9c1b645136facad5c2e93 upstream. |
| |
| When driver is loaded in Target/Dual mode, it creates QPair to support |
| MQ and allocates resources for each QPair. This Qpair initialization is |
| delayed until the FW personality is changed to Dual/Target mode by |
| issuing chip reset. At the time of chip reset firmware is re-initilized |
| in correct personality all the QPairs are initialized by sending |
| MBC_INITIALIZE_MULTIQ (001Fh). |
| |
| This patch fixes memory leak by adding check to issue |
| MBC_INITIALIZE_MULTIQ command only while deleting rsp/req queue when the |
| flag is set for initiator mode, and clean up QPair resources correctly |
| during the driver unload. This MBX does not need to be issued for |
| Target/Dual mode because chip reset will reset ISP. |
| |
| Fixes: d65237c7f0860 ("scsi: qla2xxx: Fix mailbox failure while deleting Queue pairs") |
| Cc: <stable@vger.kernel.org> # 4.10+ |
| Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> |
| Reviewed-by: Hannes Reinecke <hare@suse.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/qla2xxx/qla_init.c | 4 +--- |
| drivers/scsi/qla2xxx/qla_mid.c | 18 ++++++++++-------- |
| 2 files changed, 11 insertions(+), 11 deletions(-) |
| |
| --- a/drivers/scsi/qla2xxx/qla_init.c |
| +++ b/drivers/scsi/qla2xxx/qla_init.c |
| @@ -8092,9 +8092,6 @@ int qla2xxx_delete_qpair(struct scsi_qla |
| int ret = QLA_FUNCTION_FAILED; |
| struct qla_hw_data *ha = qpair->hw; |
| |
| - if (!vha->flags.qpairs_req_created && !vha->flags.qpairs_rsp_created) |
| - goto fail; |
| - |
| qpair->delete_in_progress = 1; |
| while (atomic_read(&qpair->ref_count)) |
| msleep(500); |
| @@ -8102,6 +8099,7 @@ int qla2xxx_delete_qpair(struct scsi_qla |
| ret = qla25xx_delete_req_que(vha, qpair->req); |
| if (ret != QLA_SUCCESS) |
| goto fail; |
| + |
| ret = qla25xx_delete_rsp_que(vha, qpair->rsp); |
| if (ret != QLA_SUCCESS) |
| goto fail; |
| --- a/drivers/scsi/qla2xxx/qla_mid.c |
| +++ b/drivers/scsi/qla2xxx/qla_mid.c |
| @@ -575,14 +575,15 @@ qla25xx_free_rsp_que(struct scsi_qla_hos |
| int |
| qla25xx_delete_req_que(struct scsi_qla_host *vha, struct req_que *req) |
| { |
| - int ret = -1; |
| + int ret = QLA_SUCCESS; |
| |
| - if (req) { |
| + if (req && vha->flags.qpairs_req_created) { |
| req->options |= BIT_0; |
| ret = qla25xx_init_req_que(vha, req); |
| + if (ret != QLA_SUCCESS) |
| + return QLA_FUNCTION_FAILED; |
| } |
| - if (ret == QLA_SUCCESS) |
| - qla25xx_free_req_que(vha, req); |
| + qla25xx_free_req_que(vha, req); |
| |
| return ret; |
| } |
| @@ -590,14 +591,15 @@ qla25xx_delete_req_que(struct scsi_qla_h |
| int |
| qla25xx_delete_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) |
| { |
| - int ret = -1; |
| + int ret = QLA_SUCCESS; |
| |
| - if (rsp) { |
| + if (rsp && vha->flags.qpairs_rsp_created) { |
| rsp->options |= BIT_0; |
| ret = qla25xx_init_rsp_que(vha, rsp); |
| + if (ret != QLA_SUCCESS) |
| + return QLA_FUNCTION_FAILED; |
| } |
| - if (ret == QLA_SUCCESS) |
| - qla25xx_free_rsp_que(vha, rsp); |
| + qla25xx_free_rsp_que(vha, rsp); |
| |
| return ret; |
| } |