[PATCHv7 08/17] pci: PCIe driver for Marvell Armada 370/XP systems
Thomas Petazzoni
thomas.petazzoni at free-electrons.com
Tue Apr 9 06:57:41 EST 2013
Dear Bjorn Helgaas,
On Mon, 8 Apr 2013 14:29:59 -0600, Bjorn Helgaas wrote:
> > Signed-off-by: Thomas Petazzoni
> > <thomas.petazzoni at free-electrons.com>
>
> Acked-by: Bjorn Helgaas <bhelgaas at google.com>
>
> A few trivial comments below; it's up to you whether you do anything
> with them or not. It's OK with me if you ignore them :)
>
> The only thing I saw that might be a bug is the resource_size()
> question in mvebu_pcie_probe().
Thanks for the review!
> > diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> > new file mode 100644
> > index 0000000..3ad563f
> > --- /dev/null
> > +++ b/drivers/pci/host/Makefile
> > @@ -0,0 +1,4 @@
> > +obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> > +CFLAGS_pci-mvebu.o += \
> > + -I$(srctree)/arch/arm/plat-orion/include \
> > + -I$(srctree)/arch/arm/mach-mvebu/include
>
> Too bad to have to adjust CFLAGS here. Seems like I remember earlier
> discussion, but I didn't pay much attention, and if this is the best
> we can do, I guess it's OK.
Ah, indeed! This is now longer needed. The plat-orion include was
needed to get access to some PCIe functions, which are now part of the
driver, and the mach-mvebu header was needed to access some address
decoding window related functions, that are now part of the mvebu-mbus
driver.
> > +#define PCIE_BAR_CTRL_OFF(n) (0x1804 + ((n - 1) * 4))
>
> Strictly speaking, I suppose you should have "(((n) - 1) ..." here.
Correct, thanks.
> > +#define PCIE_STAT_OFF 0x1a04
> > +#define PCIE_STAT_DEV_OFFS 20
> > +#define PCIE_STAT_DEV_MASK 0x1f
> > +#define PCIE_STAT_BUS_OFFS 8
> > +#define PCIE_STAT_BUS_MASK 0xff
> > +#define PCIE_STAT_LINK_DOWN 1
>
> Whoever wrote pci_regs.h came up with a style I kind of like: the bit
> masks are already shifted so you can see where they are in the value,
> and there are no #defines for the shifts, e.g.,
>
> #define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
>
> The users of PCI_EXP_FLAGS_TYPE just have a bare ">> 4" where
> necessary. It seems like a good compromise that uses only one symbol
> (good for grepping), gives good visual indication in the header file
> of how the value is laid out, allows clearing bits without shifts, and
> clearly shows what's happening at the uses.
>
> But what you have is OK, too :)
Hum, ok, I'll try to think of it. Maybe too much of a 'big' change at
this point, but I'll see.
> > +static int mvebu_pcie_link_up(void __iomem *base)
>
> This could return bool, I guess.
Indeed.
> I think I would make
>
> mvebu_pcie_link_up()
> mvebu_pcie_set_local_bus_nr()
> mvebu_pcie_setup_wins()
> mvebu_pcie_setup_hw()
> mvebu_pcie_hw_rd_conf()
> mvebu_pcie_hw_wr_conf()
>
> all take a "struct mvebu_pcie_port *port" directly rather than having
> the caller pass in "port->base", but maybe you have a reason for doing
> otherwise.
I'll review this, I think your suggestion makes sense.
> > + /*
> > + * First, disable and clear BARs and windows.
> > + */
>
> Typically single-line comments would be "/* ... */" all on one line.
Correct.
> > + for (i = 1; i <= 2; i++) {
>
> Interesting use of "i <= 2" rather than the typical "i < 3".
I must confess this code comes from plat-orion/pcie.c, and I just
copy/pasted it (note: we intentionally don't use plat-orion/pcie.c to
avoid having to have to include a header in plat-orion/include, and
this plat-orion/pcie.c should ultimately go away once all Marvell EBU
platforms are migrated to use the new PCIe driver).
> > + /*
> > + * Enable interrupt lines A-D.
> > + */
> > + mask = readl(base + PCIE_MASK_OFF);
> > + mask |= 0x0f000000;
>
> No #defines for these bits?
Good point.
> > + writel(mask, base + PCIE_MASK_OFF);
> > +}
> > +
> > +static int mvebu_pcie_hw_rd_conf(void __iomem *base, struct
> > pci_bus *bus,
> > + u32 devfn, int where, int size,
> > u32 *val) +{
> > + writel(PCIE_CONF_BUS(bus->number) |
> > + PCIE_CONF_DEV(PCI_SLOT(devfn)) |
> > + PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
> > + PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN,
>
> A "PCIE_CONF_ADDR(busnr, devfn, where)" macro would be nice here.
Right.
> > +static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port
> > *port) +{
> > + phys_addr_t iobase;
> > +
> > + /* Are the current iobase/iolimit values invalid? */
>
> I first thought "current ... values" meant "the values before the
> change." If you used "new values" it might be clearer that this is
> used to handle *writes* to the window base/size registers, and that
> we're looking at the values being written.
Ok, makes sense indeed.
> > + return mvebu_sw_pci_bridge_write(port, where, size,
> > val);
> > + }
> > +
> > + return PCIBIOS_SUCCESSFUL;
>
> This last "return" is unreachable (I see you omitted it from the
> rd_conf() path already :)). This would be slightly simpler as:
>
> static struct mvebu_pcie_port *mvebu_find_port(struct mvebu_pcie
> *pcie, struct pci_bus *bus, int devfn)
> {
> int i;
>
> for (i = 0; i < pcie->nports; i++) {
> if ((bus->number == 0 && pcie->ports[i].devfn == devfn) ||
> (pcie->ports[porti].bridge.secondary_bus == bus->number))
> return &pcie->ports[i];
> }
> return NULL;
> }
>
> static int mvebu_pcie_wr_conf(struct pci_bus *bus, ...)
> {
> port = mvebu_find_port(pcie, bus, devfn);
> if (!port)
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> if (bus->number == 0)
> return mvebu_sw_pci_bridge_write(port, where, size, val);
>
> if (!port->haslink || PCI_SLOT(devfn) != 0)
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> ...
> return ret;
> }
Ok, I'll have a look at this.
> > IORESOURCE_TYPE_BITS;
> > + if (restype == IORESOURCE_IO) {
> > + of_pci_range_to_resource(&range, np,
> > &pcie->io);
> > + of_pci_range_to_resource(&range, np,
> > &pcie->realio);
> > + pcie->io.name = "I/O";
> > + pcie->realio.start = PCIBIOS_MIN_IO;
> > + pcie->realio.end =
> > min(resource_size(&pcie->io),
> > + IO_SPACE_LIMIT);
>
> Using "resource_size(&pcie->io)" here seems strange -- are you
> assuming that pcie->io starts at address zero?
No, I'm assuming PCIBIOS_MIN_IO is always 0. So presumarly, this should
be something like:
pcie->realio.end = min(PCIBIOS_MIN_IO +
resource_size(&pcie->io),
IO_SPACE_LIMIT);
Thanks for all your valuable comments!
Thomas
--
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
More information about the devicetree-discuss
mailing list