From: Jeff Garzik <jgarzik@pobox.com>
To: Andrew Morton <akpm@osdl.org>, Linus Torvalds <torvalds@osdl.org>
Cc: linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org
Subject: [git patch] libata fix
Date: Fri, 16 Sep 2005 06:03:51 -0400 [thread overview]
Message-ID: <20050916100351.GA21329@havoc.gtf.org> (raw)
Please pull from 'upstream-fixes' branch of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
to obtain the following fix:
drivers/scsi/libata-core.c | 37 +++++++++++++++++++++++--------------
1 files changed, 23 insertions(+), 14 deletions(-)
commit 7fb6ec287a05d7a71ec086d8bc9a452d5e16ff1a
Author: Jeff Garzik <jgarzik@pobox.com>
Date: Fri Sep 16 06:01:48 2005 -0400
[libata] fix PIO completion race
Make sure we that completion is the final action we take; prior to this
change, another CPU may have changed ap->pio_task_state before we tested
it a final time.
Spotted by, and original patch by Albert Lee @ IBM.
Also includes a minor optimization: eliminate a ton of unnecessary
queue_work() calls, simply by jumping to the beginning of the FSM
function ata_pio_task().
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct
*
* LOCKING:
* None. (executing in kernel thread context)
+ *
+ * RETURNS:
+ * Non-zero if qc completed, zero otherwise.
*/
-static void ata_pio_complete (struct ata_port *ap)
+static int ata_pio_complete (struct ata_port *ap)
{
struct ata_queued_cmd *qc;
u8 drv_stat;
@@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
ap->pio_task_state = PIO_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
- return;
+ return 0;
}
}
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
ap->pio_task_state = PIO_ST_ERR;
- return;
+ return 0;
}
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata
ap->pio_task_state = PIO_ST_IDLE;
ata_poll_qc_complete(qc, drv_stat);
+
+ /* another command may start at this point */
+
+ return 1;
}
@@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata
next_sg:
if (unlikely(qc->cursg >= qc->n_elem)) {
- /*
+ /*
* The end of qc->sg is reached and the device expects
* more data to transfer. In order not to overrun qc->sg
* and fulfill length specified in the byte count register,
@@ -2721,7 +2728,7 @@ next_sg:
unsigned int i;
if (words) /* warning if bytes > 1 */
- printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
+ printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
ap->id, bytes);
for (i = 0; i < words; i++)
@@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_por
if (is_atapi_taskfile(&qc->tf)) {
/* no more data to transfer or unsupported ATAPI command */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_IDLE;
-
- ata_poll_qc_complete(qc, status);
+ ap->pio_task_state = PIO_ST_LAST;
return;
}
@@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_por
static void ata_pio_task(void *_data)
{
struct ata_port *ap = _data;
- unsigned long timeout = 0;
+ unsigned long timeout;
+ int qc_completed;
+
+fsm_start:
+ timeout = 0;
+ qc_completed = 0;
switch (ap->pio_task_state) {
case PIO_ST_IDLE:
@@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data)
break;
case PIO_ST_LAST:
- ata_pio_complete(ap);
+ qc_completed = ata_pio_complete(ap);
break;
case PIO_ST_POLL:
@@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data)
}
if (timeout)
- queue_delayed_work(ata_wq, &ap->pio_task,
- timeout);
- else
- queue_work(ata_wq, &ap->pio_task);
+ queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+ else if (!qc_completed)
+ goto fsm_start;
}
static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
next reply other threads:[~2005-09-16 10:03 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-09-16 10:03 Jeff Garzik [this message]
-- strict thread matches above, loose matches on Subject: below --
2011-06-10 1:59 [git patch] libata fix Jeff Garzik
2011-05-14 18:55 Jeff Garzik
2010-11-19 19:19 Jeff Garzik
2010-09-28 19:16 Jeff Garzik
2010-03-29 20:22 Jeff Garzik
2010-01-21 4:29 Jeff Garzik
2009-12-07 16:51 Jeff Garzik
2009-11-20 11:44 Jeff Garzik
2008-11-14 23:56 Jeff Garzik
2008-11-15 20:30 ` Alan Cox
2008-05-09 20:59 Jeff Garzik
2007-10-02 17:17 Jeff Garzik
2007-06-04 20:54 Jeff Garzik
2006-09-25 19:35 Jeff Garzik
2006-09-25 20:27 ` Alan Cox
2006-09-25 20:29 ` Jeff Garzik
2006-09-25 20:30 ` Alan Cox
2006-09-25 20:08 ` Jeff Garzik
2006-06-12 14:26 Jeff Garzik
2006-04-12 22:15 Jeff Garzik
2006-03-13 0:29 Jeff Garzik
2005-12-24 15:13 Jeff Garzik
2005-07-31 23:29 Jeff Garzik
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=20050916100351.GA21329@havoc.gtf.org \
--to=jgarzik@pobox.com \
--cc=akpm@osdl.org \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).