summaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2008-11-04 16:35:06 +0100
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-11-05 18:44:37 +0100
commit45316a86a67934ab499dcfac44c91aa8f39c4c78 (patch)
treea5bd349ddb25034751ac3129677bbf19604cfd7b /drivers/s390/scsi
parent[SCSI] zfcp: Dont clear reference from SCSI device to unit (diff)
downloadlinux-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.c5
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();