qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] smbus: do not immediately complete commands


From: Philippe Mathieu-Daudé
Subject: Re: [Qemu-devel] [PATCH] smbus: do not immediately complete commands
Date: Fri, 15 Dec 2017 08:17:46 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0

On 12/10/2017 02:27 PM, Hervé Poussineau wrote:
> PIIX4 errata says that "immediate polling of the Host Status Register BUSY
> bit may indicate that the SMBus is NOT busy."
> Due to this, some code does the following steps:
> (a) set parameters
> (b) start command
> (c) check for smbus busy bit set (to know that command started)
> (d) check for smbus busy bit not set (to know that command finished)
> 
> Let (c) happen, by immediately setting the busy bit, and really executing
> the command when status register has been read once.
> 
> This fixes a problem with AMIBIOS, which can now properly initialize the 
> PIIX4.
> 
> Signed-off-by: Hervé Poussineau <address@hidden>

This looks sane, so:

Signed-off-by: Philippe Mathieu-Daudé <address@hidden>

> ---
>  hw/i2c/pm_smbus.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c
> index 6fc3923f56..ec060d58cc 100644
> --- a/hw/i2c/pm_smbus.c
> +++ b/hw/i2c/pm_smbus.c
> @@ -63,6 +63,9 @@ static void smb_transaction(PMSMBus *s)
>      I2CBus *bus = s->smbus;
>      int ret;
>  
> +    assert(s->smb_stat & STS_HOST_BUSY);
> +    s->smb_stat &= ~STS_HOST_BUSY;
> +
>      SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
>      /* Transaction isn't exec if STS_DEV_ERR bit set */
>      if ((s->smb_stat & STS_DEV_ERR) != 0)  {
> @@ -135,6 +138,13 @@ error:
>  
>  }
>  
> +static void smb_transaction_start(PMSMBus *s)
> +{
> +    /* Do not execute immediately the command ; it will be
> +     * executed when guest will read SMB_STAT register */
> +    s->smb_stat |= STS_HOST_BUSY;
> +}
> +
>  static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
>                                unsigned width)
>  {
> @@ -150,7 +160,7 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, 
> uint64_t val,
>      case SMBHSTCNT:
>          s->smb_ctl = val;
>          if (val & 0x40)
> -            smb_transaction(s);
> +            smb_transaction_start(s);
>          break;
>      case SMBHSTCMD:
>          s->smb_cmd = val;
> @@ -182,6 +192,10 @@ static uint64_t smb_ioport_readb(void *opaque, hwaddr 
> addr, unsigned width)
>      switch(addr) {
>      case SMBHSTSTS:
>          val = s->smb_stat;
> +        if (s->smb_stat & STS_HOST_BUSY) {
> +            /* execute command now */
> +            smb_transaction(s);
> +        }
>          break;
>      case SMBHSTCNT:
>          s->smb_index = 0;
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]