diff options
author | Christoph Hellwig <hch@lst.de> | 2006-02-06 09:40:45 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-02-28 00:08:37 -0500 |
commit | 8cac814501677e9f6a824cf4d423122ac8d67fcb (patch) | |
tree | 60dfd19ceaf02739cbab9d9b42cb6b8e9c11e543 /drivers/scsi/aic7xxx/aic7xxx_osm.c | |
parent | fe27381d16c6683c55e618360d0d11bd43647e43 (diff) |
[SCSI] aic7xxx: semaphore to completion conversion
On Tue, Jan 31, 2006 at 06:20:18PM +0100, Christoph Hellwig wrote:
> switch eh_sem to a completion. due to wait_for_completion_timeout this
> also nicely simplifies the code. Unfortunately it's untested, so if
> someone with the hardware could give it a try that would be nice. Once
> it works the same thing can be applied to aic79xx.
New version that switches to the common onstack completion and just a
pointer in the platform_data struct idiom. This gets rid of all the
flags fiddling.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aic7xxx/aic7xxx_osm.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 45 |
1 files changed, 11 insertions, 34 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 051970efba68..2c801672d8bb 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -373,7 +373,6 @@ static void ahc_linux_handle_scsi_status(struct ahc_softc *, | |||
373 | struct scb *); | 373 | struct scb *); |
374 | static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, | 374 | static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, |
375 | struct scsi_cmnd *cmd); | 375 | struct scsi_cmnd *cmd); |
376 | static void ahc_linux_sem_timeout(u_long arg); | ||
377 | static void ahc_linux_freeze_simq(struct ahc_softc *ahc); | 376 | static void ahc_linux_freeze_simq(struct ahc_softc *ahc); |
378 | static void ahc_linux_release_simq(struct ahc_softc *ahc); | 377 | static void ahc_linux_release_simq(struct ahc_softc *ahc); |
379 | static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); | 378 | static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag); |
@@ -1193,7 +1192,6 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) | |||
1193 | memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); | 1192 | memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); |
1194 | ahc->platform_data->irq = AHC_LINUX_NOIRQ; | 1193 | ahc->platform_data->irq = AHC_LINUX_NOIRQ; |
1195 | ahc_lockinit(ahc); | 1194 | ahc_lockinit(ahc); |
1196 | init_MUTEX_LOCKED(&ahc->platform_data->eh_sem); | ||
1197 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; | 1195 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; |
1198 | ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; | 1196 | ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4; |
1199 | if (aic7xxx_pci_parity == 0) | 1197 | if (aic7xxx_pci_parity == 0) |
@@ -1830,10 +1828,9 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb) | |||
1830 | if (ahc_get_transaction_status(scb) == CAM_BDR_SENT | 1828 | if (ahc_get_transaction_status(scb) == CAM_BDR_SENT |
1831 | || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) | 1829 | || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) |
1832 | ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); | 1830 | ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); |
1833 | if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { | 1831 | |
1834 | ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; | 1832 | if (ahc->platform_data->eh_done) |
1835 | up(&ahc->platform_data->eh_sem); | 1833 | complete(ahc->platform_data->eh_done); |
1836 | } | ||
1837 | } | 1834 | } |
1838 | 1835 | ||
1839 | ahc_free_scb(ahc, scb); | 1836 | ahc_free_scb(ahc, scb); |
@@ -2040,22 +2037,6 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd) | |||
2040 | } | 2037 | } |
2041 | 2038 | ||
2042 | static void | 2039 | static void |
2043 | ahc_linux_sem_timeout(u_long arg) | ||
2044 | { | ||
2045 | struct ahc_softc *ahc; | ||
2046 | u_long s; | ||
2047 | |||
2048 | ahc = (struct ahc_softc *)arg; | ||
2049 | |||
2050 | ahc_lock(ahc, &s); | ||
2051 | if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) { | ||
2052 | ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE; | ||
2053 | up(&ahc->platform_data->eh_sem); | ||
2054 | } | ||
2055 | ahc_unlock(ahc, &s); | ||
2056 | } | ||
2057 | |||
2058 | static void | ||
2059 | ahc_linux_freeze_simq(struct ahc_softc *ahc) | 2040 | ahc_linux_freeze_simq(struct ahc_softc *ahc) |
2060 | { | 2041 | { |
2061 | unsigned long s; | 2042 | unsigned long s; |
@@ -2355,25 +2336,21 @@ done: | |||
2355 | if (paused) | 2336 | if (paused) |
2356 | ahc_unpause(ahc); | 2337 | ahc_unpause(ahc); |
2357 | if (wait) { | 2338 | if (wait) { |
2358 | struct timer_list timer; | 2339 | DECLARE_COMPLETION(done); |
2359 | int ret; | ||
2360 | 2340 | ||
2361 | ahc->platform_data->flags |= AHC_UP_EH_SEMAPHORE; | 2341 | ahc->platform_data->eh_done = &done; |
2362 | ahc_unlock(ahc, &flags); | 2342 | ahc_unlock(ahc, &flags); |
2363 | 2343 | ||
2364 | init_timer(&timer); | ||
2365 | timer.data = (u_long)ahc; | ||
2366 | timer.expires = jiffies + (5 * HZ); | ||
2367 | timer.function = ahc_linux_sem_timeout; | ||
2368 | add_timer(&timer); | ||
2369 | printf("Recovery code sleeping\n"); | 2344 | printf("Recovery code sleeping\n"); |
2370 | down(&ahc->platform_data->eh_sem); | 2345 | if (!wait_for_completion_timeout(&done, 5 * HZ)) { |
2371 | printf("Recovery code awake\n"); | 2346 | ahc_lock(ahc, &flags); |
2372 | ret = del_timer_sync(&timer); | 2347 | ahc->platform_data->eh_done = NULL; |
2373 | if (ret == 0) { | 2348 | ahc_unlock(ahc, &flags); |
2349 | |||
2374 | printf("Timer Expired\n"); | 2350 | printf("Timer Expired\n"); |
2375 | retval = FAILED; | 2351 | retval = FAILED; |
2376 | } | 2352 | } |
2353 | printf("Recovery code awake\n"); | ||
2377 | } else | 2354 | } else |
2378 | ahc_unlock(ahc, &flags); | 2355 | ahc_unlock(ahc, &flags); |
2379 | return (retval); | 2356 | return (retval); |