All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Isaku Yamahata <yamahata@valinux.co.jp>
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] Re: [PATCH 4/4] pci: interrupt disable bit support
Date: Thu, 26 Nov 2009 14:38:19 +0200	[thread overview]
Message-ID: <20091126123819.GA31495@redhat.com> (raw)
In-Reply-To: <20091126095316.GC26861@redhat.com>

On Thu, Nov 26, 2009 at 11:53:16AM +0200, Michael S. Tsirkin wrote:
> On Thu, Nov 26, 2009 at 12:04:51PM +0900, Isaku Yamahata wrote:
> > On Wed, Nov 25, 2009 at 06:59:06PM +0200, Michael S. Tsirkin wrote:
> > > interrupt disable bit is mandatory in PCI spec,
> > > so we must implement it to be spec compliant.
> > > 
> > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > ---
> > >  hw/pci.c |   57 ++++++++++++++++++++++++++++++++++++++++-----------------
> > >  hw/pci.h |    4 ++++
> > >  2 files changed, 44 insertions(+), 17 deletions(-)
> > > 
> > > diff --git a/hw/pci.c b/hw/pci.c
> > > index 844664b..3daae46 100644
> > > --- a/hw/pci.c
> > > +++ b/hw/pci.c
> > > @@ -114,12 +114,43 @@ static void pci_update_irq_status(PCIDevice *dev)
> > >      }
> > >  }
> > >  
> > > +static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
> > > +{
> > > +    PCIBus *bus;
> > > +    for (;;) {
> > > +        bus = pci_dev->bus;
> > > +        irq_num = bus->map_irq(pci_dev, irq_num);
> > > +        if (bus->set_irq)
> > > +            break;
> > > +        pci_dev = bus->parent_dev;
> > > +    }
> > > +    bus->irq_count[irq_num] += change;
> > > +    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
> > 
> > Let's use ! instead of != 0 for consistency.
> > 
> 
> This patch simply moves code, so it's better to keep it
> the same - this way git blame can find it.
> A separate patch to clean this might be a good idea.
> 
> > > +}
> > > +
> > > +/* Update irq disabled field after config space change,
> > > + * assert/deassert interrupts if necessary. */
> > > +static void pci_update_irq_disabled(PCIDevice *d)
> > > +{
> > > +    int i;
> > > +    int disabled = !!(pci_get_word(d->config + PCI_COMMAND) &
> > > +                      PCI_COMMAND_INTX_DISABLE);
> > > +    if (disabled == d->irq_disabled)
> > > +        return;
> > > +    d->irq_disabled = disabled;
> > > +    for (i = 0; i < ARRAY_SIZE(d->irq_state); ++i) {
> > > +        int state = d->irq_state[i];
> > > +        pci_change_irq_level(d, i, disabled ? -state : state);
> > > +    }
> > > +}
> > > +
> > 
> > "if (!changed) return" check is in pci_set_irq().
> > So if d->irq_state[i] == 0, bus->set_irq() will be called again.
> > I suppose this isn't your intention.
> 
> Good catch, thanks!

Thinking about this more, in fact, it is harmless to call set_irq
with the same level as th old one, and this
is not on datapath.
So yes, this is the intention.

> > I suppose !changed check should be in pci_change_irq_level() instead of pci_set_irq().
> > 
> 
> The fix is different: in fact pci_update_irq_disabled
> should never call pci_change_irq_level with change value 0.
> that -state should have been 1 - state.
> I'll fix this. Thanks!

In fact, you were right.
While calling pci_change_irq_level with change 0 is harmless,
it's cleaner to move the check within that function.
I'll do that.

