From: Jeff Garzik <jgarzik@pobox.com>
To: Tejun Heo <htejun@gmail.com>
Cc: Mark Lord <liml@rtr.ca>, Mark Lord <mlord@pobox.com>,
IDE/ATA development list <linux-ide@vger.kernel.org>,
hare@suse.de
Subject: Re: libata total system lockup fix
Date: Thu, 11 Aug 2005 16:13:02 -0400 [thread overview]
Message-ID: <42FBB14E.5040002@pobox.com> (raw)
In-Reply-To: <20050805040105.GA18466@htj.dyndns.org>
Tejun Heo wrote:
> And this is the combined patch against ncq head of libata-dev-2.6
> tree. Commit d032ec9048ff82a704b96b93cfd6f2e8e3a06b19.
>
> Only ata_piix, sata_sil and ahci are converted and all other SATA
> drivers are broken. So, enable only those three SATA drivers when
> compiling with this patch.
Overall, the approach of adding a timeout to the 'special' commands is a
good, and necessary approach.
Comments follow...
> Index: work/drivers/scsi/libata-core.c
> ===================================================================
> --- work.orig/drivers/scsi/libata-core.c 2005-08-05 12:55:08.000000000 +0900
> +++ work/drivers/scsi/libata-core.c 2005-08-05 12:55:50.000000000 +0900
> @@ -49,6 +49,10 @@
>
> #include "libata.h"
>
> +#define ata_for_each_tag(tag, mask) \
> + for (tag = find_first_bit(&mask, ATA_MAX_CMDS); tag < ATA_MAX_CMDS; \
> + tag = find_next_bit(&mask, ATA_MAX_CMDS, tag + 1))
> +
> static unsigned int ata_busy_sleep (struct ata_port *ap,
> unsigned long tmout_pat,
> unsigned long tmout);
> @@ -59,7 +63,6 @@ static int fgb(u32 bitmap);
> static int ata_choose_xfer_mode(struct ata_port *ap,
> u8 *xfer_mode_out,
> unsigned int *xfer_shift_out);
> -static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
> static void __ata_qc_complete(struct ata_queued_cmd *qc);
>
> static unsigned int ata_unique_id = 1;
> @@ -70,6 +73,87 @@ MODULE_DESCRIPTION("Library module for A
> MODULE_LICENSE("GPL");
> MODULE_VERSION(DRV_VERSION);
>
> +static void ata_qc_complete_noop(struct ata_queued_cmd *qc)
> +{
> + /* noop */
> +}
> +
> +static void ata_qc_exec_special_timeout(unsigned long data)
> +{
> + struct completion *wait = (void *)data;
> + complete(wait);
> +}
> +
> +/**
> + * ata_qc_exec_special - execute libata internal special command
> + * @qc: Command to execute
> + * @tmout: timeout in jiffies
> + *
> + * Executes libata internal command with timeout. Timeout and
> + * error conditions are reported via return value. No recovery
> + * action is taken after a command times out. It's caller's duto
> + * to clean up after timeout.
> + *
> + * Also, note that error condition is checked after the qc is
> + * completed, meaning that if another command is issued before
> + * checking the condition, we get the wrong values. As special
> + * cmds are used only for initialization and recovery, this
> + * won't cause any problem currently.
> + *
> + * LOCKING:
> + * None. Should be called with kernel context, might sleep.
> + */
> +
> +static int ata_qc_exec_special(struct ata_queued_cmd *qc, unsigned long tmout)
> +{
> + struct ata_port *ap = qc->ap;
> + DECLARE_COMPLETION(wait);
> + struct timer_list timer;
> + int rc;
> +
> + might_sleep();
> +
> + if (ata_busy_sleep(ap, ATA_TMOUT_SPECIAL_QUICK, ATA_TMOUT_SPECIAL))
> + return -ETIMEDOUT;
> +
> + qc->complete_fn = ata_qc_complete_noop;
> + qc->waiting = &wait;
> +
> + if (tmout) {
> + init_timer(&timer);
> + timer.function = ata_qc_exec_special_timeout;
> + timer.data = (unsigned long)&wait;
> + timer.expires = jiffies + tmout;
> + add_timer(&timer);
Just use mod_timer(), and combine these last two lines into a single one.
> + spin_lock_irq(&ap->host_set->lock);
> + rc = ata_qc_issue(qc);
> + spin_unlock_irq(&ap->host_set->lock);
> +
> + if (rc) {
> + if (tmout)
> + del_timer(&timer);
Use del_timer_sync() here, and for every case where you are not inside a
spinlock.
> + return -EAGAIN; /* any better value for issue failure? */
> + }
> +
> + wait_for_completion(&wait);
> +
> + if (tmout && !del_timer(&timer)) {
> + spin_lock_irq(&ap->host_set->lock);
> + if (qc->waiting == &wait) {
> + ata_qc_complete(qc);
> + rc = -ETIMEDOUT;
> + }
> + spin_unlock_irq(&ap->host_set->lock);
> + }
> +
> + if (rc == 0 && !ata_ok(ata_chk_status(ap)))
> + rc = -EIO;
General comment on libata: we should move away from using the Status
register directly, and more towards an indication that the taskfile
described by the queue_cmd is in error. i.e. add an 'error' flag or
something like that.
The rest seems fairly sane.
General comment on libata error handling: as soon as SATA ATAPI is
complete, we can move libata to using SCSI's fine-grained error handling
hooks (eh_{abort,timeout,bus,host}_handler), which will make error
handling easier, and avoid the problems that keep cropping up with the
->eh_strategy_handler() approach.
Jeff
next prev parent reply other threads:[~2005-08-11 20:13 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-07-25 13:47 libata total system lockup fix Mark Lord
2005-07-25 14:51 ` Jeff Garzik
2005-07-25 15:53 ` Mark Lord
2005-08-05 3:52 ` Tejun Heo
2005-08-05 4:01 ` Tejun Heo
2005-08-11 20:13 ` Jeff Garzik [this message]
2005-08-12 0:49 ` Tejun Heo
2005-08-12 2:22 ` Mark Lord
2005-08-12 2:38 ` Tejun Heo
2005-08-12 2:41 ` Tejun Heo
2005-08-09 15:16 ` Mark Lord
2005-08-09 23:54 ` Tejun Heo
2005-08-10 14:16 ` Mark Lord
2005-08-10 21:24 ` Jeff Garzik
2005-08-19 0:46 ` Mark Lord
2005-08-19 3:21 ` Tejun Heo
2005-08-19 3:36 ` Mark Lord
2005-08-19 3:45 ` Tejun Heo
2005-08-19 4:01 ` Mark Lord
2005-08-19 9:37 ` Erik Slagter
2005-08-19 9:35 ` Erik Slagter
2005-08-19 13:07 ` Mark Lord
2005-08-19 13:32 ` Bartlomiej Zolnierkiewicz
2005-08-19 13:37 ` Bartlomiej Zolnierkiewicz
2005-09-03 22:58 ` Mark Lord
2005-09-03 23:06 ` 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=42FBB14E.5040002@pobox.com \
--to=jgarzik@pobox.com \
--cc=hare@suse.de \
--cc=htejun@gmail.com \
--cc=liml@rtr.ca \
--cc=linux-ide@vger.kernel.org \
--cc=mlord@pobox.com \
/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).