diff options
author | Xiaotian Feng <dfeng@redhat.com> | 2010-01-29 05:09:30 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-08 14:40:18 -0500 |
commit | 0f19bc681ed0849a2b95778460a0a8132e3700e2 (patch) | |
tree | b6e0fc96f341fe4020c601f1b188d0de1e5375b4 /drivers/scsi | |
parent | 7dec9cf1dfa283feca4b761160112ea4838a6a8c (diff) |
[SCSI] qla2xxx: make msix interrupt handler safe for irq
Yinghai has reported a lockdep warning on qla2xxx:
[ 77.965784] WARNING: at kernel/lockdep.c:2332
trace_hardirqs_on_caller+0xc6/0x14b()
[ 77.977492] Hardware name: Sun
[ 77.979485] Modules linked in:
[ 77.994337] Pid: 0, comm: swapper Not tainted
2.6.33-rc4-tip-yh-03949-g3a8e3f5-dirty #64
[ 78.000120] Call Trace:
[ 78.013298] <IRQ> [<ffffffff81076b54>] warn_slowpath_common+0x7c/0x94
[ 78.017746] [<ffffffff81cd712c>] ? _raw_spin_unlock_irq+0x30/0x36
[ 78.035171] [<ffffffff81076b80>] warn_slowpath_null+0x14/0x16
[ 78.040152] [<ffffffff810a2ae8>] trace_hardirqs_on_caller+0xc6/0x14b
[ 78.055400] [<ffffffff810a2b7a>] trace_hardirqs_on+0xd/0xf
[ 78.058951] [<ffffffff81cd712c>] _raw_spin_unlock_irq+0x30/0x36
[ 78.074889] [<ffffffff816461ef>] qla24xx_msix_default+0x243/0x281
[ 78.091598] [<ffffffff810a5752>] ? __lock_release+0xa5/0xae
[ 78.096799] [<ffffffff810c02ae>] handle_IRQ_event+0x53/0x113
[ 78.111568] [<ffffffff810c2061>] handle_edge_irq+0xf3/0x13b
[ 78.116255] [<ffffffff81035109>] handle_irq+0x24/0x2f
[ 78.132063] [<ffffffff81cdc4b4>] do_IRQ+0x5c/0xc3
[ 78.134684] [<ffffffff81cd7393>] ret_from_intr+0x0/0xf
[ 78.137903] <EOI> [<ffffffff81039a56>] ? mwait_idle+0xaf/0xbb
[ 78.155674] [<ffffffff81039a4d>] ? mwait_idle+0xa6/0xbb
[ 78.158600] [<ffffffff81031c7c>] cpu_idle+0x61/0xa1
[ 78.174333] [<ffffffff81c85d7a>] rest_init+0x7e/0x80
[ 78.178122] [<ffffffff82832d1f>] start_kernel+0x316/0x31d
[ 78.193623] [<ffffffff82832297>] x86_64_start_reservations+0xa7/0xab
[ 78.198924] [<ffffffff8283237f>] x86_64_start_kernel+0xe4/0xeb
[ 78.214540] ---[ end trace be4529f30a2e4ef5 ]---
This was happened when qla2xxx msix interrupt handler is trying to enable
IRQs by spin_unlock_irq(). We should make interrupt handler safe for IRQs,
use spin_lock_irqsave/spin_unlock_irqrestore, this will not break the IRQs
status in interrupt handler.
Reported-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
Acked-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ffd0efdff40e..0ced91c5ebd3 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1917,6 +1917,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) | |||
1917 | struct rsp_que *rsp; | 1917 | struct rsp_que *rsp; |
1918 | struct device_reg_24xx __iomem *reg; | 1918 | struct device_reg_24xx __iomem *reg; |
1919 | struct scsi_qla_host *vha; | 1919 | struct scsi_qla_host *vha; |
1920 | unsigned long flags; | ||
1920 | 1921 | ||
1921 | rsp = (struct rsp_que *) dev_id; | 1922 | rsp = (struct rsp_que *) dev_id; |
1922 | if (!rsp) { | 1923 | if (!rsp) { |
@@ -1927,7 +1928,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) | |||
1927 | ha = rsp->hw; | 1928 | ha = rsp->hw; |
1928 | reg = &ha->iobase->isp24; | 1929 | reg = &ha->iobase->isp24; |
1929 | 1930 | ||
1930 | spin_lock_irq(&ha->hardware_lock); | 1931 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1931 | 1932 | ||
1932 | vha = qla25xx_get_host(rsp); | 1933 | vha = qla25xx_get_host(rsp); |
1933 | qla24xx_process_response_queue(vha, rsp); | 1934 | qla24xx_process_response_queue(vha, rsp); |
@@ -1935,7 +1936,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) | |||
1935 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 1936 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); |
1936 | RD_REG_DWORD_RELAXED(®->hccr); | 1937 | RD_REG_DWORD_RELAXED(®->hccr); |
1937 | } | 1938 | } |
1938 | spin_unlock_irq(&ha->hardware_lock); | 1939 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1939 | 1940 | ||
1940 | return IRQ_HANDLED; | 1941 | return IRQ_HANDLED; |
1941 | } | 1942 | } |
@@ -1946,6 +1947,7 @@ qla25xx_msix_rsp_q(int irq, void *dev_id) | |||
1946 | struct qla_hw_data *ha; | 1947 | struct qla_hw_data *ha; |
1947 | struct rsp_que *rsp; | 1948 | struct rsp_que *rsp; |
1948 | struct device_reg_24xx __iomem *reg; | 1949 | struct device_reg_24xx __iomem *reg; |
1950 | unsigned long flags; | ||
1949 | 1951 | ||
1950 | rsp = (struct rsp_que *) dev_id; | 1952 | rsp = (struct rsp_que *) dev_id; |
1951 | if (!rsp) { | 1953 | if (!rsp) { |
@@ -1958,10 +1960,10 @@ qla25xx_msix_rsp_q(int irq, void *dev_id) | |||
1958 | /* Clear the interrupt, if enabled, for this response queue */ | 1960 | /* Clear the interrupt, if enabled, for this response queue */ |
1959 | if (rsp->options & ~BIT_6) { | 1961 | if (rsp->options & ~BIT_6) { |
1960 | reg = &ha->iobase->isp24; | 1962 | reg = &ha->iobase->isp24; |
1961 | spin_lock_irq(&ha->hardware_lock); | 1963 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1962 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 1964 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); |
1963 | RD_REG_DWORD_RELAXED(®->hccr); | 1965 | RD_REG_DWORD_RELAXED(®->hccr); |
1964 | spin_unlock_irq(&ha->hardware_lock); | 1966 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1965 | } | 1967 | } |
1966 | queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work); | 1968 | queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work); |
1967 | 1969 | ||
@@ -1979,6 +1981,7 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
1979 | uint32_t stat; | 1981 | uint32_t stat; |
1980 | uint32_t hccr; | 1982 | uint32_t hccr; |
1981 | uint16_t mb[4]; | 1983 | uint16_t mb[4]; |
1984 | unsigned long flags; | ||
1982 | 1985 | ||
1983 | rsp = (struct rsp_que *) dev_id; | 1986 | rsp = (struct rsp_que *) dev_id; |
1984 | if (!rsp) { | 1987 | if (!rsp) { |
@@ -1990,7 +1993,7 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
1990 | reg = &ha->iobase->isp24; | 1993 | reg = &ha->iobase->isp24; |
1991 | status = 0; | 1994 | status = 0; |
1992 | 1995 | ||
1993 | spin_lock_irq(&ha->hardware_lock); | 1996 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1994 | vha = pci_get_drvdata(ha->pdev); | 1997 | vha = pci_get_drvdata(ha->pdev); |
1995 | do { | 1998 | do { |
1996 | stat = RD_REG_DWORD(®->host_status); | 1999 | stat = RD_REG_DWORD(®->host_status); |
@@ -2039,7 +2042,7 @@ qla24xx_msix_default(int irq, void *dev_id) | |||
2039 | } | 2042 | } |
2040 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); | 2043 | WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); |
2041 | } while (0); | 2044 | } while (0); |
2042 | spin_unlock_irq(&ha->hardware_lock); | 2045 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2043 | 2046 | ||
2044 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && | 2047 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && |
2045 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { | 2048 | (status & MBX_INTERRUPT) && ha->flags.mbox_int) { |