[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5673E9E2.6070507@synopsys.com>
Date: Fri, 18 Dec 2015 11:11:30 +0000
From: Joao Pinto <Joao.Pinto@...opsys.com>
To: Bjorn Helgaas <helgaas@...nel.org>,
Joao Pinto <Joao.Pinto@...opsys.com>
CC: <Vineet.Gupta1@...opsys.com>, <linux-pci@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <CARLOS.PALMINHA@...opsys.com>,
<Alexey.Brodkin@...opsys.com>, <robh+dt@...nel.org>,
<pawel.moll@....com>, <mark.rutland@....com>,
<ijc+devicetree@...lion.org.uk>, <galak@...eaurora.org>
Subject: Re: [PATCH v2 1/2] PCI support added to ARC
Hi Bjorn,
Thanks for the review. I am going to simplify the code and send a v3 patch set.
Joao
On 12/17/2015 9:11 PM, Bjorn Helgaas wrote:
> On Wed, Dec 16, 2015 at 02:14:55PM +0000, Joao Pinto wrote:
>> This patch adds PCI support to ARC and updates drivers/pci Makefile enabling
>> the ARC arch to use the generic PCI setup functions.
>>
>> Signed-off-by: Joao Pinto <jpinto@...opsys.com>
>
> Checkpatch complains about some whitespace errors (new blank lines at
> EOF).
>
> Hmmm, almost all of this appears to be copied straight from arch/arm,
> but almost none of it is actually used. If that's true, it's good
> because you can make the patches much smaller. But it's a little bit
> bad, too, because it means we almost merged a bunch of dead code.
>
>> ---
>> Change v1 -> v2:
>> - In arch/arc/Kconfig, the new menu entry (Bus Configuration) was moved to the
>> slot between sourcing of drivers/Kconfig and fs/Kconfig (Vineet Gupta)
>> - In arch/arc/plat-axs10x/Kconfig the "select MIGHT_HAVE_PCI" option was placed
>> in order as suggested (Vineet Gupta)
>> - ioport_map() and ioport_unmap() were static inlined and included in
>> the io.h (Vineet Gupta)
>> - pcibios_min_io and pcibios_min_mem declaration moved to
>> pcibios.c (Vineet Gupta)
>> - pr_err() replaced by dev_err() in pcibios_enable_device() (Bjorn Helgaas)
>> - string simplified in pcibios_enable_device() (Vineet Gupta)
>> - pci_host_bridge_window structure was replaced by resource_entry structure, and
>> list_for_each_entry() for resource_list_for_each_entry() in pcibios.c
>>
>> arch/arc/Kconfig | 23 +++
>> arch/arc/include/asm/dma.h | 5 +
>> arch/arc/include/asm/io.h | 10 ++
>> arch/arc/include/asm/mach/pci.h | 97 +++++++++++
>> arch/arc/include/asm/pci.h | 34 ++++
>> arch/arc/kernel/Makefile | 1 +
>> arch/arc/kernel/pcibios.c | 358 ++++++++++++++++++++++++++++++++++++++++
>> arch/arc/mm/ioremap.c | 10 +-
>> arch/arc/plat-axs10x/Kconfig | 1 +
>> drivers/pci/Makefile | 1 +
>> 10 files changed, 539 insertions(+), 1 deletion(-)
>> create mode 100644 arch/arc/include/asm/mach/pci.h
>> create mode 100644 arch/arc/include/asm/pci.h
>> create mode 100644 arch/arc/kernel/pcibios.c
>>
>> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
>> index 2c2ac3f..98b32c1 100644
>> --- a/arch/arc/Kconfig
>> +++ b/arch/arc/Kconfig
>> @@ -19,6 +19,7 @@ config ARC
>> select GENERIC_FIND_FIRST_BIT
>> # for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
>> select GENERIC_IRQ_SHOW
>> + select GENERIC_PCI_IOMAP
>> select GENERIC_PENDING_IRQ if SMP
>> select GENERIC_SMP_IDLE_THREAD
>> select HAVE_ARCH_KGDB
>> @@ -39,6 +40,9 @@ config ARC
>> select PERF_USE_VMALLOC
>> select HAVE_DEBUG_STACKOVERFLOW
>>
>> +config MIGHT_HAVE_PCI
>> + bool
>> +
>> config TRACE_IRQFLAGS_SUPPORT
>> def_bool y
>>
>> @@ -570,6 +574,25 @@ endmenu # "ARC Architecture Configuration"
>> source "mm/Kconfig"
>> source "net/Kconfig"
>> source "drivers/Kconfig"
>> +
>> +menu "Bus Support"
>> +
>> +config PCI
>> + bool "PCI support" if MIGHT_HAVE_PCI
>> + help
>> + PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside
>> + your box.Find out if your board/platform have PCI.
>> + Note: PCIE support for Synopsys Device will be available only when
>> + HAPS DX is configured with PCIE RC bitmap. If you have PCI, say Y, otherwise N.
>> +
>> +config PCI_SYSCALL
>> + def_bool PCI
>> +
>> +source "drivers/pci/Kconfig"
>> +source "drivers/pci/pcie/Kconfig"
>> +
>> +endmenu
>> +
>> source "fs/Kconfig"
>> source "arch/arc/Kconfig.debug"
>> source "security/Kconfig"
>> diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h
>> index ca7c451..37942fa 100644
>> --- a/arch/arc/include/asm/dma.h
>> +++ b/arch/arc/include/asm/dma.h
>> @@ -10,5 +10,10 @@
>> #define ASM_ARC_DMA_H
>>
>> #define MAX_DMA_ADDRESS 0xC0000000
>> +#ifdef CONFIG_PCI
>> +extern int isa_dma_bridge_buggy;
>> +#else
>> +#define isa_dma_bridge_buggy (0)
>> +#endif
>>
>> #endif
>> diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
>> index 694ece8..2ec3cf4 100644
>> --- a/arch/arc/include/asm/io.h
>> +++ b/arch/arc/include/asm/io.h
>> @@ -16,7 +16,17 @@
>> extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
>> extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
>> unsigned long flags);
>> +static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
>> +{
>> + return (void __iomem *)port;
>> +}
>> +
>> +static inline void ioport_unmap(void __iomem *addr)
>> +{
>> +}
>> +
>> extern void iounmap(const void __iomem *addr);
>> +extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
>>
>> #define ioremap_nocache(phy, sz) ioremap(phy, sz)
>> #define ioremap_wc(phy, sz) ioremap(phy, sz)
>> diff --git a/arch/arc/include/asm/mach/pci.h b/arch/arc/include/asm/mach/pci.h
>> new file mode 100644
>> index 0000000..9e75277
>> --- /dev/null
>> +++ b/arch/arc/include/asm/mach/pci.h
>> @@ -0,0 +1,97 @@
>> +/*
>> + * arch/arc/include/asm/mach/pci.h
>> + *
>> + * Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __ASM_MACH_PCI_H
>> +#define __ASM_MACH_PCI_H
>> +
>> +#include <linux/ioport.h>
>> +
>> +struct pci_sys_data;
>> +struct pci_ops;
>> +struct pci_bus;
>> +struct device;
>> +
>> +struct hw_pci {
>> +#ifdef CONFIG_PCI_DOMAINS
>> + int domain;
>> +#endif
>> + struct pci_ops *ops;
>> + int nr_controllers;
>> + void **private_data;
>> + int (*setup)(int nr, struct pci_sys_data *);
>> + struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
>> + void (*preinit)(void);
>> + void (*postinit)(void);
>> + u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
>> + int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
>> + resource_size_t (*align_resource)(struct pci_dev *dev,
>> + const struct resource *res,
>> + resource_size_t start,
>> + resource_size_t size,
>> + resource_size_t align);
>> + void (*add_bus)(struct pci_bus *bus);
>> + void (*remove_bus)(struct pci_bus *bus);
>> +};
>> +
>> +/*
>> + * Per-controller structure
>> + */
>> +struct pci_sys_data {
>> +#ifdef CONFIG_PCI_DOMAINS
>> + int domain;
>> +#endif
>> + struct list_head node;
>> + int busnr; /* primary bus number */
>> + u64 mem_offset; /* bus->cpu memory mapping offset */
>> + unsigned long io_offset; /* bus->cpu IO mapping offset */
>> + struct pci_bus *bus; /* PCI bus */
>> + struct list_head resources; /* root bus resources (apertures) */
>> + struct resource io_res;
>> + char io_res_name[12];
>> + /* Bridge swizzling */
>> + u8 (*swizzle)(struct pci_dev *, u8 *);
>> + /* IRQ mapping */
>> + int (*map_irq)(const struct pci_dev *, u8, u8);
>> + /* Resource alignement requirements */
>> + resource_size_t (*align_resource)(struct pci_dev *dev,
>> + const struct resource *res,
>> + resource_size_t start,
>> + resource_size_t size,
>> + resource_size_t align);
>> + void (*add_bus)(struct pci_bus *bus);
>> + void (*remove_bus)(struct pci_bus *bus);
>> + void *private_data; /* platform controller private data */
>> +};
>> +
>> +/*
>> + * Call this with your hw_pci struct to initialise the PCI system.
>> + */
>> +void pci_common_init_dev(struct device *, struct hw_pci *);
>> +
>> +/*
>> + * Compatibility wrapper for older platforms that do not care about
>> + * passing the parent device.
>> + */
>> +static inline void pci_common_init(struct hw_pci *hw)
>> +{
>> + pci_common_init_dev(NULL, hw);
>> +}
>
> All the above stuff (hw_pci, pci_sys_data, pci_common_init_dev(),
> pci_common_init()) appears to be unused.
>
>> +
>> +/*
>> + * Setup early fixed I/O mapping.
>> + */
>> +#if defined(CONFIG_PCI)
>> +extern void pci_map_io_early(unsigned long pfn);
>> +#else
>> +static inline void pci_map_io_early(unsigned long pfn) {}
>> +#endif
>> +
>> +#endif /* __ASM_MACH_PCI_H */
>> +
>> diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
>> new file mode 100644
>> index 0000000..085b15f
>> --- /dev/null
>> +++ b/arch/arc/include/asm/pci.h
>> @@ -0,0 +1,34 @@
>> +/*
>> + * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef _ASM_ARC_PCI_H
>> +#define _ASM_ARC_PCI_H
>> +
>> +#ifdef __KERNEL__
>> +#include <asm-generic/pci-dma-compat.h>
>> +#include <asm-generic/pci-bridge.h>
>> +
>> +#include <asm/mach/pci.h> /* for pci_sys_data */
>> +
>> +extern unsigned long pcibios_min_io;
>> +#define PCIBIOS_MIN_IO pcibios_min_io
>> +extern unsigned long pcibios_min_mem;
>> +#define PCIBIOS_MIN_MEM pcibios_min_mem
>> +
>> +#define pcibios_assign_all_busses() 1
>> +/*
>> + * The PCI address space does equal the physical memory address space.
>> + * The networking and block device layers use this boolean for bounce
>> + * buffer decisions.
>> + */
>> +#define PCI_DMA_BUS_IS_PHYS (1)
>> +
>> +#endif /* __KERNEL__ */
>> +
>> +#endif /* _ASM_ARC_PCI_H */
>> +
>> diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
>> index e7f3625..1bc2036 100644
>> --- a/arch/arc/kernel/Makefile
>> +++ b/arch/arc/kernel/Makefile
>> @@ -12,6 +12,7 @@ obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
>> obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
>> obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o
>> obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o
>> +obj-$(CONFIG_PCI) += pcibios.o
>>
>> obj-$(CONFIG_MODULES) += arcksyms.o module.o
>> obj-$(CONFIG_SMP) += smp.o
>> diff --git a/arch/arc/kernel/pcibios.c b/arch/arc/kernel/pcibios.c
>> new file mode 100644
>> index 0000000..5af7bf0
>> --- /dev/null
>> +++ b/arch/arc/kernel/pcibios.c
>> @@ -0,0 +1,358 @@
>> +/*
>> + * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/pci.h>
>> +#include <linux/delay.h>
>> +#include <linux/string.h>
>> +#include <linux/init.h>
>> +#include <linux/sched.h>
>> +#include <linux/errno.h>
>> +#include <linux/bootmem.h>
>> +#include <linux/sizes.h>
>> +#include <linux/slab.h>
>> +
>> +#include <asm/pci.h>
>> +#include <asm/mach/pci.h>
>> +
>> +unsigned long pcibios_min_io = 0x100;
>> +EXPORT_SYMBOL(pcibios_min_io);
>> +
>> +unsigned long pcibios_min_mem = 0x100000;
>> +EXPORT_SYMBOL(pcibios_min_mem);
>> +
>> +static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
>> +{
>> + int ret;
>> + struct resource_entry *window;
>> +
>> + if (list_empty(&sys->resources)) {
>> + pci_add_resource_offset(&sys->resources,
>> + &iomem_resource, sys->mem_offset);
>> + }
>> +
>> + resource_list_for_each_entry(window, &sys->resources) {
>> + if (resource_type(window->res) == IORESOURCE_IO)
>> + return 0;
>> + }
>> +
>> + sys->io_res.start = (busnr * SZ_64K) ? : pcibios_min_io;
>> + sys->io_res.end = (busnr + 1) * SZ_64K - 1;
>> + sys->io_res.flags = IORESOURCE_IO;
>> + sys->io_res.name = sys->io_res_name;
>> + sprintf(sys->io_res_name, "PCI%d I/O", busnr);
>> +
>> + ret = request_resource(&ioport_resource, &sys->io_res);
>> + if (ret) {
>> + pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
>> + return ret;
>> + }
>> + pci_add_resource_offset(&sys->resources, &sys->io_res,
>> + sys->io_offset);
>> +
>> + return 0;
>> +}
>
> Appears unused.
>
>> +static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
>> + struct list_head *head)
>> +{
>> + struct pci_sys_data *sys = NULL;
>> + int ret;
>> + int nr, busnr;
>> +
>> + for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
>> + sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
>> + if (!sys)
>> + panic("PCI: unable to allocate sys data!");
>> +
>> +#ifdef CONFIG_PCI_DOMAINS
>> + sys->domain = hw->domain;
>> +#endif
>> + sys->busnr = busnr;
>> + sys->swizzle = hw->swizzle;
>> + sys->map_irq = hw->map_irq;
>> + sys->align_resource = hw->align_resource;
>> + sys->add_bus = hw->add_bus;
>> + sys->remove_bus = hw->remove_bus;
>> + INIT_LIST_HEAD(&sys->resources);
>> +
>> +
>> + if (hw->private_data)
>> + sys->private_data = hw->private_data[nr];
>> +
>> + ret = hw->setup(nr, sys);
>> +
>> + if (ret > 0) {
>> + ret = pcibios_init_resources(nr, sys);
>> + if (ret) {
>> + kfree(sys);
>> + break;
>> + }
>> +
>> + if (hw->scan)
>> + sys->bus = hw->scan(nr, sys);
>> + else
>> + sys->bus = pci_scan_root_bus(parent, sys->busnr,
>> + hw->ops, sys, &sys->resources);
>> +
>> + if (!sys->bus)
>> + panic("PCI: unable to scan bus!");
>> +
>> + busnr = sys->bus->busn_res.end + 1;
>> +
>> + list_add(&sys->node, head);
>> + } else {
>> + kfree(sys);
>> + if (ret < 0)
>> + break;
>> + }
>> + }
>> +}
>
> Appears unused.
>
>> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>> +{
>> + return 0;
>> +}
>> +
>> +void pcibios_add_bus(struct pci_bus *bus)
>> +{
>> +}
>> +
>> +void pcibios_remove_bus(struct pci_bus *bus)
>> +{
>> +}
>
> The above three are Unnecessary since drivers/pci/probe.c defines
> default (weak) versions.
>
>> +/*
>> + * Swizzle the device pin each time we cross a bridge. If a platform does
>> + * not provide a swizzle function, we perform the standard PCI swizzling.
>> + *
>> + * The default swizzling walks up the bus tree one level at a time, applying
>> + * the standard swizzle function at each step, stopping when it finds the PCI
>> + * root bus. This will return the slot number of the bridge device on the
>> + * root bus and the interrupt pin on that device which should correspond
>> + * with the downstream device interrupt.
>> + *
>> + * Platforms may override this, in which case the slot and pin returned
>> + * depend entirely on the platform code. However, please note that the
>> + * PCI standard swizzle is implemented on plug-in cards and Cardbus based
>> + * PCI extenders, so it can not be ignored.
>> + */
>> +static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
>> +{
>> + int slot;
>> + struct pci_sys_data *sys = dev->sysdata;
>> +
>> + if (sys->swizzle)
>> + slot = sys->swizzle(dev, pin);
>> + else
>> + slot = pci_common_swizzle(dev, pin);
>> +
>> + return slot;
>> +}
>
> Appears unused.
>
>> +/*
>> + * Map a slot/pin to an IRQ.
>> + */
>> +static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>> +{
>> + struct pci_sys_data *sys = dev->sysdata;
>> + int irq = -1;
>> +
>> + if (sys->map_irq)
>> + irq = sys->map_irq(dev, slot, pin);
>> +
>> + return irq;
>> +}
>
> Appears unused.
>
>> +void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
>> +{
>> + struct pci_sys_data *sys;
>> + LIST_HEAD(head);
>> +
>> + pci_add_flags(PCI_REASSIGN_ALL_RSRC);
>> + if (hw->preinit)
>> + hw->preinit();
>> + pcibios_init_hw(parent, hw, &head);
>> + if (hw->postinit)
>> + hw->postinit();
>> +
>> + pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
>> +
>> + list_for_each_entry(sys, &head, node) {
>> + struct pci_bus *bus = sys->bus;
>> +
>> + if (!pci_has_flag(PCI_PROBE_ONLY)) {
>> + /*
>> + * Size the bridge windows.
>> + */
>> + pci_bus_size_bridges(bus);
>> +
>> + /*
>> + * Assign resources.
>> + */
>> + pci_bus_assign_resources(bus);
>> + }
>> +
>> + /*
>> + * Tell drivers about devices found.
>> + */
>> + pci_bus_add_devices(bus);
>> + }
>> +}
>
> Appears unused.
>
>> +/*
>> + * We don't have to worry about legacy ISA devices, so nothing to do here
>> + */
>> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
>> + resource_size_t size, resource_size_t align)
>> +{
>> + return res->start;
>> +}
>> +
>> +/**
>> + * pcibios_enable_device - Enable I/O and memory.
>> + * @dev: PCI device to be enabled
>> + */
>> +int pcibios_enable_device(struct pci_dev *pci_dev, int mask)
>> +{
>> + u16 cmd, old_cmd;
>> + int idx;
>> + struct resource *r;
>> +
>> + pci_read_config_word(pci_dev, PCI_COMMAND, &cmd);
>> + old_cmd = cmd;
>> + for (idx = 0; idx < 6; idx++) {
>> + /* Only set up the requested stuff */
>> + if (!(mask & (1 << idx)))
>> + continue;
>> +
>> + r = pci_dev->resource + idx;
>> + if (!r->start && r->end) {
>> + dev_err(&pci_dev->dev, "PCI: Device %s not available\n",
>> + pci_name(pci_dev));
>> + return -EINVAL;
>> + }
>> + if (r->flags & IORESOURCE_IO)
>> + cmd |= PCI_COMMAND_IO;
>> + if (r->flags & IORESOURCE_MEM)
>> + cmd |= PCI_COMMAND_MEMORY;
>> + }
>> +
>> + /*
>> + * Bridges (eg, cardbus bridges) need to be fully enabled
>> + */
>> + if ((pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
>> + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
>> +
>> + if (cmd != old_cmd) {
>> + pr_info("PCI: enabling device %s (%04x -> %04x)\n",
>> + pci_name(pci_dev), old_cmd, cmd);
>> + pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
>> + }
>> + return 0;
>> +}
>
> There's a default (weak) version of pcibios_enable_device(). You
> should omit this definition and use the default unless your arch
> requires something special.
>
>> +
>> +/*
>> + * If the bus contains any of these devices, then we must not turn on
>> + * parity checking of any kind. Currently this is CyberPro 20x0 only.
>> + */
>> +static inline int pdev_bad_for_parity(struct pci_dev *dev)
>> +{
>> + return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
>> + (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
>> + dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
>> + (dev->vendor == PCI_VENDOR_ID_ITE &&
>> + dev->device == PCI_DEVICE_ID_ITE_8152));
>> +
>> +}
>> +
>> +/*
>> + * pcibios_fixup_bus - Called after each bus is probed,
>> + * but before its children are examined.
>> + */
>> +void pcibios_fixup_bus(struct pci_bus *bus)
>> +{
>> + struct pci_dev *dev;
>> + u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY
>> + | PCI_COMMAND_FAST_BACK;
>> +
>> + /*
>> + * Walk the devices on this bus, working out what we can
>> + * and can't support.
>> + */
>> + list_for_each_entry(dev, &bus->devices, bus_list) {
>> + u16 status;
>> +
>> + pci_read_config_word(dev, PCI_STATUS, &status);
>> +
>> + /*
>> + * If any device on this bus does not support fast back
>> + * to back transfers, then the bus as a whole is not able
>> + * to support them. Having fast back to back transfers
>> + * on saves us one PCI cycle per transaction.
>> + */
>> + if (!(status & PCI_STATUS_FAST_BACK))
>> + features &= ~PCI_COMMAND_FAST_BACK;
>> +
>> + if (pdev_bad_for_parity(dev))
>> + features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
>> +
>> + switch (dev->class >> 8) {
>> + case PCI_CLASS_BRIDGE_PCI:
>> + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
>> + status |= PCI_BRIDGE_CTL_PARITY
>> + |PCI_BRIDGE_CTL_MASTER_ABORT;
>> + status &= ~(PCI_BRIDGE_CTL_BUS_RESET
>> + |PCI_BRIDGE_CTL_FAST_BACK);
>> + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
>> + break;
>> +
>> + case PCI_CLASS_BRIDGE_CARDBUS:
>> + pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
>> + &status);
>> + status |= PCI_CB_BRIDGE_CTL_PARITY
>> + |PCI_CB_BRIDGE_CTL_MASTER_ABORT;
>> + pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
>> + status);
>> + break;
>> + }
>> + }
>> +
>> + /*
>> + * Now walk the devices again, this time setting them up.
>> + */
>> + list_for_each_entry(dev, &bus->devices, bus_list) {
>> + u16 cmd;
>> +
>> + pci_read_config_word(dev, PCI_COMMAND, &cmd);
>> + cmd |= features;
>> + pci_write_config_word(dev, PCI_COMMAND, cmd);
>> +
>> + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
>> + L1_CACHE_BYTES >> 2);
>> + }
>> +
>> + /*
>> + * Propagate the flags to the PCI bridge.
>> + */
>> + if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
>> + if (features & PCI_COMMAND_FAST_BACK)
>> + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
>> + if (features & PCI_COMMAND_PARITY)
>> + bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
>> + }
>> +
>> + /*
>> + * Report what we did for this bus
>> + */
>> + pr_info("PCI: bus%d: Fast back to back transfers %sabled\n",
>> + bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
>> +}
>> +EXPORT_SYMBOL(pcibios_fixup_bus);
>
> This pcibios_fixup_bus() implementation has been blindly copied all
> over the place, but I don't think it's relevant for most arches. I
> think you could probably make it an empty function as on arm64.
>
>> diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
>> index 739e65f..fe807b0 100644
>> --- a/arch/arc/mm/ioremap.c
>> +++ b/arch/arc/mm/ioremap.c
>> @@ -13,6 +13,7 @@
>> #include <linux/mm.h>
>> #include <linux/slab.h>
>> #include <linux/cache.h>
>> +#include <linux/sizes.h>
>>
>> void __iomem *ioremap(unsigned long paddr, unsigned long size)
>> {
>> @@ -80,7 +81,6 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
>> }
>> EXPORT_SYMBOL(ioremap_prot);
>>
>> -
>> void iounmap(const void __iomem *addr)
>> {
>> if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE)
>> @@ -89,3 +89,11 @@ void iounmap(const void __iomem *addr)
>> vfree((void *)(PAGE_MASK & (unsigned long __force)addr));
>> }
>> EXPORT_SYMBOL(iounmap);
>> +
>> +#ifdef CONFIG_PCI
>> +int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
>> +{
>> + return ioremap_nocache(phys_addr + offset, SZ_64K);
>> +}
>> +EXPORT_SYMBOL_GPL(pci_ioremap_io);
>> +#endif
>> diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig
>> index d475f9d..426ac4b 100644
>> --- a/arch/arc/plat-axs10x/Kconfig
>> +++ b/arch/arc/plat-axs10x/Kconfig
>> @@ -11,6 +11,7 @@ menuconfig ARC_PLAT_AXS10X
>> select DW_APB_ICTL
>> select GPIO_DWAPB
>> select OF_GPIO
>> + select MIGHT_HAVE_PCI
>> select GENERIC_IRQ_CHIP
>> select ARCH_REQUIRE_GPIOLIB
>> help
>> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
>> index be3f631..2154092 100644
>> --- a/drivers/pci/Makefile
>> +++ b/drivers/pci/Makefile
>> @@ -32,6 +32,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
>> # Some architectures use the generic PCI setup functions
>> #
>> obj-$(CONFIG_ALPHA) += setup-irq.o
>> +obj-$(CONFIG_ARC) += setup-irq.o
>> obj-$(CONFIG_ARM) += setup-irq.o
>> obj-$(CONFIG_ARM64) += setup-irq.o
>> obj-$(CONFIG_UNICORE32) += setup-irq.o
>> --
>> 1.8.1.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo@...r.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists