linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
To: Albert Lee <albertcc@tw.ibm.com>
Cc: Jeff Garzik <jgarzik@pobox.com>,
	Linux IDE <linux-ide@vger.kernel.org>,
	Doug Maxey <dwm@maxeymade.com>, Tejun Heo <htejun@gmail.com>,
	Mark Lord <mlord@pobox.com>, Brett Russ <russb@emc.com>
Subject: Re: [PATCH/RFC 3/4] libata: interrupt driven pio for libata-core
Date: Thu, 29 Sep 2005 12:08:40 +0200	[thread overview]
Message-ID: <58cb370e05092903083e0d001c@mail.gmail.com> (raw)
In-Reply-To: <433912FB.9000606@tw.ibm.com>

Hi,

On 9/27/05, Albert Lee <albertcc@tw.ibm.com> wrote:
> Patch 3/4: interrupt driven pio for libata-core
>
> Changes:
> - add PIO_ST_FIRST for the state before sending ATAPI CDB or sending

HSM_ST_FIRST

Could you add some brief comments about HSM_* states
(one line per state should be OK)?

> @@ -3344,43 +3356,96 @@ int ata_qc_issue_prot(struct ata_queued_
>  {
>         struct ata_port *ap = qc->ap;
>
> +       /* select the device */
>         ata_dev_select(ap, qc->dev->devno, 1, 0);
>
> +       /* start the command */
>         switch (qc->tf.protocol) {
>         case ATA_PROT_NODATA:
> +               if (qc->tf.flags & ATA_TFLAG_POLLING)
> +                       ata_qc_set_polling(qc);
> +
>                 ata_tf_to_host_nolock(ap, &qc->tf);
> +               ap->hsm_task_state = HSM_ST_LAST;
> +
> +               if (qc->tf.flags & ATA_TFLAG_POLLING)
> +                       queue_work(ata_wq, &ap->pio_task);
> +
>                 break;
>
>         case ATA_PROT_DMA:
> +               assert(!(qc->tf.flags & ATA_TFLAG_POLLING));
> +
>                 ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
>                 ap->ops->bmdma_setup(qc);           /* set up bmdma */
>                 ap->ops->bmdma_start(qc);           /* initiate bmdma */
> +               ap->hsm_task_state = HSM_ST_LAST;
>                 break;
>
> -       case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
> -               ata_qc_set_polling(qc);
> +       case ATA_PROT_PIO:
> +               if (qc->tf.flags & ATA_TFLAG_POLLING)
> +                       ata_qc_set_polling(qc);
> +
>                 ata_tf_to_host_nolock(ap, &qc->tf);
> -               ap->hsm_task_state = HSM_ST;
> -               queue_work(ata_wq, &ap->pio_task);
> +
> +               if (qc->tf.flags & ATA_TFLAG_POLLING) {
> +                       /* polling PIO */
> +                       ap->hsm_task_state = HSM_ST;
> +                       queue_work(ata_wq, &ap->pio_task);
> +               } else {
> +                       /* interrupt driven PIO */
> +                       if (qc->tf.flags & ATA_TFLAG_WRITE) {
> +                               /* PIO data out protocol */
> +                               ap->hsm_task_state = HSM_ST_FIRST;
> +                               queue_work(ata_wq, &ap->packet_task);

atapi_packet_task() is now abused to do ATA PIO out which is
very confusing given that name of the function (and all the comments)
remains unchanged.  Please correct it (I think it would be good idea to
separate HSM_ST_CDB from HSM_ST_FIRST).

>         case ATA_PROT_ATAPI:
> -               ata_qc_set_polling(qc);
> +               if (qc->tf.flags & ATA_TFLAG_POLLING)
> +                       ata_qc_set_polling(qc);
> +
>                 ata_tf_to_host_nolock(ap, &qc->tf);
> -               queue_work(ata_wq, &ap->packet_task);
> +               ap->hsm_task_state = HSM_ST_FIRST;
> +
> +               /* send cdb by polling if no cdb interrupt */
> +               if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
> +                   (qc->tf.flags & ATA_TFLAG_POLLING))
> +                       queue_work(ata_wq, &ap->packet_task);
>                 break;
>
>         case ATA_PROT_ATAPI_NODATA:
> -               ap->flags |= ATA_FLAG_NOINTR;
> +               if (qc->tf.flags & ATA_TFLAG_POLLING)
> +                       ata_qc_set_polling(qc);
> +
>                 ata_tf_to_host_nolock(ap, &qc->tf);
> -               queue_work(ata_wq, &ap->packet_task);
> +               ap->hsm_task_state = HSM_ST_FIRST;
> +
> +               /* send cdb by polling if no cdb interrupt */
> +               if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
> +                   (qc->tf.flags & ATA_TFLAG_POLLING))
> +                       queue_work(ata_wq, &ap->packet_task);
>                 break;

ATA_PROT_ATAPI_NODATA case is now identical
to ATA_PROT_ATAPI one - no need to duplicate code.

It may be also worth to split ata_qc_issue_prot() on IRQ
and polling versions because it is really hard to read now.

> +/**
>   *     ata_host_intr - Handle host interrupt for given (port, task)
>   *     @ap: Port on which interrupt arrived (possibly...)
>   *     @qc: Taskfile currently active in engine
> @@ -3641,47 +3742,142 @@ void ata_bmdma_stop(struct ata_queued_cm
>  inline unsigned int ata_host_intr (struct ata_port *ap,
>                                    struct ata_queued_cmd *qc)
>  {

We should check first if we are polling and if so we shouldn't touch hardware
et all as we can interface with ata_pio_task or atapi_packet_task.  Just think
about HSM_ST case when hardware is ready for the next transfer and IRQ
happens (from some other device).

Please note that this bug is present in original libata code.

> -       u8 status, host_stat;
> -
> -       switch (qc->tf.protocol) {
> +       u8 status, host_stat = 0;
>
> -       case ATA_PROT_DMA:
> -       case ATA_PROT_ATAPI_DMA:
> -       case ATA_PROT_ATAPI:

Your patch changes behavior for ATA_PROT_ATAPI case - now DMA
engine won't be checked.  We had discussion about fixing it before
but I don't remember what was the conclusion - in any case it is worth
to at least mention this change in the patch description.

> -               /* check status of DMA engine */
> -               host_stat = ap->ops->bmdma_status(ap);
> -               VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
> +       VPRINTK("ata%u: protocol %d task_state %d\n",
> +               ap->id, qc->tf.protocol, ap->hsm_task_state);
>
> -               /* if it's not our irq... */
> -               if (!(host_stat & ATA_DMA_INTR))
> +       /* Check whether we are expecting interrupt in this state */
> +       switch (ap->hsm_task_state) {
> +       case HSM_ST_FIRST:
> +               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
> +                * The flag was turned on only for atapi devices.
> +                * No need to check is_atapi_taskfile(&qc->tf) again.
> +                */
> +               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
>                         goto idle_irq;
> +               break;
> +       case HSM_ST_LAST:
> +               if (qc->tf.protocol == ATA_PROT_DMA ||
> +                   qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
> +                       /* check status of DMA engine */
> +                       host_stat = ap->ops->bmdma_status(ap);
> +                       VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
> +
> +                       /* if it's not our irq... */
> +                       if (!(host_stat & ATA_DMA_INTR))
> +                               goto idle_irq;
>
> -               /* before we do anything else, clear DMA-Start bit */
> -               ap->ops->bmdma_stop(qc);
> +                       /* before we do anything else, clear DMA-Start bit */
> +                       ap->ops->bmdma_stop(qc);
> +               }
> +               break;
> +       case HSM_ST:
> +               break;
> +       default:
> +               goto idle_irq;
> +       }
>
> -               /* fall through */
> +       /* check altstatus */
> +       status = ata_altstatus(ap);
> +       if (status & ATA_BUSY)
> +               goto idle_irq;
>
> -       case ATA_PROT_ATAPI_NODATA:
> -       case ATA_PROT_NODATA:
> -               /* check altstatus */
> -               status = ata_altstatus(ap);
> -               if (status & ATA_BUSY)
> -                       goto idle_irq;
> +       /* check main status, clearing INTRQ */
> +       status = ata_chk_status(ap);
> +       if (unlikely(status & ATA_BUSY))
> +               goto idle_irq;
>
> -               /* check main status, clearing INTRQ */
> -               status = ata_chk_status(ap);
> -               if (unlikely(status & ATA_BUSY))
> -                       goto idle_irq;
> -               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
> -                       ap->id, qc->tf.protocol, status);
> +       DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
> +               ap->id, qc->tf.protocol, ap->hsm_task_state, status);
>
> -               /* ack bmdma irq events */
> -               ap->ops->irq_clear(ap);
> +       /* ack bmdma irq events */
> +       ap->ops->irq_clear(ap);
> +
> +       /* check error */
> +       if (unlikely((status & ATA_ERR) || (host_stat & ATA_DMA_ERR)))
> +               ap->hsm_task_state = HSM_ST_ERR;
> +
> +fsm_start:
> +       switch (ap->hsm_task_state) {
> +       case HSM_ST_FIRST:
> +               /* Some pre-ATAPI-4 devices assert INTRQ
> +                * at this state when ready to receive CDB.
> +                */
> +
> +               /* check device status */
> +               if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
> +                       /* Wrong status. Let EH handle this */
> +                       ap->hsm_task_state = HSM_ST_ERR;
> +                       goto fsm_start;
> +               }
> +
> +               atapi_send_cdb(ap, qc);

This case can happen also for ATA PIO out:
ata_qc_issue_prot() -> IRQ happens -> ata_host_intr().

Sending CDB unconditionally is wrong.


The rest of the patch looks fine but it is was quite difficult to review
because you've combined two major logical changes into one patch:
* switching libata to use host state information
* adding support for IRQ driven PIO

Thanks,
Bartlomiej

  parent reply	other threads:[~2005-09-29 10:08 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-09 16:14 [PATCH RFC] libata: interrupt driven pio Albert Lee
2005-09-09 17:35 ` Jeff Garzik
2005-09-09 18:14   ` Doug Maxey
2005-09-22  4:00   ` [PATCH/RFC 0/3] libata: interrupt driven pio (revised) Albert Lee
2005-09-22  4:09     ` [PATCH/RFC 1/3] libata: interrupt driven pio for libata-core Albert Lee
2005-09-23  9:25       ` Albert Lee
2005-09-22  4:11     ` [PATCH/RFC 2/3] libata: rename task states/variables Albert Lee
2005-09-23  9:34       ` Albert Lee
2005-09-22  4:14     ` [PATCH/RFC 3/3] libata: interrupt driven pio for LLD Albert Lee
2005-09-22 12:56       ` Mark Lord
2005-09-23  2:40         ` Albert Lee
2005-09-23  9:46     ` [PATCH/RFC 0/3] libata: interrupt driven pio (revised) Jeff Garzik
2005-09-27  9:31       ` [PATCH/RFC 0/4] libata: interrupt driven pio (revised 2) Albert Lee
2005-09-27  9:34         ` [PATCH/RFC 1/4] libata: indent and whitespace change Albert Lee
2005-09-27  9:36         ` [PATCH/RFC 2/4] libata: rename host states Albert Lee
2005-09-28 15:59           ` Jeff Garzik
2005-09-27  9:38         ` [PATCH/RFC 3/4] libata: interrupt driven pio for libata-core Albert Lee
2005-09-28 16:09           ` Jeff Garzik
2005-09-29 10:08           ` Bartlomiej Zolnierkiewicz [this message]
2005-09-30  8:02             ` Albert Lee
2005-09-30  9:28               ` Bartlomiej Zolnierkiewicz
2005-09-30 11:28                 ` Albert Lee
2005-09-30 12:00                   ` Bartlomiej Zolnierkiewicz
2005-09-30 11:04             ` [PATCH/RFC 0/4] libata: irq driven pio follow-up patches Albert Lee
2005-09-30 11:07               ` [PATCH/RFC 1/4] irq-pio: add comments and cleanup Albert Lee
2005-09-30 11:09               ` [PATCH/RFC 2/4] irq-pio: rename atapi_packet_task() and comments Albert Lee
2005-09-30 11:11               ` [PATCH/RFC 3/4] irq-pio: simplify if condition in ata_dataout_task() Albert Lee
2005-09-30 11:14               ` [PATCH/RFC 4/4] irq-pio: cleanup ata_qc_issue_prot() Albert Lee
2005-09-30 11:21               ` [PATCH/RFC 0/4] libata: irq driven pio follow-up patches Jeff Garzik
2005-10-03 11:46                 ` [PATCH/RFC 0/4] libata: more " Albert Lee
2005-10-03 13:00                   ` [PATCH/RFC 1/4] irq-pio: move functions Albert Lee
2005-10-03 13:02                   ` [PATCH/RFC 2/4] irq-pio: remove ap->dataout_task Albert Lee
2005-10-04 10:09                     ` Jeff Garzik
2005-10-04 11:54                       ` Albert Lee
2005-10-03 13:18                   ` [PATCH/RFC 3/4] irq-pio: integrate ata_pio_first_block() with ata_pio_task() Albert Lee
2005-10-04 10:10                     ` Jeff Garzik
2005-10-03 13:19                   ` [PATCH/RFC 4/4] irq-pio: add read/write multiple support Albert Lee
2005-10-03 13:35                     ` Mark Lord
2005-10-04  9:43                       ` Jeff Garzik
2005-10-04 12:00                         ` Albert Lee
2005-10-04 12:07                           ` Jeff Garzik
2005-10-04 12:22                             ` [PATCH/RFC 0/4] libata: CHS follow-up patches Albert Lee
2005-10-04 12:27                               ` [PATCH/RFC 1/4] CHS: white space beautification Albert Lee
2005-10-04 12:49                                 ` Jeff Garzik
2005-10-04 12:29                               ` [PATCH/RFC 2/4] CHS: tidy up SCSI lba and transfer length calculation Albert Lee
2005-10-04 12:30                               ` [PATCH/RFC 3/4] CHS: add CHS support to ata_scsi_start_stop_xlat() Albert Lee
2005-10-04 12:34                               ` [PATCH/RFC 4/4] CHS: calculate LBA28/LBA48 commands and protocol on the fly Albert Lee
2005-10-04 12:52                                 ` Jeff Garzik
2005-10-05 11:16                                   ` [PATCH/RFC 0/4] libata: more CHS follow-up patches Albert Lee
2005-10-05 11:20                                     ` [PATCH/RFC 1/4] CHS: move the initialization of taskfile LBA flags Albert Lee
2005-10-05 11:23                                     ` [PATCH/RFC 2/4] CHS: calculate read/write commands and protocol on the fly Albert Lee
2005-10-05 11:25                                     ` [PATCH/RFC 3/4] CHS: support overriding the ata_rwcmd_protocol() function Albert Lee
2005-10-05 11:27                                     ` [PATCH/RFC 4/4] CHS: optimize LBA28/LBA48 usage Albert Lee
2005-10-05 11:59                                     ` [PATCH/RFC 1/4] CHS: move the initialization of taskfile LBA flags (resend) Albert Lee
2005-10-05 12:02                                     ` [PATCH/RFC 2/4] CHS: calculate read/write commands and protocol on the fly (resend) Albert Lee
2005-10-05 12:03                                     ` [PATCH/RFC 3/4] CHS: support overriding the ata_rwcmd_protocol() function (resend) Albert Lee
2005-10-05 12:04                                     ` [PATCH/RFC 4/4] CHS: optimize LBA28/LBA48 usage (resend) Albert Lee
2005-10-06 11:26                                     ` [PATCH/RFC 0/4] libata: more CHS follow-up patches Jeff Garzik
2005-10-07  6:53                                       ` [PATCH 0/3] libata: CHS follow-up patches (resend #2) Albert Lee
2005-10-07  6:58                                         ` [PATCH 1/3] CHS: move the initialization of taskfile LBA flags Albert Lee
2005-10-07  7:01                                         ` [PATCH 2/3] CHS: calculate read/write commands and protocol on the fly Albert Lee
2005-10-07  7:04                                         ` [PATCH 3/3] CHS: LBA28/LBA48 optimization Albert Lee
2005-10-07  8:32                                         ` [PATCH 0/3] libata: CHS follow-up patches (resend #4) Albert Lee
2005-10-07  8:34                                           ` [PATCH 1/3] CHS: move the initialization of taskfile LBA flags " Albert Lee
2005-10-07  8:36                                           ` [PATCH 2/3] CHS: calculate read/write commands and protocol on the fly " Albert Lee
2005-10-07  8:37                                           ` [PATCH 3/3] CHS: LBA28/LBA48 optimization " Albert Lee
2005-10-09 13:41                                           ` [PATCH 0/3] libata: CHS follow-up patches " Jeff Garzik
2005-10-11 11:05                                             ` [PATCH 0/4] libata: CHS follow-up patches (resend #5) Albert Lee
2005-10-11 11:09                                               ` [PATCH 1/4] CHS: move the initialization of taskfile LBA flags " Albert Lee
2005-10-11 11:11                                               ` [PATCH 2/4] CHS: calculate read/write commands and protocol on the fly " Albert Lee
2005-10-11 11:21                                               ` [PATCH 4/4] CHS: LBA28/LBA48 optimization " Albert Lee
2005-10-11 13:09                                                 ` Mark Lord
2005-10-11 13:12                                                 ` Mark Lord
2005-10-12  5:05                                                   ` Albert Lee
2005-10-04 15:48                                 ` [PATCH/RFC 4/4] CHS: calculate LBA28/LBA48 commands and protocol on the fly Alan Cox
2005-10-04 10:19                     ` [PATCH/RFC 4/4] irq-pio: add read/write multiple support Jeff Garzik
2005-09-27  9:39         ` [PATCH/RFC 4/4] libata: interrupt driven pio for LLD Albert Lee

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=58cb370e05092903083e0d001c@mail.gmail.com \
    --to=bzolnier@gmail.com \
    --cc=albertcc@tw.ibm.com \
    --cc=dwm@maxeymade.com \
    --cc=htejun@gmail.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=mlord@pobox.com \
    --cc=russb@emc.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).