[Qemu-devel] [PATCH 4/5] atapi: call ide_set_irq before ide_transfer_start

Paolo Bonzini posted 5 patches 7 years, 8 months ago
[Qemu-devel] [PATCH 4/5] atapi: call ide_set_irq before ide_transfer_start
Posted by Paolo Bonzini 7 years, 8 months ago
The ATAPI_INT_REASON_IO interrupt is raised when I/O starts, but in the
AHCI case ide_set_irq was actually called at the end of a mutual recursion.
Move it early, with the side effect that ide_transfer_start becomes a tail
call in ide_atapi_cmd_reply_end.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/ide/atapi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index c0509c8bf5..be99a929cf 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -287,6 +287,7 @@ void ide_atapi_cmd_reply_end(IDEState *s)
         } else {
             /* a new transfer is needed */
             s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
+            ide_set_irq(s->bus);
             byte_count_limit = atapi_byte_count_limit(s);
             trace_ide_atapi_cmd_reply_end_bcl(s, byte_count_limit);
             size = s->packet_transfer_size;
@@ -307,10 +308,9 @@ void ide_atapi_cmd_reply_end(IDEState *s)
             s->packet_transfer_size -= size;
             s->elementary_transfer_size -= size;
             s->io_buffer_index += size;
+            trace_ide_atapi_cmd_reply_end_new(s, s->status);
             ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
                                size, ide_atapi_cmd_reply_end);
-            ide_set_irq(s->bus);
-            trace_ide_atapi_cmd_reply_end_new(s, s->status);
         }
     }
 }
-- 
2.14.3



Re: [Qemu-devel] [PATCH 4/5] atapi: call ide_set_irq before ide_transfer_start
Posted by John Snow 7 years, 7 months ago

On 02/23/2018 10:26 AM, Paolo Bonzini wrote:
> The ATAPI_INT_REASON_IO interrupt is raised when I/O starts, but in the
> AHCI case ide_set_irq was actually called at the end of a mutual recursion.
> Move it early, with the side effect that ide_transfer_start becomes a tail
> call in ide_atapi_cmd_reply_end.
> 

Do you know in which spec it specifies that we should interrupt?

Seems okay, but I wanted to double check the wording in the spec (was
looking in scsi MMC and ATA8) and couldn't find it quickly.

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/ide/atapi.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
> index c0509c8bf5..be99a929cf 100644
> --- a/hw/ide/atapi.c
> +++ b/hw/ide/atapi.c
> @@ -287,6 +287,7 @@ void ide_atapi_cmd_reply_end(IDEState *s)
>          } else {
>              /* a new transfer is needed */
>              s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
> +            ide_set_irq(s->bus);
>              byte_count_limit = atapi_byte_count_limit(s);
>              trace_ide_atapi_cmd_reply_end_bcl(s, byte_count_limit);
>              size = s->packet_transfer_size;
> @@ -307,10 +308,9 @@ void ide_atapi_cmd_reply_end(IDEState *s)
>              s->packet_transfer_size -= size;
>              s->elementary_transfer_size -= size;
>              s->io_buffer_index += size;
> +            trace_ide_atapi_cmd_reply_end_new(s, s->status);
>              ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
>                                 size, ide_atapi_cmd_reply_end);
> -            ide_set_irq(s->bus);
> -            trace_ide_atapi_cmd_reply_end_new(s, s->status);
>          }
>      }
>  }
> 

Re: [Qemu-devel] [PATCH 4/5] atapi: call ide_set_irq before ide_transfer_start
Posted by Paolo Bonzini 7 years, 7 months ago
On 21/03/2018 01:35, John Snow wrote:
>> The ATAPI_INT_REASON_IO interrupt is raised when I/O starts, but in the
>> AHCI case ide_set_irq was actually called at the end of a mutual recursion.
>> Move it early, with the side effect that ide_transfer_start becomes a tail
>> call in ide_atapi_cmd_reply_end.
>>
> Do you know in which spec it specifies that we should interrupt?
> 
> Seems okay, but I wanted to double check the wording in the spec (was
> looking in scsi MMC and ATA8) and couldn't find it quickly.

I have an "Interrupt Reason" field in my copy of the ATA/ATAPI spec:

---
6.4.3 Input/Output (I/O) bit
The Input/Output bit shall be cleared to zero if the transfer is to the
device. The Input/Output bit shall be set to one if the transfer is to
the host. In ATA/ATAPI-7 this bit was documented as the I/O bit.
---

I suppose the commit message needs some improvement---the point is that
since this is a READ, the I/O bit must be set before we start the
transfer.  It can be done after the disk I/O starts, but it must be done
before the PIO transfer starts; in other words, the bug is only there
for AHCI.

Paolo