summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJitendra Bhivare <jitendra.bhivare@broadcom.com>2016-12-13 11:25:56 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2017-01-05 06:21:12 +0100
commitfaa0a22d54230ae9658c419e495fc1a469e191f3 (patch)
tree1c77f39cadc4ab81f9ab3762a7497e7ec4fe84e9
parentscsi: be2iscsi: Fix for crash in beiscsi_eh_device_reset (diff)
downloadlinux-faa0a22d54230ae9658c419e495fc1a469e191f3.tar.xz
linux-faa0a22d54230ae9658c419e495fc1a469e191f3.zip
scsi: be2iscsi: Take iscsi_task ref in abort handler
Hold the reference of iscsi_task till invalidation completes. This prevents use of ICD when invalidation of that ICD is being processed. Signed-off-by: Jitendra Bhivare <jitendra.bhivare@broadcom.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/be2iscsi/be_main.c45
1 files changed, 19 insertions, 26 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 7feecc0b4903..260842a1f14e 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -218,47 +218,40 @@ static int beiscsi_slave_configure(struct scsi_device *sdev)
static int beiscsi_eh_abort(struct scsi_cmnd *sc)
{
+ struct iscsi_task *abrt_task = (struct iscsi_task *)sc->SCp.ptr;
struct iscsi_cls_session *cls_session;
- struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr;
- struct beiscsi_io_task *aborted_io_task;
- struct iscsi_conn *conn;
+ struct beiscsi_io_task *abrt_io_task;
struct beiscsi_conn *beiscsi_conn;
- struct beiscsi_hba *phba;
struct iscsi_session *session;
struct invldt_cmd_tbl inv_tbl;
- unsigned int cid;
+ struct beiscsi_hba *phba;
+ struct iscsi_conn *conn;
int rc;
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
- spin_lock_bh(&session->frwd_lock);
- if (!aborted_task || !aborted_task->sc) {
- /* we raced */
- spin_unlock_bh(&session->frwd_lock);
- return SUCCESS;
- }
-
- aborted_io_task = aborted_task->dd_data;
- if (!aborted_io_task->scsi_cmnd) {
- /* raced or invalid command */
- spin_unlock_bh(&session->frwd_lock);
+ /* check if we raced, task just got cleaned up under us */
+ spin_lock_bh(&session->back_lock);
+ if (!abrt_task || !abrt_task->sc) {
+ spin_unlock_bh(&session->back_lock);
return SUCCESS;
}
- spin_unlock_bh(&session->frwd_lock);
-
- conn = aborted_task->conn;
+ /* get a task ref till FW processes the req for the ICD used */
+ __iscsi_get_task(abrt_task);
+ abrt_io_task = abrt_task->dd_data;
+ conn = abrt_task->conn;
beiscsi_conn = conn->dd_data;
phba = beiscsi_conn->phba;
- /* Invalidate WRB Posted for this Task */
+ /* mark WRB invalid which have been not processed by FW yet */
AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
- aborted_io_task->pwrb_handle->pwrb,
- 1);
- /* invalidate iocb */
- cid = beiscsi_conn->beiscsi_conn_cid;
- inv_tbl.cid = cid;
- inv_tbl.icd = aborted_io_task->psgl_handle->sgl_index;
+ abrt_io_task->pwrb_handle->pwrb, 1);
+ inv_tbl.cid = beiscsi_conn->beiscsi_conn_cid;
+ inv_tbl.icd = abrt_io_task->psgl_handle->sgl_index;
+ spin_unlock_bh(&session->back_lock);
+
rc = beiscsi_mgmt_invalidate_icds(phba, &inv_tbl, 1);
+ iscsi_put_task(abrt_task);
if (rc) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH,
"BM_%d : sc %p invalidation failed %d\n",