* [PATCH] SCSI: aic7xxx replace semaphores
@ 2004-10-20 20:08 Thomas Gleixner
0 siblings, 0 replies; only message in thread
From: Thomas Gleixner @ 2004-10-20 20:08 UTC (permalink / raw)
To: Andrew Morton; +Cc: Ingo Molnar, LKML, James Bottomley, SCSI
Use wait_event, completion instead of semaphores
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Ingo Molnar <mingo@elte.hu>
---
2.6.9-bk-041020-thomas/drivers/scsi/aic7xxx/aic7xxx_osm.c | 84
++++++--------
2.6.9-bk-041020-thomas/drivers/scsi/aic7xxx/aic7xxx_osm.h | 8 -
2 files changed, 42 insertions(+), 50 deletions(-)
diff -puN drivers/scsi/aic7xxx/aic7xxx_osm.c~aic7xxx
drivers/scsi/aic7xxx/aic7xxx_osm.c
---
2.6.9-bk-041020/drivers/scsi/aic7xxx/aic7xxx_osm.c~aic7xxx 2004-10-20
16:06:12.000000000 +0200
+++ 2.6.9-bk-041020-thomas/drivers/scsi/aic7xxx/aic7xxx_osm.c 2004-10-20
16:13:23.000000000 +0200
@@ -1873,9 +1873,10 @@ ahc_platform_alloc(struct ahc_softc *ahc
ahc->platform_data->completeq_timer.data = (u_long)ahc;
ahc->platform_data->completeq_timer.function =
(ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
- init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
- init_MUTEX_LOCKED(&ahc->platform_data->dv_sem);
- init_MUTEX_LOCKED(&ahc->platform_data->dv_cmd_sem);
+ init_waitqueue_head(&ahc->platform_data->eh_done);
+ init_waitqueue_head(&ahc->platform_data->dv_done);
+ init_waitqueue_head(&ahc->platform_data->dv_cmd_done);
+ init_completion(&ahc->platform_data->dv_exit);
tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,
(unsigned long)ahc);
ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
@@ -2156,7 +2157,7 @@ ahc_linux_start_dv(struct ahc_softc *ahc
ahc_linux_freeze_simq(ahc);
/* Wake up the DV kthread */
- up(&ahc->platform_data->dv_sem);
+ wake_up(&ahc->platform_data->dv_done);
}
}
@@ -2169,39 +2170,22 @@ ahc_linux_kill_dv_thread(struct ahc_soft
if (ahc->platform_data->dv_pid != 0) {
ahc->platform_data->flags |= AHC_DV_SHUTDOWN;
ahc_unlock(ahc, &s);
- up(&ahc->platform_data->dv_sem);
+ wake_up(&ahc->platform_data->dv_done);
- /*
- * Use the eh_sem as an indicator that the
- * dv thread is exiting. Note that the dv
- * thread must still return after performing
- * the up on our semaphore before it has
- * completely exited this module. Unfortunately,
- * there seems to be no easy way to wait for the
- * exit of a thread for which you are not the
- * parent (dv threads are parented by init).
- * Cross your fingers...
- */
- down(&ahc->platform_data->eh_sem);
-
- /*
- * Mark the dv thread as already dead. This
- * avoids attempting to kill it a second time.
- * This is necessary because we must kill the
- * DV thread before calling ahc_free() in the
- * module shutdown case to avoid bogus locking
- * in the SCSI mid-layer, but we ahc_free() is
- * called without killing the DV thread in the
- * instance detach case, so ahc_platform_free()
- * calls us again to verify that the DV thread
- * is dead.
- */
- ahc->platform_data->dv_pid = 0;
+ /* Wait until the thread has exited */
+ wait_for_completion(&ahc->platform_data->dv_exit);
} else {
ahc_unlock(ahc, &s);
}
}
+#define AHC_WAIT_FOR_WORK \
+ (ahc->platform_data->flags & (AHC_DV_SHUTDOWN | AHC_DV_ACTIVE))
+#define AHC_WAIT_FOR_SIMQ_EMPTY \
+ (!(ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY))
+#define AHC_WAIT_FOR_SIMQ_RELEASE \
+ (!(ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE))
+
static int
ahc_linux_dv_thread(void *data)
{
@@ -2235,11 +2219,9 @@ ahc_linux_dv_thread(void *data)
unlock_kernel();
while (1) {
- /*
- * Use down_interruptible() rather than down() to
- * avoid inclusion in the load average.
- */
- down_interruptible(&ahc->platform_data->dv_sem);
+ /* Wait for work */
+ wait_event_interruptible(ahc->platform_data->dv_done,
+ AHC_WAIT_FOR_WORK);
/* Check to see if we've been signaled to exit */
ahc_lock(ahc, &s);
@@ -2262,7 +2244,8 @@ ahc_linux_dv_thread(void *data)
while (LIST_FIRST(&ahc->pending_scbs) != NULL) {
ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_EMPTY;
ahc_unlock(ahc, &s);
- down_interruptible(&ahc->platform_data->dv_sem);
+ wait_event_interruptible(ahc->platform_data->dv_done,
+ AHC_WAIT_FOR_SIMQ_EMPTY);
ahc_lock(ahc, &s);
}
@@ -2273,7 +2256,8 @@ ahc_linux_dv_thread(void *data)
while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
ahc_unlock(ahc, &s);
- down_interruptible(&ahc->platform_data->dv_sem);
+ wait_event_interruptible(ahc->platform_data->dv_done,
+ AHC_WAIT_FOR_SIMQ_RELEASE);
ahc_lock(ahc, &s);
}
ahc_unlock(ahc, &s);
@@ -2291,7 +2275,9 @@ ahc_linux_dv_thread(void *data)
*/
ahc_linux_release_simq((u_long)ahc);
}
- up(&ahc->platform_data->eh_sem);
+ /* Mark it as gone */
+ ahc->platform_data->dv_pid = 0;
+ complete(&ahc->platform_data->dv_exit);
return (0);
}
@@ -2454,7 +2440,9 @@ ahc_linux_dv_target(struct ahc_softc *ah
#else
spin_unlock_irqrestore(&io_request_lock, s);
#endif
- down_interruptible(&ahc->platform_data->dv_cmd_sem);
+ wait_event_interruptible(ahc->platform_data->dv_cmd_done,
+ !timer_pending(&cmd->eh_timeout));
+
/*
* Wait for the SIMQ to be released so that DV is the
* only reason the queue is frozen.
@@ -2463,7 +2451,8 @@ ahc_linux_dv_target(struct ahc_softc *ah
while (AHC_DV_SIMQ_FROZEN(ahc) == 0) {
ahc->platform_data->flags |= AHC_DV_WAIT_SIMQ_RELEASE;
ahc_unlock(ahc, &s);
- down_interruptible(&ahc->platform_data->dv_sem);
+ wait_event_interruptible(ahc->platform_data->dv_done,
+ AHC_WAIT_FOR_SIMQ_RELEASE);
ahc_lock(ahc, &s);
}
ahc_unlock(ahc, &s);
@@ -3404,7 +3393,7 @@ ahc_linux_dv_complete(struct scsi_cmnd *
#endif
/* Wake up the state machine */
- up(&ahc->platform_data->dv_cmd_sem);
+ wake_up(&ahc->platform_data->dv_cmd_done);
}
static void
@@ -4164,7 +4153,7 @@ ahc_done(struct ahc_softc *ahc, struct s
ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
- up(&ahc->platform_data->eh_sem);
+ wake_up(&ahc->platform_data->eh_done);
}
}
@@ -4174,7 +4163,7 @@ ahc_done(struct ahc_softc *ahc, struct s
if ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_EMPTY) != 0
&& LIST_FIRST(&ahc->pending_scbs) == NULL) {
ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_EMPTY;
- up(&ahc->platform_data->dv_sem);
+ wake_up(&ahc->platform_data->dv_done);
}
}
@@ -4563,7 +4552,7 @@ ahc_linux_sem_timeout(u_long arg)
ahc_lock(ahc, &s);
if ((ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE) != 0) {
ahc->platform_data->flags &= ~AHC_UP_EH_SEMAPHORE;
- up(&ahc->platform_data->eh_sem);
+ wake_up(&ahc->platform_data->eh_done);
}
ahc_unlock(ahc, &s);
}
@@ -4600,7 +4589,7 @@ ahc_linux_release_simq(u_long arg)
if (AHC_DV_SIMQ_FROZEN(ahc)
&& ((ahc->platform_data->flags & AHC_DV_WAIT_SIMQ_RELEASE) != 0)) {
ahc->platform_data->flags &= ~AHC_DV_WAIT_SIMQ_RELEASE;
- up(&ahc->platform_data->dv_sem);
+ wake_up(&ahc->platform_data->dv_done);
}
ahc_schedule_runq(ahc);
ahc_unlock(ahc, &s);
@@ -4952,7 +4941,8 @@ done:
timer.function = ahc_linux_sem_timeout;
add_timer(&timer);
printf("Recovery code sleeping\n");
- down(&ahc->platform_data->eh_sem);
+ wait_event(ahc->platform_data->eh_done,
+ !(ahc->platform_data->flags & AHC_UP_EH_SEMAPHORE));
printf("Recovery code awake\n");
ret = del_timer_sync(&timer);
if (ret == 0) {
diff -puN drivers/scsi/aic7xxx/aic7xxx_osm.h~aic7xxx
drivers/scsi/aic7xxx/aic7xxx_osm.h
---
2.6.9-bk-041020/drivers/scsi/aic7xxx/aic7xxx_osm.h~aic7xxx 2004-10-20
16:06:23.000000000 +0200
+++ 2.6.9-bk-041020-thomas/drivers/scsi/aic7xxx/aic7xxx_osm.h 2004-10-20
16:08:38.000000000 +0200
@@ -534,11 +534,13 @@ struct ahc_platform_data {
pid_t dv_pid;
struct timer_list completeq_timer;
struct timer_list reset_timer;
- struct semaphore eh_sem;
- struct semaphore dv_sem;
- struct semaphore dv_cmd_sem; /* XXX This needs to be in
+ wait_queue_head_t eh_done;
+ wait_queue_head_t dv_done;
+ wait_queue_head_t dv_cmd_done; /* XXX This needs to be in
* the target struct
*/
+ struct completion dv_exit;
+
struct scsi_device *dv_scsi_dev;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHC_LINUX_NOIRQ ((uint32_t)~0)
_
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2004-10-20 20:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-20 20:08 [PATCH] SCSI: aic7xxx replace semaphores Thomas Gleixner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.