> > >  static void pci_device_reset(PCIDevice *dev)
> > >  {
> > >      int r;
> > >  
> > >      memset(dev->irq_state, 0, sizeof dev->irq_state);
> > >      dev->irq_status = 0;
> > > +    dev->irq_disabled = 0;
> > >      pci_update_irq_status(dev);
> > >      dev->config[PCI_COMMAND] &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
> > >                                    PCI_COMMAND_MASTER);
> > > @@ -345,6 +376,7 @@ int pci_device_load(PCIDevice *s, QEMUFile *f)
> > >      }
> > >      /* Restore the interrupt status bit. */
> > >      pci_update_irq_status(s);
> > > +    pci_update_irq_disabled(s);
> > >      return ret;
> > >  }
> > >  
> > > @@ -458,7 +490,8 @@ static void pci_init_wmask(PCIDevice *dev)
> > >      dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
> > >      dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
> > >      pci_set_word(dev->wmask + PCI_COMMAND,
> > > -                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
> > > +                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
> > > +                 PCI_COMMAND_INTX_DISABLE);
> > >  
> > >      memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff,
> > >             config_size - PCI_CONFIG_HEADER_SIZE);
> > > @@ -903,26 +936,14 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
> > >          ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
> > >          range_covers_byte(addr, l, PCI_COMMAND))
> > >          pci_update_mappings(d);
> > > +
> > > +    if (range_covers_byte(addr, l, PCI_COMMAND))
> > > +        pci_update_irq_disabled(d);
> > >  }
> > >  
> > >  /***********************************************************/
> > >  /* generic PCI irq support */
> > >  
> > > -static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
> > > -{
> > > -    PCIBus *bus;
> > > -    for (;;) {
> > > -        bus = pci_dev->bus;
> > > -        irq_num = bus->map_irq(pci_dev, irq_num);
> > > -        if (bus->set_irq)
> > > -            break;
> > > -        pci_dev = bus->parent_dev;
> > > -    }
> > > -    bus->irq_count[irq_num] += change;
> > > -    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
> > > -}
> > > -
> > > -
> > >  /* 0 <= irq_num <= 3. level must be 0 or 1 */
> > >  static void pci_set_irq(void *opaque, int irq_num, int level)
> > >  {
> > > @@ -935,7 +956,9 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
> > >  
> > >      pci_dev->irq_state[irq_num] = level;
> > >      pci_dev->irq_status += change;
> > > -    pci_update_irq_status(s);
> > > +    pci_update_irq_status(pci_dev);
> > > +    if (pci_dev->irq_disabled)
> > > +        return;
> > >      pci_change_irq_level(pci_dev, irq_num, change);
> > >  }
> > >  
> > > diff --git a/hw/pci.h b/hw/pci.h
> > > index c3f2c3f..994b8bc 100644
> > > --- a/hw/pci.h
> > > +++ b/hw/pci.h
> > > @@ -101,6 +101,7 @@ typedef struct PCIIORegion {
> > >  #define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
> > >  #define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
> > >  #define  PCI_COMMAND_MASTER	0x4	/* Enable bus master */
> > > +#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
> > >  #define PCI_STATUS              0x06    /* 16 bits */
> > >  #define  PCI_STATUS_INTERRUPT   0x08
> > >  #define PCI_REVISION_ID         0x08    /* 8 bits  */
> > > @@ -226,6 +227,9 @@ struct PCIDevice {
> > >      /* Sum of all irq levels. Used to implement irq status register. */
> > >      int irq_status;
> > >  
> > > +    /* Whether interrupts are disabled by command bit. */
> > > +    int irq_disabled;
> > > +
> > >      /* Capability bits */
> > >      uint32_t cap_present;
> > >  
> > 
> > -- 
> > yamahata

  reply	other threads:[~2009-11-26 12:41 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1259168040.git.mst@redhat.com>
2009-11-25 16:58 ` [Qemu-devel] [PATCH 1/4] pci: rearrange code for interrupts Michael S. Tsirkin
2009-11-25 16:58 ` [Qemu-devel] [PATCH 2/4] pci: track IRQ status Michael S. Tsirkin
2009-11-25 16:58 ` [Qemu-devel] [PATCH 3/4] pci: interrupt status bit implementation Michael S. Tsirkin
2009-11-25 16:59 ` [Qemu-devel] [PATCH 4/4] pci: interrupt disable bit support Michael S. Tsirkin
2009-11-26  3:04   ` [Qemu-devel] " Isaku Yamahata
2009-11-26  9:53     ` Michael S. Tsirkin
2009-11-26 12:38       ` Michael S. Tsirkin [this message]
2009-11-26 13:21     ` Michael S. Tsirkin

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=20091126123819.GA31495@redhat.com \
    --to=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=yamahata@valinux.co.jp \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.