qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] Re: [PATCH 09/10] pci: set PCI multi-function bit appropria


From: Isaku Yamahata
Subject: [Qemu-devel] Re: [PATCH 09/10] pci: set PCI multi-function bit appropriately.
Date: Fri, 18 Jun 2010 11:40:57 +0900
User-agent: Mutt/1.5.19 (2009-01-05)

On Thu, Jun 17, 2010 at 12:37:21PM +0300, Michael S. Tsirkin wrote:
> On Thu, Jun 17, 2010 at 03:15:51PM +0900, Isaku Yamahata wrote:
> > set PCI multi-function bit appropriately.
> > 
> > Signed-off-by: Isaku Yamahata <address@hidden>
> > 
> > ---
> > changes v1 -> v2:
> > don't set header type register in configuration space.
> > ---
> >  hw/pci.c |   25 +++++++++++++++++++++++++
> >  1 files changed, 25 insertions(+), 0 deletions(-)
> > 
> > diff --git a/hw/pci.c b/hw/pci.c
> > index 5316aa5..ee391dc 100644
> > --- a/hw/pci.c
> > +++ b/hw/pci.c
> > @@ -607,6 +607,30 @@ static void pci_init_wmask_bridge(PCIDevice *d)
> >      pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> >  }
> >  
> > +static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
> > +{
> > +    uint8_t slot = PCI_SLOT(dev->devfn);
> > +    uint8_t func_max = 8;
> 
> enum or define would be better

Will fix.


> > +    uint8_t func;
> 
> If I understand correctly what this does, it goes over
> other functions of the same device, and sets the MULTI_FUNCTION bit
> for them if there's more than one function.
> Instead, why don't we just set PCI_HEADER_TYPE_MULTI_FUNCTION
> in relevant devices?

pci address, devfn ,is exported to users as addr property,
so users can populate pci function(PCIDevice in qemu)
at arbitrary devfn.
It means each function(PCIDevice) don't know whether pci device
(PCIDevice[8]) is multi function or not.
So I chose to handle it in pci generic layer.

It can be argued that it's user operation fault and that
the missing part is validation checks to catch such user errors.
But I prefer more flexible and more user friendly way.


> > +
> > +    for (func = 0; func < func_max; ++func) {
> > +        if (bus->devices[PCI_DEVFN(slot, func)]) {
> > +            break;
> > +        }
> > +    }
> > +    if (func == func_max) {
> > +        return;
> > +    }
> > +
> 
> The above only works if the function is called before
> device is added to bus.

That's right. This function is called before bus->devices[devfn] = dev.

> 
> > +    for (func = 0; func < func_max; ++func) {
> > +        if (bus->devices[PCI_DEVFN(slot, func)]) {
> > +            bus->devices[PCI_DEVFN(slot, func)]->config[PCI_HEADER_TYPE] |=
> > +                PCI_HEADER_TYPE_MULTI_FUNCTION;
> > +        }
> > +    }
> > +    dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
> 
> Isn't the bit set above already?
> 
> > +}
> > +
> >  static void pci_config_alloc(PCIDevice *pci_dev)
> >  {
> >      int config_size = pci_config_size(pci_dev);
> > @@ -660,6 +684,7 @@ static PCIDevice *do_pci_register_device(PCIDevice 
> > *pci_dev, PCIBus *bus,
> >      if (is_bridge) {
> >          pci_init_wmask_bridge(pci_dev);
> >      }
> > +    pci_init_multifunction(bus, pci_dev);
> >  
> >      if (!config_read)
> >          config_read = pci_default_read_config;
> > -- 
> > 1.6.6.1
> 

-- 
yamahata



reply via email to

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