This patch fixes issue during switch command query where driver was freeing
SRB resources multiple times
Following stack trace will be seen
[ 853.436234] BUG: unable to handle kernel NULL pointer dereference at
0000000000000001
[ 853.436348] IP: [<
ffffffff811df514>] kmem_cache_alloc+0x74/0x1e0
[ 853.436476] PGD 0
[ 853.436601] Oops: 0000 [#1] SMP
[ 853.454700] [<
ffffffff81099f6a>] ? mod_timer+0x14a/0x220
[ 853.455543] [<
ffffffff81185465>] mempool_alloc_slab+0x15/0x20
[ 853.456395] [<
ffffffff811855a9>] mempool_alloc+0x69/0x170
[ 853.457257] [<
ffffffff81098af2>] ? internal_add_timer+0x32/0x70
[ 853.458136] [<
ffffffffc0092d2b>] qla2xxx_queuecommand+0x29b/0x3f0 [qla2xxx]
[ 853.459024] [<
ffffffff8146535a>] scsi_dispatch_cmd+0xaa/0x230
[ 853.459923] [<
ffffffff8146e11f>] scsi_request_fn+0x4df/0x680
[ 853.460829] [<
ffffffff81029557>] ? __switch_to+0xd7/0x510
[ 853.461747] [<
ffffffff812f7113>] __blk_run_queue+0x33/0x40
[ 853.462670] [<
ffffffff812f7735>] blk_delay_work+0x25/0x40
[ 853.463603] [<
ffffffff810a882a>] process_one_work+0x17a/0x440
[ 853.464546] [<
ffffffff810a94f6>] worker_thread+0x126/0x3c0
[ 853.465501] [<
ffffffff810a93d0>] ? manage_workers.isra.24+0x2a0/0x2a0
[ 853.466447] [<
ffffffff810b099f>] kthread+0xcf/0xe0
[ 853.467379] [<
ffffffff810b08d0>] ? insert_kthread_work+0x40/0x40
[ 853.470172] Code: db e2 7e 49 8b 50 08 4d 8b 20 49 8b 40 10 4d 85 e4 0f 84 20
01 00 00 48 85 c0 0f 84 17 01 00 00 49 63 46 20 48 8d 4a 01 4d 8b 06 <49> 8b 1c
04 4c 89 e0 65 49 0f c7 08 0f 94 c0 84 c0 74 ba 49 63
[ 853.472072] RIP [<
ffffffff811df514>] kmem_cache_alloc+0x74/0x1e0
[ 853.472971] RSP <
ffff88103726fc50>
Fixes: 726b85487067 ("qla2xxx: Add framework for async fabric discovery")
Cc: <stable@vger.kernel.org>
Signed-off-by: Giridhar Malavali <giridhar.malavali@cavium.com>
Reviewed-by: Ewan D. Milne <emilne@redhat.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
"Async done-%s res %x, WWPN %8phC \n",
sp->name, res, fcport->port_name);
+ if (res == QLA_FUNCTION_TIMEOUT)
+ return;
+
if (res == (DID_ERROR << 16)) {
/* entry status error */
goto done;
struct srb_iocb *iocb;
struct req_que *req;
unsigned long flags;
+ struct qla_hw_data *ha = sp->vha->hw;
- spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags);
+ WARN_ON(irqs_disabled());
+ spin_lock_irqsave(&ha->hardware_lock, flags);
req = sp->qpair->req;
req->outstanding_cmds[sp->handle] = NULL;
iocb = &sp->u.iocb_cmd;
- spin_unlock_irqrestore(sp->qpair->qp_lock_ptr, flags);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
iocb->timeout(sp);
}
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+ if (res == QLA_FUNCTION_TIMEOUT)
+ return;
+
+ if (res == QLA_FUNCTION_TIMEOUT) {
+ dma_pool_free(sp->vha->hw->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
+ sp->u.iocb_cmd.u.mbx.in_dma);
+ return;
+ }
+
memset(&ea, 0, sizeof(ea));
ea.event = FCME_GPDB_DONE;
ea.fcport = fcport;