From: Andrew Jones <drjones@redhat.com>
To: Alexander Gordeev <agordeev@redhat.com>
Cc: kvmarm@lists.cs.columbia.edu
Subject: Re: [kvm-unit-tests PATCH 02/11] arm/pci: PCI bus scanning
Date: Tue, 2 Feb 2016 12:20:06 +0100 [thread overview]
Message-ID: <20160202112006.GD3688@hawk.localdomain> (raw)
In-Reply-To: <20160202093400.GA27102@dhcp-27-118.brq.redhat.com>
On Tue, Feb 02, 2016 at 10:34:01AM +0100, Alexander Gordeev wrote:
> On Wed, Jan 13, 2016 at 04:58:46PM +0100, Andrew Jones wrote:
> > On Sat, Jan 09, 2016 at 01:22:49PM +0100, Alexander Gordeev wrote:
> > > Scan bus 0 and function 0 only for now
> > >
> > > Cc: Andrew Jones <drjones@redhat.com>
> > > Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
> > > ---
> > > arm/pci-test.c | 4 +++
> > > lib/pci-host-generic.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > > lib/pci-host-generic.h | 1 +
> > > lib/pci.h | 1 +
> > > 4 files changed, 73 insertions(+)
> > >
> > > diff --git a/arm/pci-test.c b/arm/pci-test.c
> > > index 8629c89..1539d3e 100644
> > > --- a/arm/pci-test.c
> > > +++ b/arm/pci-test.c
> > > @@ -11,6 +11,7 @@
> > > int main(void)
> > > {
> > > struct pci *pci;
> > > + int ret;
> > >
> > > pci = pci_dt_probe();
> > >
> > > @@ -18,6 +19,9 @@ int main(void)
> > > if (!pci)
> > > goto done;
> > >
> > > + ret = pci_bus_scan(pci);
> > > + report("PCI bus scanning detected %d devices", true, ret);
> >
> > How many devices are expected in this test? You can pass the expected
> > number in on the command line, and then make this a "real" test report
> > with
> >
> > report(..., ret == atol(argv[0]), ret)
>
> What if a machine's PCI hierarchy changed? Such test would break then.
How would the number *of* detected devices change if we never pass more
or less devices on the qemu command line? I realize the PCI addresses
may change.
>
> Also, this report is not entirely dummy. It ensures PCI configuration
> space access operates, devices do respond and generally the bus is fine.
>
> > > +
> > > pci_shutdown(pci);
> > >
> > > done:
> > > diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c
> > > index 62b5662..e479989 100644
> > > --- a/lib/pci-host-generic.c
> > > +++ b/lib/pci-host-generic.c
> > > @@ -14,6 +14,49 @@
> > > #include "pci-host-generic.h"
> > > #include <linux/pci_regs.h>
> > >
> > > +#define for_each_pci_dev(pci, dev, conf) \
> > > + for (dev = find_next_dev(pci, -1, &conf); \
> > > + dev >= 0; \
> > > + dev = find_next_dev(pci, dev, &conf))
> >
> > Why do we need to pass both a dev index and a conf
> > pointer? I see below you can get the later from the
> > former easily enough.
>
> No particular reason apart from the fact each for_each_pci_dev()
> would be followed by dev_conf() call - so I paired it to save
> few lines. I have no preference here, though.
Then please drop one or the other.
>
> > > +
> > > +static u8 pci_config_readb(const void *conf, int off)
> > > +{
> > > + return readb(conf + off);
> > > +}
> > > +
> > > +static u32 pci_config_readl(const void *conf, int off)
> > > +{
> > > + return readl(conf + off);
> > > +}
> > > +
> > > +static void pci_config_writel(u32 val, void *conf, int off)
> > > +{
> > > + writel(val, conf + off);
> > > +}
> >
> > These read/write wrappers don't look all that useful to me. They would
> > be more useful if they took a 'struct pci[_dev] like Linux's
> > pci_read_config_byte/word/dword do. In fact, stealing those from Linux
> > makes sense.
>
> I put those ones only to emphasize PCI reads/writes as opposed to
> direct read*/write* accesses. Matching the Linux names is probably
> confusing.
>
> Bringing Linux-like pci_read_config_byte/word/dword seems as an
> overkill to me as it entails pulling the whole data hierarchy
> pci_host_bridge->pci_bus->pci_dev.
>
> By contrast, if we do not pull the whole hierarchy then we could
> introduce our own minimalistic data structure(s) and get off with
> it easily.
Yes, that's what I was thinking. We already do have our own minimalistic
data structure 'struct pci[_dev]'. However, now that I've made x86 pci
code common you'll either just need to create a lib/arm/asm/pci.h with
a pci_config_read like in lib/x86/asm/pci.h, or perhaps expand on that
if you need to read different sizes, by adding the _byte/word/...
variants.
>
> > > +
> > > +static void* dev_conf(struct pci *pci, int dev)
> > > +{
> > > + struct pci_host_bridge *host = pci->sysdata;
> > > + return (void*)host->cpu_range.start + (dev * 8) * PCI_ECAM_CONFIG_SIZE;
> > > +}
> > > +
> > > +/* We scan bus 0 only for now */
> > > +static int find_next_dev(struct pci *pci, int dev, void **pconf)
> > > +{
> > > + struct pci_host_bridge *host = pci->sysdata;
> > > + int limit = MIN(32u, host->cpu_range.size / PCI_ECAM_CONFIG_SIZE);
> >
> > 32 is the pci max devices per bus limit, right? Assuming a sane DT, is it
> > possible to have host->cpu_range.size/PCI_ECAM_CONFIG_SIZE > 32?
>
> The point here is not host->cpu_range.size/PCI_ECAM_CONFIG_SIZE > 32
> but rather host->cpu_range.size/PCI_ECAM_CONFIG_SIZE < 32.
>
> But you are right - a bus with less than 32 device slots is likely
> insane.
>
> > > +
> > > + for (dev++; dev < limit; dev++) {
> > > + void *conf = dev_conf(pci, dev);
> > > + if (pci_config_readl(conf, PCI_VENDOR_ID) != ((u32)~0)) {
> > > + *pconf = conf;
> > > + return dev;
> > > + }
> > > + }
> > > +
> > > + return -1;
> > > +}
> > > +
> > > static void pci_host_addr_space_init(struct pci_addr_space as[], int nr_as,
> > > u32 cells[], int nr_range_cells)
> > > {
> > > @@ -133,6 +176,24 @@ static struct pci_host_bridge *pci_host_bridge_probe(void)
> > > return host;
> > > }
> > >
> > > +int pci_bus_scan(struct pci *pci)
> > > +{
> > > + void *conf;
> > > + int dev;
> > > + int nr_dev = 0;
> > > +
> > > + for_each_pci_dev(pci, dev, conf) {
> > > + /* We are only interested in normal PCI devices */
> > > + if (pci_config_readb(conf, PCI_HEADER_TYPE) !=
> > > + PCI_HEADER_TYPE_NORMAL)
> > > + continue;
> > > + pci_config_writel(PCI_COMMAND_SERR, conf, PCI_COMMAND);
> >
> > Shouldn't the driver (unit test) be the one that writes SERR? Also,
> > doesn't this clear everything in the Command register except SERR?
>
> I do not thing a driver is in charge. It is a minimal devices
> initialization that is expected from firmware/BIOS AFAICT. A driver
> should inherit the properly initialized bus with allocated io/memory
> buffers to use.
OK, does QEMU not provide that already?
>
> > If a scan gets run again after driver/unittest has started using a device
> > then this write may mess things up.
>
> PCI bus scan is normally done once to initialize hierarchy. I am
> struggling to imagine a usecase when it is called repeatedly,
> especially in such a small framework.
A unit test can do whatever it likes. I'd like the initial setup to be
useful, but minimal, and easily modifiable.
>
> > > + nr_dev++;
> > > + }
> > > +
> > > + return nr_dev;
> > > +}
> > > +
> > > struct pci *pci_dt_probe(void)
> > > {
> > > struct pci_host_bridge *host;
> > > @@ -150,6 +211,12 @@ struct pci *pci_dt_probe(void)
> > >
> > > void pci_shutdown(struct pci *pci)
> > > {
> > > + void *conf;
> > > + int dev;
> > > +
> > > + for_each_pci_dev(pci, dev, conf)
> > > + pci_config_writel(PCI_COMMAND_INTX_DISABLE, conf, PCI_COMMAND);
> >
> > I think I know why this is here, but I don't think that kvm-unit-tests
> > needs to bother with it.
>
> Well, it is not about interrupts, rather about disabling devices
> access to access io/memory buffers, which is writing 0 to the
> command regiester. PCI_COMMAND_INTX_DISABLE is just a good one
> to write as well.
>
> BTW, this is the reason I named this routine pci_shutdown(), not
> pci_free().
I'm currently thinking any sort of shutdown is overkill for
kvm-unit-tests, but I'll accept anything you can make a good
case for :-)
>
> > > +
> > > free(pci->sysdata);
> > > free(pci);
> > > }
> > > diff --git a/lib/pci-host-generic.h b/lib/pci-host-generic.h
> > > index 097ac2d..c14d32d 100644
> > > --- a/lib/pci-host-generic.h
> > > +++ b/lib/pci-host-generic.h
> > > @@ -22,5 +22,6 @@ struct pci_host_bridge {
> > > };
> > >
> > > #define PCI_ECAM_BUS_SIZE (1 << 20)
> > > +#define PCI_ECAM_CONFIG_SIZE (1 << 12)
> >
> > Are these also defined in the Linux kernel? I'm too lazy to pull up the
> > PCI spec right now, so I'd rather confirm the sizes by looking them up
> > in Linux. If they are defined there somewhere, then please use the same
> > names here. Otherwise, I guess references to some documentation or
> > something would be nice for pci dummies like me.
> >
> > >
> > > #endif
> > > diff --git a/lib/pci.h b/lib/pci.h
> > > index 22b8e31..bc4f2d2 100644
> > > --- a/lib/pci.h
> > > +++ b/lib/pci.h
> > > @@ -8,6 +8,7 @@ struct pci {
> > > };
> > >
> > > extern struct pci *pci_dt_probe(void);
> > > +extern int pci_bus_scan(struct pci *pci);
> > > extern void pci_shutdown(struct pci *pci);
> > >
> > > #endif
> > > --
> > > 1.8.3.1
> > >
next prev parent reply other threads:[~2016-02-02 11:14 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-09 12:22 [kvm-unit-tests PATCH 00/11] pci/arm: add PCI bus support Alexander Gordeev
2016-01-09 12:22 ` [kvm-unit-tests PATCH 01/11] arm/pci: Device tree PCI probing Alexander Gordeev
2016-01-13 15:13 ` Andrew Jones
2016-01-28 15:17 ` Alexander Gordeev
2016-01-28 16:40 ` Andrew Jones
2016-02-05 11:48 ` Alexander Gordeev
2016-02-05 12:18 ` Andrew Jones
2016-01-09 12:22 ` [kvm-unit-tests PATCH 02/11] arm/pci: PCI bus scanning Alexander Gordeev
2016-01-13 15:58 ` Andrew Jones
2016-02-02 9:34 ` Alexander Gordeev
2016-02-02 11:20 ` Andrew Jones [this message]
2016-01-09 12:22 ` [kvm-unit-tests PATCH 03/11] arm/pci: Read devices BARs Alexander Gordeev
2016-01-09 12:22 ` [kvm-unit-tests PATCH 04/11] arm/pci: Allocate and assign memory/io space resources Alexander Gordeev
2016-01-09 12:22 ` [kvm-unit-tests PATCH 05/11] arm/pci: Add pci_find_dev() and pci_bar_addr() functions Alexander Gordeev
2016-01-15 15:17 ` Andrew Jones
2016-01-09 12:22 ` [kvm-unit-tests PATCH 06/11] arm/pci: PCI testdev existence test Alexander Gordeev
2016-01-09 12:22 ` [kvm-unit-tests PATCH 07/11] arm/pci: PCI device operation test Alexander Gordeev
2016-01-15 15:32 ` Andrew Jones
2016-02-04 12:18 ` Alexander Gordeev
2016-02-04 15:31 ` Andrew Jones
2016-01-09 12:22 ` [kvm-unit-tests PATCH 08/11] arm/pci: PCI device read/write test Alexander Gordeev
2016-01-15 15:33 ` Andrew Jones
2016-02-04 12:03 ` Alexander Gordeev
2016-01-15 15:34 ` Andrew Jones
2016-01-09 12:22 ` [kvm-unit-tests PATCH 09/11] arm/pci: PCI host bridge info printing Alexander Gordeev
2016-01-15 15:35 ` Andrew Jones
2016-01-09 12:22 ` [kvm-unit-tests PATCH 10/11] arm/pci: PCI devices basic " Alexander Gordeev
2016-01-15 15:38 ` Andrew Jones
2016-01-09 12:22 ` [kvm-unit-tests PATCH 11/11] arm/pci: PCI testdev test flavour printing Alexander Gordeev
2016-01-15 15:39 ` Andrew Jones
2016-01-15 15:42 ` [kvm-unit-tests PATCH 00/11] pci/arm: add PCI bus support Andrew Jones
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=20160202112006.GD3688@hawk.localdomain \
--to=drjones@redhat.com \
--cc=agordeev@redhat.com \
--cc=kvmarm@lists.cs.columbia.edu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox