[SCSI] bnx2i: Added fix for NOP-Out response panic from unsolicited NOP-In
authorEddie Wai <eddie.wai@broadcom.com>
Tue, 23 Nov 2010 23:29:21 +0000 (15:29 -0800)
committerJames Bottomley <James.Bottomley@suse.de>
Tue, 21 Dec 2010 18:24:10 +0000 (12:24 -0600)
The patch fixes the following situations where NOP-Out pkt is called for:
- local unsolicited NOP-Out requests (requesting no NOP-In response)
- local NOP-Out responses to unsolicited NOP-In requests

kernel panic is observed due to double session spin_lock requests; one in the
bnx2i_process_nopin_local_cmpl routine in bnx2i_hwi.c and the other in the
iscsi_put_task routine in libiscsi.c

The proposed fix is to export the currently static __iscsi_put_task() routine
and have bnx2i call it directly instead of the iscsi_put_task() routine which
holds the session spin lock.

Signed-off-by: Eddie Wai <eddie.wai@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Reviewed-by: Anil Veerabhadrappa <anilgv@broadcom.com>
Acked-by: Benjamin Li <benli@broadcom.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/libiscsi.c
include/scsi/libiscsi.h

index 16c76e0b23186778b1f7ea7eccad494d02c70293..32cf9306ffcbf8fe440c52eb98d1dfd944fe509d 100644 (file)
@@ -1513,7 +1513,7 @@ static void bnx2i_process_nopin_local_cmpl(struct iscsi_session *session,
        task = iscsi_itt_to_task(conn,
                                 nop_in->itt & ISCSI_NOP_IN_MSG_INDEX);
        if (task)
-               iscsi_put_task(task);
+               __iscsi_put_task(task);
        spin_unlock(&session->lock);
 }
 
index c15fde808c33e98ea1b48398afaf951e19eedeaa..7551abe409002455798f6d71f0ffed5454fb9963 100644 (file)
@@ -539,11 +539,12 @@ void __iscsi_get_task(struct iscsi_task *task)
 }
 EXPORT_SYMBOL_GPL(__iscsi_get_task);
 
-static void __iscsi_put_task(struct iscsi_task *task)
+void __iscsi_put_task(struct iscsi_task *task)
 {
        if (atomic_dec_and_test(&task->refcount))
                iscsi_free_task(task);
 }
+EXPORT_SYMBOL_GPL(__iscsi_put_task);
 
 void iscsi_put_task(struct iscsi_task *task)
 {
index b81d969ddc67cbbfde3f4522cf11a7b2f7487509..68e951d79f0b1f03f90aa5895496244f93398576 100644 (file)
@@ -419,6 +419,7 @@ extern struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *, itt_t);
 extern struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *, itt_t);
 extern void iscsi_requeue_task(struct iscsi_task *task);
 extern void iscsi_put_task(struct iscsi_task *task);
+extern void __iscsi_put_task(struct iscsi_task *task);
 extern void __iscsi_get_task(struct iscsi_task *task);
 extern void iscsi_complete_scsi_task(struct iscsi_task *task,
                                     uint32_t exp_cmdsn, uint32_t max_cmdsn);