From: Thomas Gleixner <tglx@tglx.de>
To: Andrew Morton <akpm@osdl.org>
Cc: Ingo Molnar <mingo@elte.hu>, LKML <linux-kernel@vger.kernel.org>,
James Bottomley <James.Bottomley@SteelEye.com>,
SCSI <linux-scsi@vger.kernel.org>
Subject: [PATCH] SCSI: aic7xxx replace semaphores
Date: Wed, 20 Oct 2004 22:08:11 +0200 [thread overview]
Message-ID: <1098302891.25591.2.camel@thomas> (raw)
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)
_
reply other threads:[~2004-10-20 20:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1098302891.25591.2.camel@thomas \
--to=tglx@tglx.de \
--cc=James.Bottomley@SteelEye.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=mingo@elte.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.