Message ID | 1563200177-8380-1-git-send-email-jaz@semihalf.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | PCI: pci-bridge-emul: fix big-endian support | expand |
On Mon, Jul 15, 2019 at 04:16:17PM +0200, Grzegorz Jaszczyk wrote: > Perform conversion to little-endian before every write to configuration > space and converse back to cpu endianness during read. Additionally > initialise every not-byte wide fields of config space with proper > cpu_to_le* macro. > > This is required since the structure describing config space of emulated > bridge assumes little-endian convention. This is insufficient - pci-bridge-emul.h needs to be fixed up to use __le32 and __le16. It is a good idea to check such changes with sparse - a tool originally written by Linus, which is able to detect incorrect endian accesses (iow, access to LE members without using a LE accessor.) Such checks rely on using the right types.
Hi Russell pon., 15 lip 2019 o 16:30 Russell King - ARM Linux admin <linux@armlinux.org.uk> napisaĆ(a): > This is insufficient - pci-bridge-emul.h needs to be fixed up to use > __le32 and __le16. > > It is a good idea to check such changes with sparse - a tool originally > written by Linus, which is able to detect incorrect endian accesses > (iow, access to LE members without using a LE accessor.) Such checks > rely on using the right types. Thank you for pointing this out - it is really usefully tool. I will send v2 soon. regards, Grzegorz
diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 83fb077..d1235d2 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -270,10 +270,10 @@ const static struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = { int pci_bridge_emul_init(struct pci_bridge_emul *bridge, unsigned int flags) { - bridge->conf.class_revision |= PCI_CLASS_BRIDGE_PCI << 16; + bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16); bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; bridge->conf.cache_line_size = 0x10; - bridge->conf.status = PCI_STATUS_CAP_LIST; + bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST); bridge->pci_regs_behavior = kmemdup(pci_regs_behavior, sizeof(pci_regs_behavior), GFP_KERNEL); @@ -357,7 +357,7 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where, ret = PCI_BRIDGE_EMUL_NOT_HANDLED; if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) - *value = cfgspace[reg / 4]; + *value = le32_to_cpu(cfgspace[reg / 4]); /* * Make sure we never return any reserved bit with a value @@ -431,7 +431,7 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, /* Clear the W1C bits */ new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); - cfgspace[reg / 4] = new; + cfgspace[reg / 4] = cpu_to_le32(new); if (write_op) write_op(bridge, reg, old, new, mask);
Perform conversion to little-endian before every write to configuration space and converse back to cpu endianness during read. Additionally initialise every not-byte wide fields of config space with proper cpu_to_le* macro. This is required since the structure describing config space of emulated bridge assumes little-endian convention. Signed-off-by: Grzegorz Jaszczyk <jaz@semihalf.com> --- drivers/pci/pci-bridge-emul.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)