diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-11-04 16:35:06 +0100 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-11-05 18:44:37 +0100 |
commit | 45316a86a67934ab499dcfac44c91aa8f39c4c78 (patch) | |
tree | a5bd349ddb25034751ac3129677bbf19604cfd7b /drivers/s390/scsi | |
parent | [SCSI] zfcp: Dont clear reference from SCSI device to unit (diff) | |
download | linux-45316a86a67934ab499dcfac44c91aa8f39c4c78.tar.xz linux-45316a86a67934ab499dcfac44c91aa8f39c4c78.zip |
[SCSI] zfcp: fix req_list_locking.
The per adapter req_list_lock must be held with interrupts disabled, otherwise
we might end up with nice deadlocks as lockdep tells us (see below).
zfcp 0.0.1804: QDIO problem occurred.
=========================================================
[ INFO: possible irq lock inversion dependency detected ]
2.6.27-rc8-00035-g4a77035-dirty #86
---------------------------------------------------------
swapper/0 just changed the state of lock:
(&adapter->erp_lock){++..}, at: [<00000000002c82ae>] zfcp_erp_adapter_reopen+0x4e/0x8c
but this lock took another, hard-irq-unsafe lock in the past:
(&adapter->req_list_lock){-+..}
and interrupts could create inverse lock ordering between them.
[tons of backtraces, but only the interesting part follows]
the second lock's dependencies:
-> (&adapter->req_list_lock){-+..} ops: 2280627634176 {
initial-use at:
[<0000000000071f10>] __lock_acquire+0x504/0x18bc
[<000000000007335c>] lock_acquire+0x94/0xbc
[<00000000003d7224>] _spin_lock_irqsave+0x6c/0xb0
[<00000000002cf684>] zfcp_fsf_req_dismiss_all+0x50/0x140
[<00000000002c87ee>] zfcp_erp_adapter_strategy_generic+0x66/0x3d0
[<00000000002c9498>] zfcp_erp_thread+0x88c/0x1318
[<000000000001b0d2>] kernel_thread_starter+0x6/0xc
[<000000000001b0cc>] kernel_thread_starter+0x0/0xc
in-softirq-W at:
[<0000000000072172>] __lock_acquire+0x766/0x18bc
[<000000000007335c>] lock_acquire+0x94/0xbc
[<00000000003d7224>] _spin_lock_irqsave+0x6c/0xb0
[<00000000002ca73e>] zfcp_qdio_int_resp+0xbe/0x2ac
[<000000000027a1d6>] qdio_kick_inbound_handler+0x82/0xa0
[<000000000027daba>] tiqdio_inbound_processing+0x62/0xf8
[<0000000000047ba4>] tasklet_action+0x100/0x1f4
[<0000000000048b5a>] __do_softirq+0xae/0x154
[<0000000000021e4a>] do_softirq+0xea/0xf0
[<00000000000485de>] irq_exit+0xde/0xe8
[<0000000000268c64>] do_IRQ+0x160/0x1fc
[<00000000000261a2>] io_return+0x0/0x8
[<000000000001b8f8>] cpu_idle+0x17c/0x224
hardirq-on-W at:
[<0000000000072190>] __lock_acquire+0x784/0x18bc
[<000000000007335c>] lock_acquire+0x94/0xbc
[<00000000003d702c>] _spin_lock+0x5c/0x9c
[<00000000002caff6>] zfcp_fsf_req_send+0x3e/0x158
[<00000000002ce7fe>] zfcp_fsf_exchange_config_data+0x106/0x124
[<00000000002c8948>] zfcp_erp_adapter_strategy_generic+0x1c0/0x3d0
[<00000000002c98ea>] zfcp_erp_thread+0xcde/0x1318
[<000000000001b0d2>] kernel_thread_starter+0x6/0xc
[<000000000001b0cc>] kernel_thread_starter+0x0/0xc
}
... key at: [<0000000000e356c8>] __key.26629+0x0/0x8
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Christof Schmitt <christof.schmit@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5ae1d497e5ed..694d9c9ea7cc 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -770,13 +770,14 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; struct zfcp_qdio_queue *req_q = &adapter->req_q; + unsigned long flags; int idx; /* put allocated FSF request into hash table */ - spin_lock(&adapter->req_list_lock); + spin_lock_irqsave(&adapter->req_list_lock, flags); idx = zfcp_reqlist_hash(req->req_id); list_add_tail(&req->list, &adapter->req_list[idx]); - spin_unlock(&adapter->req_list_lock); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); req->qdio_outb_usage = atomic_read(&req_q->count); req->issued = get_clock(); |