Patchwork AHCI Port Interrupt Enable register cleaning on soft reset

login
register
mail settings
Submitter Alexander Motin
Date Sept. 12, 2011, 8:19 a.m.
Message ID <4E6DC08D.3010507@FreeBSD.org>
Download mbox | patch
Permalink /patch/114299/
State New
Headers show

Comments

Alexander Motin - Sept. 12, 2011, 8:19 a.m.
Alexander Graf wrote:
> Am 11.09.2011 um 16:43 schrieb Alexander Motin <mav@FreeBSD.org>:
>> I've found that FreeBSD AHCI driver doesn't work with AHCI hardware
>> emulation of QEMU 0.15.0. I believe the problem is on QEMU's side. As I
>> see, it clears port's Interrupt Enable register each time when reset of
>> any level happens. Is is reasonable for the global controller reset. It
>> is probably not good, but acceptable for FreeBSD driver for the port
>> hard reset. But it is IMO wrong for the device soft reset. None of real
>> hardware I know behaves that way.
>>
>> This patch fixes the problem for me:
>> http://people.freebsd.org/~mav/qemu.ahci.patch
> 
> Ah, cool! So FreeBSD works with AHCI using this patch? 

Yes. I haven't done deep testing to guarantee there is no other issues,
but at least disk is properly detected now.

> Please send it again as an inline patch (if really really hard not 100% important) and add a signed-off-by line (very important) to the patch.

OK. Here it is:

Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Kevin Wolf - Sept. 19, 2011, 10:36 a.m.
Am 12.09.2011 10:19, schrieb Alexander Motin:
> Alexander Graf wrote:
>> Am 11.09.2011 um 16:43 schrieb Alexander Motin <mav@FreeBSD.org>:
>>> I've found that FreeBSD AHCI driver doesn't work with AHCI hardware
>>> emulation of QEMU 0.15.0. I believe the problem is on QEMU's side. As I
>>> see, it clears port's Interrupt Enable register each time when reset of
>>> any level happens. Is is reasonable for the global controller reset. It
>>> is probably not good, but acceptable for FreeBSD driver for the port
>>> hard reset. But it is IMO wrong for the device soft reset. None of real
>>> hardware I know behaves that way.
>>>
>>> This patch fixes the problem for me:
>>> http://people.freebsd.org/~mav/qemu.ahci.patch
>>
>> Ah, cool! So FreeBSD works with AHCI using this patch? 
> 
> Yes. I haven't done deep testing to guarantee there is no other issues,
> but at least disk is properly detected now.
> 
>> Please send it again as an inline patch (if really really hard not 100% important) and add a signed-off-by line (very important) to the patch.
> 
> OK. Here it is:
> 
> Signed-off-by: Alexander Motin <mav@FreeBSD.org>
> 
> --- hw/ide/ahci.c.prev	2011-09-11 16:39:53.000000000 +0300
> +++ hw/ide/ahci.c	2011-09-11 16:39:48.000000000 +0300
> @@ -505,10 +505,7 @@ static void ahci_reset_port(AHCIState *s
>      ide_bus_reset(&d->port);
>      ide_state->ncq_queues = AHCI_MAX_CMDS;
> 
> -    pr->irq_stat = 0;
> -    pr->irq_mask = 0;
>      pr->scr_stat = 0;
> -    pr->scr_ctl = 0;
>      pr->scr_err = 0;
>      pr->scr_act = 0;
>      d->busy_slot = -1;
> @@ -1157,12 +1154,17 @@ void ahci_uninit(AHCIState *s)
>  void ahci_reset(void *opaque)
>  {
>      struct AHCIPCIState *d = opaque;
> +    AHCIPortRegs *pr;
>      int i;
> 
>      d->ahci.control_regs.irqstatus = 0;
>      d->ahci.control_regs.ghc = 0;
> 
>      for (i = 0; i < d->ahci.ports; i++) {
> +        pr = &d->ahci.dev[i].port_regs;
> +        pr->irq_stat = 0;
> +        pr->irq_mask = 0;
> +        pr->scr_ctl = 0;
>          ahci_reset_port(&d->ahci, i);
>      }
>  }
> 

Thanks, applied to the block branch.

Kevin

Patch

--- hw/ide/ahci.c.prev	2011-09-11 16:39:53.000000000 +0300
+++ hw/ide/ahci.c	2011-09-11 16:39:48.000000000 +0300
@@ -505,10 +505,7 @@  static void ahci_reset_port(AHCIState *s
     ide_bus_reset(&d->port);
     ide_state->ncq_queues = AHCI_MAX_CMDS;

-    pr->irq_stat = 0;
-    pr->irq_mask = 0;
     pr->scr_stat = 0;
-    pr->scr_ctl = 0;
     pr->scr_err = 0;
     pr->scr_act = 0;
     d->busy_slot = -1;
@@ -1157,12 +1154,17 @@  void ahci_uninit(AHCIState *s)
 void ahci_reset(void *opaque)
 {
     struct AHCIPCIState *d = opaque;
+    AHCIPortRegs *pr;
     int i;

     d->ahci.control_regs.irqstatus = 0;
     d->ahci.control_regs.ghc = 0;

     for (i = 0; i < d->ahci.ports; i++) {
+        pr = &d->ahci.dev[i].port_regs;
+        pr->irq_stat = 0;
+        pr->irq_mask = 0;
+        pr->scr_ctl = 0;
         ahci_reset_port(&d->ahci, i);
     }
 }