From: "Michael S. Tsirkin" <mst@redhat.com>
To: Isaku Yamahata <yamahata@valinux.co.jp>
Cc: blauwirbel@gmail.com, yu.liu@freescale.com,
qemu-devel@nongnu.org, aurelien@aurel32.net,
paul@codesourcery.com
Subject: [Qemu-devel] Re: [PATCH v4 3/6] pci: set PCI multi-function bit appropriately.
Date: Mon, 21 Jun 2010 15:36:00 +0300 [thread overview]
Message-ID: <20100621123600.GB10511@redhat.com> (raw)
In-Reply-To: <99d849f1b4eeb12893447e78a6950c26a32088ac.1277100005.git.yamahata@valinux.co.jp>
On Mon, Jun 21, 2010 at 03:03:58PM +0900, Isaku Yamahata wrote:
> Set PCI multi-function bit according to multifunction property.
> 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 this patch allows user to set multifunction bit via property
> and checks whether multifunction bit is set correctly.
>
> Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Applying it this way will break bisect.
We also need to handle migration compatibility.
I propose we split it this way:
- patch to add multifunction property (ignored)
- set property in builtin devices where appropriate
- patch to look at property and set bit in header
> ---
> changes v3 -> v4:
> - introduce multifunction property.
>
> changes v2 -> v3:
> - introduce PCI_FUNC_MAX
> - more commit log
>
> changes v1 -> v2:
> ---
> hw/pci.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
> hw/pci.h | 4 ++++
> 2 files changed, 61 insertions(+), 3 deletions(-)
>
> diff --git a/hw/pci.c b/hw/pci.c
> index b6c0a10..abc3c1d 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -67,6 +67,7 @@ static struct BusInfo pci_bus_info = {
> DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
> DEFINE_PROP_STRING("romfile", PCIDevice, romfile),
> DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1),
> + DEFINE_PROP_UINT8("multifunction", PCIDevice, mf, 0),
Please make this a bit property, not UINT8. It can be stored in
cap_present.
> DEFINE_PROP_END_OF_LIST()
> }
> };
> @@ -575,6 +576,44 @@ static void pci_init_wmask_bridge(PCIDevice *d)
> pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
> }
>
> +static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
> +{
IMO we should just add in pci_register_device:
if (d->cap_resent & QEMU_PCI_CAP_MULTIFUNCTION) {
dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
} else if (PCI_FUNC(dev->devfn)) {
error_report("PCI: single function device can't be populated %x.%x",
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
return -1;
}
And be done with it.
> + uint8_t slot = PCI_SLOT(dev->devfn);
> + uint8_t func = PCI_FUNC(dev->devfn);
> +
> + /* we are here before bus->devices[dev->devfn] = dev */
> + assert(!bus->devices[dev->devfn]);
Can users trigger this?
If yes, this needs and error, not an assert.
> +
> + if (dev->mf) {
> + dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
> + }
> +
> + if (func) {
Please open-code func above.
> + PCIDevice *d = bus->devices[PCI_DEVFN(slot, 0)];
> + if (d && !d->mf) {
> + /* function 0 should set multifunction bit */
> + error_report("PCI: single function device can't be populated "
> + "in function %x.%x", slot, func);
> + return -1;
> + }
> + return 0;
> + }
> +
> + if (dev->mf) {
> + return 0;
> + }
> + /* function 0 indicates single function, so function > 0 must be NULL */
We don't need the below test: each function will be checked
when it is added.
> + for (func = 1; func < PCI_FUNC_MAX; ++func) {
> + if (bus->devices[PCI_DEVFN(slot, func)]) {
> + error_report("PCI: %x.0 indicates single function, "
> + "but %x.%x is already populated.",
> + slot, slot, func);
> + return -1;
> + }
> + }
> + return 0;
> +}
> +
> static void pci_config_alloc(PCIDevice *pci_dev)
> {
> int config_size = pci_config_size(pci_dev);
> @@ -629,6 +668,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
> if (is_bridge) {
> pci_init_wmask_bridge(pci_dev);
> }
> + if (pci_init_multifunction(bus, pci_dev)) {
> + return NULL;
> + }
>
> if (!config_read)
> config_read = pci_default_read_config;
> @@ -1652,22 +1694,34 @@ void pci_qdev_register_many(PCIDeviceInfo *info)
> }
> }
>
> -PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name)
> +PCIDevice *pci_create_mf(PCIBus *bus, int devfn, uint8_t mf, const char *name)
> {
> DeviceState *dev;
>
> dev = qdev_create(&bus->qbus, name);
> qdev_prop_set_uint32(dev, "addr", devfn);
> + qdev_prop_set_uint8(dev, "multifunction", mf);
> return DO_UPCAST(PCIDevice, qdev, dev);
> }
>
> -PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
> +PCIDevice *pci_create_simple_mf(PCIBus *bus, int devfn, uint8_t mf,
> + const char *name)
> {
> - PCIDevice *dev = pci_create(bus, devfn, name);
> + PCIDevice *dev = pci_create_mf(bus, devfn, mf, name);
> qdev_init_nofail(&dev->qdev);
> return dev;
> }
>
> +PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name)
> +{
> + return pci_create_mf(bus, devfn, 0, name);
> +}
> +
> +PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
> +{
> + return pci_create_simple_mf(bus, devfn, 0, name);
> +}
> +
> static int pci_find_space(PCIDevice *pdev, uint8_t size)
> {
> int config_size = pci_config_size(pdev);
> diff --git a/hw/pci.h b/hw/pci.h
> index 76adc66..685fd44 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -131,6 +131,7 @@ struct PCIDevice {
> /* the following fields are read only */
> PCIBus *bus;
> uint32_t devfn;
> + uint8_t mf; /* multi function capabile device */
Add a bit in cap_present please.
> char name[64];
> PCIIORegion io_regions[PCI_NUM_REGIONS];
>
> @@ -343,6 +344,9 @@ typedef struct {
> void pci_qdev_register(PCIDeviceInfo *info);
> void pci_qdev_register_many(PCIDeviceInfo *info);
>
> +PCIDevice *pci_create_mf(PCIBus *bus, int devfn, uint8_t mf, const char *name);
> +PCIDevice *pci_create_simple_mf(PCIBus *bus, int devfn, uint8_t mf,
> + const char *name);
mf->multifunction
But do we need the extra functions? I thought qdev can handle
the flag?
> PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
> PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
>
> --
> 1.6.6.1
next prev parent reply other threads:[~2010-06-21 12:41 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-21 6:03 [Qemu-devel] [PATCH v4 0/6] pci: multi-function bit fixes Isaku Yamahata
2010-06-21 6:03 ` [Qemu-devel] [PATCH v4 1/6] pci: use PCI_DEVFN() where appropriate Isaku Yamahata
2010-06-21 11:57 ` [Qemu-devel] " Michael S. Tsirkin
2010-06-21 6:03 ` [Qemu-devel] [PATCH v4 2/6] pci: remove PCIDeviceInfo::header_type Isaku Yamahata
2010-06-21 6:03 ` [Qemu-devel] [PATCH v4 3/6] pci: set PCI multi-function bit appropriately Isaku Yamahata
2010-06-21 9:45 ` [Qemu-devel] " Juan Quintela
2010-06-21 9:52 ` Isaku Yamahata
2010-06-21 12:36 ` Michael S. Tsirkin [this message]
2010-06-23 7:25 ` Isaku Yamahata
2010-06-23 9:52 ` Michael S. Tsirkin
2010-06-23 10:13 ` Isaku Yamahata
2010-06-23 10:41 ` Michael S. Tsirkin
2010-06-23 23:48 ` Isaku Yamahata
2010-06-24 8:19 ` Michael S. Tsirkin
2010-06-21 6:03 ` [Qemu-devel] [PATCH v4 4/6] pci: don't overwrite multi functio bit in pci header type Isaku Yamahata
2010-06-21 13:15 ` [Qemu-devel] " Michael S. Tsirkin
2010-06-21 6:04 ` [Qemu-devel] [PATCH v4 5/6] pci: use pci_create_simple_mf() Isaku Yamahata
2010-06-21 6:04 ` [Qemu-devel] [PATCH v4 6/6] pci_bridge: make pci bridge aware of pci multi function bit Isaku Yamahata
2010-06-21 13:22 ` [Qemu-devel] " 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=20100621123600.GB10511@redhat.com \
--to=mst@redhat.com \
--cc=aurelien@aurel32.net \
--cc=blauwirbel@gmail.com \
--cc=paul@codesourcery.com \
--cc=qemu-devel@nongnu.org \
--cc=yamahata@valinux.co.jp \
--cc=yu.liu@freescale.com \
/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.