[gPXE] [PATCH] [rtl818x] Remove broken mmio register support

Stefan Hajnoczi stefanha at gmail.com
Mon Jan 25 04:14:59 EST 2010


On Sat, Jan 23, 2010 at 8:34 AM, Joshua Oreman <oremanj at rwcr.net> wrote:
> Is this patch based on theory or do you have a testcase for it?

I don't have rtl818x hardware for testing, but the code in gPXE is not
equivalent to that in Linux.  I spotted this issue when grepping for
membase and pci_bar_size() usage in gPXE.

Here is the relevant linux-2.6.git rtl818x code:

unsigned long mem_addr, mem_len;
unsigned int io_addr, io_len;
[...]
io_addr = pci_resource_start(pdev, 0);
io_len = pci_resource_len(pdev, 0);
mem_addr = pci_resource_start(pdev, 1);
mem_len = pci_resource_len(pdev, 1);
[...]
priv->map = pci_iomap(pdev, 1, mem_len);
if (!priv->map)
	priv->map = pci_iomap(pdev, 0, io_len);

if (!priv->map) {
	printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n",
	       pci_name(pdev));
	goto err_free_dev;
}

The pci_iomap() function says:
 * Using this function you will get a __iomem address to your device BAR.
 * You can access it using ioread*() and iowrite*(). These functions hide
 * the details if this is a MMIO or PIO address space and will just do what
 * you expect from them in the correct way.

When the Linux driver uses ioread32() and friends, inl() or readl() is chosen
at runtime, based on whether this is a programmed I/O or memory-mapped
I/O address:
unsigned int ioread32(void __iomem *addr)
{
	IO_COND(addr, return inl(port), return readl(addr));
	return 0xffffffff;
}

The gPXE code is not equivalent since we don't have
pci_iomap()/ioread*()/iowrite*().  The gPXE code always uses the programmed I/O
functions:
static inline u32 rtl818x_ioread32(struct rtl818x_priv *priv __unused,
u32 *addr)
{
        return inl(addr);
}

Passing a memory address to inl() does not work.  It is like trying to use a
MAC address as an IP address - they are different address spaces.

The patch I posted simply removes the memory-mapped I/O fallback.  We could
make rtl818x_ioread*/rtl818x_iowrite* conditional or introduce the pci_iomap
API into gPXE instead.

No other driver in gPXE supports both programmed I/O and memory-mapped I/O at
runtime, so the pci_iomap API would not see much use at the moment and
perhaps take up code space.

Stefan


More information about the gPXE mailing list