diff options
author | jack wang <jack_wang@usish.com> | 2009-12-07 04:22:36 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-10 10:58:54 -0500 |
commit | 9e79e12554d651f586ff2364e69a8e9cd5e9dbcb (patch) | |
tree | 034b6b41675573b5458501a04a8c635229c33fcd /drivers | |
parent | edd163687ea59f01d6b43c9e1fdaa0126fa30191 (diff) |
[SCSI] pm8001: Fix for sata io circular lock dependency.
This patch fix for sata IO circular lock dependency. When we call task_done
for SATA IO, we have got pm8001_ha->lock ,and in sas_ata_task_done, it will
get (dev->sata_dev.ap->lock. then cause circular lock dependency .So we
should drop pm8001_ha->lock when we call task_done for SATA task.
Signed-off-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: Lindar Liu <lindar_liu@usish.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index a3de306b9045..68695b72e1ef 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -1901,7 +1901,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
1901 | { | 1901 | { |
1902 | struct sas_task *t; | 1902 | struct sas_task *t; |
1903 | struct pm8001_ccb_info *ccb; | 1903 | struct pm8001_ccb_info *ccb; |
1904 | unsigned long flags; | 1904 | unsigned long flags = 0; |
1905 | u32 param; | 1905 | u32 param; |
1906 | u32 status; | 1906 | u32 status; |
1907 | u32 tag; | 1907 | u32 tag; |
@@ -2040,7 +2040,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2040 | ts->stat = SAS_QUEUE_FULL; | 2040 | ts->stat = SAS_QUEUE_FULL; |
2041 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2041 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2042 | mb();/*in order to force CPU ordering*/ | 2042 | mb();/*in order to force CPU ordering*/ |
2043 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2043 | t->task_done(t); | 2044 | t->task_done(t); |
2045 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2044 | return; | 2046 | return; |
2045 | } | 2047 | } |
2046 | break; | 2048 | break; |
@@ -2058,7 +2060,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2058 | ts->stat = SAS_QUEUE_FULL; | 2060 | ts->stat = SAS_QUEUE_FULL; |
2059 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2061 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2060 | mb();/*ditto*/ | 2062 | mb();/*ditto*/ |
2063 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2061 | t->task_done(t); | 2064 | t->task_done(t); |
2065 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2062 | return; | 2066 | return; |
2063 | } | 2067 | } |
2064 | break; | 2068 | break; |
@@ -2084,7 +2088,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2084 | ts->stat = SAS_QUEUE_FULL; | 2088 | ts->stat = SAS_QUEUE_FULL; |
2085 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2089 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2086 | mb();/* ditto*/ | 2090 | mb();/* ditto*/ |
2091 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2087 | t->task_done(t); | 2092 | t->task_done(t); |
2093 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2088 | return; | 2094 | return; |
2089 | } | 2095 | } |
2090 | break; | 2096 | break; |
@@ -2149,7 +2155,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2149 | ts->stat = SAS_QUEUE_FULL; | 2155 | ts->stat = SAS_QUEUE_FULL; |
2150 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2156 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2151 | mb();/*ditto*/ | 2157 | mb();/*ditto*/ |
2158 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2152 | t->task_done(t); | 2159 | t->task_done(t); |
2160 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2153 | return; | 2161 | return; |
2154 | } | 2162 | } |
2155 | break; | 2163 | break; |
@@ -2171,7 +2179,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2171 | ts->stat = SAS_QUEUE_FULL; | 2179 | ts->stat = SAS_QUEUE_FULL; |
2172 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2180 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2173 | mb();/*ditto*/ | 2181 | mb();/*ditto*/ |
2182 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2174 | t->task_done(t); | 2183 | t->task_done(t); |
2184 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2175 | return; | 2185 | return; |
2176 | } | 2186 | } |
2177 | break; | 2187 | break; |
@@ -2200,11 +2210,20 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2200 | " resp 0x%x stat 0x%x but aborted by upper layer!\n", | 2210 | " resp 0x%x stat 0x%x but aborted by upper layer!\n", |
2201 | t, status, ts->resp, ts->stat)); | 2211 | t, status, ts->resp, ts->stat)); |
2202 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2212 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2203 | } else { | 2213 | } else if (t->uldd_task) { |
2204 | spin_unlock_irqrestore(&t->task_state_lock, flags); | 2214 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
2205 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2215 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2206 | mb();/* ditto */ | 2216 | mb();/* ditto */ |
2217 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2218 | t->task_done(t); | ||
2219 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2220 | } else if (!t->uldd_task) { | ||
2221 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
2222 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
2223 | mb();/*ditto*/ | ||
2224 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2207 | t->task_done(t); | 2225 | t->task_done(t); |
2226 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2208 | } | 2227 | } |
2209 | } | 2228 | } |
2210 | 2229 | ||
@@ -2212,7 +2231,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
2212 | static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | 2231 | static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) |
2213 | { | 2232 | { |
2214 | struct sas_task *t; | 2233 | struct sas_task *t; |
2215 | unsigned long flags; | 2234 | unsigned long flags = 0; |
2216 | struct task_status_struct *ts; | 2235 | struct task_status_struct *ts; |
2217 | struct pm8001_ccb_info *ccb; | 2236 | struct pm8001_ccb_info *ccb; |
2218 | struct pm8001_device *pm8001_dev; | 2237 | struct pm8001_device *pm8001_dev; |
@@ -2292,7 +2311,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
2292 | ts->stat = SAS_QUEUE_FULL; | 2311 | ts->stat = SAS_QUEUE_FULL; |
2293 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2312 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2294 | mb();/*ditto*/ | 2313 | mb();/*ditto*/ |
2314 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2295 | t->task_done(t); | 2315 | t->task_done(t); |
2316 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2296 | return; | 2317 | return; |
2297 | } | 2318 | } |
2298 | break; | 2319 | break; |
@@ -2401,11 +2422,20 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
2401 | " resp 0x%x stat 0x%x but aborted by upper layer!\n", | 2422 | " resp 0x%x stat 0x%x but aborted by upper layer!\n", |
2402 | t, event, ts->resp, ts->stat)); | 2423 | t, event, ts->resp, ts->stat)); |
2403 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2424 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2404 | } else { | 2425 | } else if (t->uldd_task) { |
2405 | spin_unlock_irqrestore(&t->task_state_lock, flags); | 2426 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
2406 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 2427 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
2407 | mb();/* in order to force CPU ordering */ | 2428 | mb();/* ditto */ |
2429 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2430 | t->task_done(t); | ||
2431 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2432 | } else if (!t->uldd_task) { | ||
2433 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
2434 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
2435 | mb();/*ditto*/ | ||
2436 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
2408 | t->task_done(t); | 2437 | t->task_done(t); |
2438 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
2409 | } | 2439 | } |
2410 | } | 2440 | } |
2411 | 2441 | ||