* [PATCH 04/12][v3] pci: fsl: add early PCI indirect access support
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
The driver needs to read/write PCI configuration very early, at
that time architecture-specific PCI controller structure and
PCI bus have not been created. The patch provides an interface
fsl_arch_fake_pci_bus which should be implemented in
architecture-specific PCI driver to fake a PCI controller structure
and PCI bus. Using the fake PCI controller and PCI bus, the patch
provides the early indirect read/write functions.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
drivers/pci/host/pci-fsl-common.c | 26 ++++++++++++++++++++++++++
include/linux/fsl/pci-common.h | 7 +++++++
2 files changed, 33 insertions(+)
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index 8bc9a64..505a6a1 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -204,6 +204,32 @@ static struct pci_ops fsl_indirect_pci_ops = {
.write = fsl_indirect_write_config,
};
+#define EARLY_FSL_PCI_OP(rw, size, type) \
+int early_fsl_##rw##_config_##size(struct fsl_pci *pci, int bus, \
+ int devfn, int offset, type value) \
+{ \
+ return pci_bus_##rw##_config_##size(fsl_arch_fake_pci_bus(pci, bus),\
+ devfn, offset, value); \
+}
+
+EARLY_FSL_PCI_OP(read, byte, u8 *)
+EARLY_FSL_PCI_OP(read, word, u16 *)
+EARLY_FSL_PCI_OP(read, dword, u32 *)
+EARLY_FSL_PCI_OP(write, byte, u8)
+EARLY_FSL_PCI_OP(write, word, u16)
+EARLY_FSL_PCI_OP(write, dword, u32)
+
+static int early_fsl_find_capability(struct fsl_pci *pci,
+ int busnr, int devfn, int cap)
+{
+ struct pci_bus *bus = fsl_arch_fake_pci_bus(pci, busnr);
+
+ if (!bus)
+ return 0;
+
+ return pci_bus_find_capability(bus, devfn, cap);
+}
+
static int setup_one_atmu(struct ccsr_pci __iomem *pci,
unsigned int index, const struct resource *res,
resource_size_t offset)
diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h
index 7df4355..a3aca29 100644
--- a/include/linux/fsl/pci-common.h
+++ b/include/linux/fsl/pci-common.h
@@ -149,5 +149,12 @@ bool fsl_pci_check_link(struct fsl_pci *pci);
/* To avoid touching specified devices */
int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn);
+/*
+ * To fake a PCI bus
+ * it is called by early_fsl_*(), at that time the architecture-dependent
+ * pci controller and pci bus have not been created.
+ */
+extern struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr);
+
#endif /* __PCI_COMMON_H */
#endif /* __KERNEL__ */
--
1.8.1.2
^ permalink raw reply related
* [PATCH 03/12][v3] pci: fsl: add PCI indirect access support
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
The patch adds PCI indirect read/write functions. The main code
is ported from arch/powerpc/sysdev/indirect_pci.c. We use general
IO API iowrite32be/ioread32be instead of out_be32/in_be32, and
use structure fsl_Pci instead of PowerPC's pci_controller.
The patch also provides fsl_pcie_check_link() to check PCI link.
The weak function fsl_arch_pci_exclude_device() is provided to
call ppc_md.pci_exclude_device() for PowerPC architecture.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
drivers/pci/host/pci-fsl-common.c | 169 ++++++++++++++++++++++++++++++++------
include/linux/fsl/pci-common.h | 6 ++
2 files changed, 151 insertions(+), 24 deletions(-)
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index 69d338b..8bc9a64 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -35,52 +35,173 @@
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
-static int fsl_pcie_check_link(struct pci_controller *hose)
+/* Indirect type */
+#define INDIRECT_TYPE_EXT_REG 0x00000002
+#define INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x00000004
+#define INDIRECT_TYPE_NO_PCIE_LINK 0x00000008
+#define INDIRECT_TYPE_BIG_ENDIAN 0x00000010
+#define INDIRECT_TYPE_FSL_CFG_REG_LINK 0x00000040
+
+int __weak fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int fsl_pci_read_config(struct fsl_pci *pci, int bus, int devfn,
+ int offset, int len, u32 *val)
+{
+ u32 bus_no, reg, data;
+
+ if (pci->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
+ if (bus != pci->first_busno)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (devfn != 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ if (fsl_arch_pci_exclude_device(pci, bus, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ bus_no = (bus == pci->first_busno) ? pci->self_busno : bus;
+
+ if (pci->indirect_type & INDIRECT_TYPE_EXT_REG)
+ reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+ else
+ reg = offset & 0xfc;
+
+ if (pci->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
+ iowrite32be(0x80000000 | (bus_no << 16) | (devfn << 8) | reg,
+ &pci->regs->config_addr);
+ else
+ iowrite32(0x80000000 | (bus_no << 16) | (devfn << 8) | reg,
+ &pci->regs->config_addr);
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ data = ioread32(&pci->regs->config_data);
+ switch (len) {
+ case 1:
+ *val = (data >> (8 * (offset & 3))) & 0xff;
+ break;
+ case 2:
+ *val = (data >> (8 * (offset & 3))) & 0xffff;
+ break;
+ default:
+ *val = data;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int fsl_pci_write_config(struct fsl_pci *pci, int bus, int devfn,
+ int offset, int len, u32 val)
+{
+ void __iomem *cfg_data;
+ u32 bus_no, reg;
+
+ if (pci->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
+ if (bus != pci->first_busno)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (devfn != 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ if (fsl_arch_pci_exclude_device(pci, bus, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ bus_no = (bus == pci->first_busno) ?
+ pci->self_busno : bus;
+
+ if (pci->indirect_type & INDIRECT_TYPE_EXT_REG)
+ reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
+ else
+ reg = offset & 0xfc;
+
+ if (pci->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
+ iowrite32be(0x80000000 | (bus_no << 16) | (devfn << 8) | reg,
+ &pci->regs->config_addr);
+ else
+ iowrite32(0x80000000 | (bus_no << 16) | (devfn << 8) | reg,
+ &pci->regs->config_addr);
+
+ /* suppress setting of PCI_PRIMARY_BUS */
+ if (pci->indirect_type & INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
+ if ((offset == PCI_PRIMARY_BUS) &&
+ (bus == pci->first_busno))
+ val &= 0xffffff00;
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = ((void *) &(pci->regs->config_data)) + (offset & 3);
+ switch (len) {
+ case 1:
+ iowrite8(val, cfg_data);
+ break;
+ case 2:
+ iowrite16(val, cfg_data);
+ break;
+ default:
+ iowrite32(val, cfg_data);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+bool fsl_pci_check_link(struct fsl_pci *pci)
{
u32 val = 0;
- if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
- if (hose->ops->read == fsl_indirect_read_config) {
- struct pci_bus bus;
- bus.number = hose->first_busno;
- bus.sysdata = hose;
- bus.ops = hose->ops;
- indirect_read_config(&bus, 0, PCIE_LTSSM, 4, &val);
- } else
- early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+ if (pci->indirect_type & INDIRECT_TYPE_FSL_CFG_REG_LINK) {
+ fsl_pci_read_config(pci, 0, 0, PCIE_LTSSM, 4, &val);
if (val < PCIE_LTSSM_L0)
- return 1;
+ return false;
} else {
- struct ccsr_pci __iomem *pci = hose->private_data;
/* for PCIe IP rev 3.0 or greater use CSR0 for link state */
- val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK)
+ val = (ioread32be(&pci->regs->pex_csr0) & PEX_CSR0_LTSSM_MASK)
>> PEX_CSR0_LTSSM_SHIFT;
if (val != PEX_CSR0_LTSSM_L0)
- return 1;
+ return false;
}
- return 0;
+ return true;
}
static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
{
- struct pci_controller *hose = pci_bus_to_host(bus);
+ struct fsl_pci *pci = fsl_arch_sys_to_pci(bus->sysdata);
+
+ if (!pci)
+ return PCIBIOS_DEVICE_NOT_FOUND;
- if (fsl_pcie_check_link(hose))
- hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+ if (fsl_pci_check_link(pci))
+ pci->indirect_type &= ~INDIRECT_TYPE_NO_PCIE_LINK;
else
- hose->indirect_type &= ~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+ pci->indirect_type |= INDIRECT_TYPE_NO_PCIE_LINK;
- return indirect_read_config(bus, devfn, offset, len, val);
+ return fsl_pci_read_config(pci, bus->number, devfn, offset, len, val);
}
-#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
-
-static struct pci_ops fsl_indirect_pcie_ops =
+static int fsl_indirect_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
{
+ struct fsl_pci *pci = fsl_arch_sys_to_pci(bus->sysdata);
+
+ if (!pci)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return fsl_pci_write_config(pci, bus->number, devfn,
+ offset, len, val);
+}
+
+static struct pci_ops fsl_indirect_pci_ops = {
.read = fsl_indirect_read_config,
- .write = indirect_write_config,
+ .write = fsl_indirect_write_config,
};
static int setup_one_atmu(struct ccsr_pci __iomem *pci,
diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h
index e56a040..7df4355 100644
--- a/include/linux/fsl/pci-common.h
+++ b/include/linux/fsl/pci-common.h
@@ -143,5 +143,11 @@ struct fsl_pci {
*/
extern struct fsl_pci *fsl_arch_sys_to_pci(void *sys);
+/* Return link status true -> link, false -> no link */
+bool fsl_pci_check_link(struct fsl_pci *pci);
+
+/* To avoid touching specified devices */
+int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn);
+
#endif /* __PCI_COMMON_H */
#endif /* __KERNEL__ */
--
1.8.1.2
^ permalink raw reply related
* [PATCH 05/12][v3] pci: fsl: port PCI ATMU related code
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
The patch ports PCI ATMU related code, just uses general IO API
iowrite32be/ioread32be instead of out_be32/in_be32, uses structure
fsl_pci instead of PowerPC's pci_controller and uses dev_*()
instead of pr_*() to output the information.
The patch also provides the weak function
fsl_arch_pci64_dma_offset(), the architecture-specific driver may
return different offset.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
drivers/pci/host/pci-fsl-common.c | 191 ++++++++++++++++++++------------------
include/linux/fsl/pci-common.h | 3 +
2 files changed, 104 insertions(+), 90 deletions(-)
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index 505a6a1..f15b605 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -42,6 +42,11 @@
#define INDIRECT_TYPE_BIG_ENDIAN 0x00000010
#define INDIRECT_TYPE_FSL_CFG_REG_LINK 0x00000040
+u64 __weak fsl_arch_pci64_dma_offset(void)
+{
+ return 0;
+}
+
int __weak fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn)
{
return PCIBIOS_SUCCESSFUL;
@@ -231,8 +236,8 @@ static int early_fsl_find_capability(struct fsl_pci *pci,
}
static int setup_one_atmu(struct ccsr_pci __iomem *pci,
- unsigned int index, const struct resource *res,
- resource_size_t offset)
+ unsigned int index, const struct resource *res,
+ resource_size_t offset)
{
resource_size_t pci_addr = res->start - offset;
resource_size_t phys_addr = res->start;
@@ -253,10 +258,10 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
if (index + i >= 5)
return -1;
- out_be32(&pci->pow[index + i].potar, pci_addr >> 12);
- out_be32(&pci->pow[index + i].potear, (u64)pci_addr >> 44);
- out_be32(&pci->pow[index + i].powbar, phys_addr >> 12);
- out_be32(&pci->pow[index + i].powar, flags | (bits - 1));
+ iowrite32be(pci_addr >> 12, &pci->pow[index + i].potar);
+ iowrite32be((u64)pci_addr >> 44, &pci->pow[index + i].potear);
+ iowrite32be(phys_addr >> 12, &pci->pow[index + i].powbar);
+ iowrite32be(flags | (bits - 1), &pci->pow[index + i].powar);
pci_addr += (resource_size_t)1U << bits;
phys_addr += (resource_size_t)1U << bits;
@@ -267,21 +272,19 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
}
/* atmu setup for fsl pci/pcie controller */
-static void setup_pci_atmu(struct pci_controller *hose)
+static void setup_pci_atmu(struct fsl_pci *pci)
{
- struct ccsr_pci __iomem *pci = hose->private_data;
int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
u64 mem, sz, paddr_hi = 0;
u64 offset = 0, paddr_lo = ULLONG_MAX;
u32 pcicsrbar = 0, pcicsrbar_sz;
u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
- const char *name = hose->dn->full_name;
const u64 *reg;
int len;
- if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
- if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
+ if (pci->is_pcie) {
+ if (in_be32(&pci->regs->block_rev1) >= PCIE_IP_REV_2_2) {
win_idx = 2;
start_idx = 0;
end_idx = 3;
@@ -289,47 +292,54 @@ static void setup_pci_atmu(struct pci_controller *hose)
}
/* Disable all windows (except powar0 since it's ignored) */
- for(i = 1; i < 5; i++)
- out_be32(&pci->pow[i].powar, 0);
+ for (i = 1; i < 5; i++)
+ iowrite32be(0, &pci->regs->pow[i].powar);
for (i = start_idx; i < end_idx; i++)
- out_be32(&pci->piw[i].piwar, 0);
+ iowrite32be(0, &pci->regs->piw[i].piwar);
/* Setup outbound MEM window */
- for(i = 0, j = 1; i < 3; i++) {
- if (!(hose->mem_resources[i].flags & IORESOURCE_MEM))
+ for (i = 0, j = 1; i < 3; i++) {
+ if (!(pci->mem_resources[i].flags & IORESOURCE_MEM))
continue;
- paddr_lo = min(paddr_lo, (u64)hose->mem_resources[i].start);
- paddr_hi = max(paddr_hi, (u64)hose->mem_resources[i].end);
+ paddr_lo = min_t(u64, paddr_lo, pci->mem_resources[i].start);
+ paddr_hi = max_t(u64, paddr_hi, pci->mem_resources[i].end);
/* We assume all memory resources have the same offset */
- offset = hose->mem_offset[i];
- n = setup_one_atmu(pci, j, &hose->mem_resources[i], offset);
+ offset = pci->mem_offset[i];
+ n = setup_one_atmu(pci->regs, j, &pci->mem_resources[i],
+ offset);
if (n < 0 || j >= 5) {
- pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i);
- hose->mem_resources[i].flags |= IORESOURCE_DISABLED;
+ dev_err(pci->dev,
+ "Ran out of outbound PCI ATMUs for resource %d!\n",
+ i);
+ pci->mem_resources[i].flags |= IORESOURCE_DISABLED;
} else
j += n;
}
/* Setup outbound IO window */
- if (hose->io_resource.flags & IORESOURCE_IO) {
- if (j >= 5) {
- pr_err("Ran out of outbound PCI ATMUs for IO resource\n");
- } else {
- pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, "
- "phy base 0x%016llx.\n",
- (u64)hose->io_resource.start,
- (u64)resource_size(&hose->io_resource),
- (u64)hose->io_base_phys);
- out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12));
- out_be32(&pci->pow[j].potear, 0);
- out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
+ if (pci->io_resource.flags & IORESOURCE_IO) {
+ if (j >= 5)
+ dev_err(pci->dev,
+ "Ran out of outbound PCI ATMUs for IO resource\n");
+ else {
+ dev_dbg(pci->dev,
+ "PCI IO resource start 0x%016llx,"
+ "size 0x%016llx, phy base 0x%016llx.\n",
+ (u64)pci->io_resource.start,
+ (u64)resource_size(&pci->io_resource),
+ (u64)pci->io_base_phys);
+ iowrite32be(pci->io_resource.start >> 12,
+ &pci->regs->pow[j].potar);
+ iowrite32be(0, &pci->regs->pow[j].potear);
+ iowrite32be(pci->io_base_phys >> 12,
+ &pci->regs->pow[j].powbar);
/* Enable, IO R/W */
- out_be32(&pci->pow[j].powar, 0x80088000
- | (ilog2(hose->io_resource.end
- - hose->io_resource.start + 1) - 1));
+ iowrite32be(0x80088000 |
+ (ilog2(resource_size(&pci->io_resource)) - 1),
+ &pci->regs->pow[j].powar);
}
}
@@ -338,18 +348,20 @@ static void setup_pci_atmu(struct pci_controller *hose)
paddr_lo -= offset;
if (paddr_hi == paddr_lo) {
- pr_err("%s: No outbound window space\n", name);
+ dev_err(pci->dev, "No outbound window space\n");
return;
}
if (paddr_lo == 0) {
- pr_err("%s: No space for inbound window\n", name);
+ dev_err(pci->dev, "No space for inbound window\n");
return;
}
/* setup PCSRBAR/PEXCSRBAR */
- early_write_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, 0xffffffff);
- early_read_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, &pcicsrbar_sz);
+ early_fsl_write_config_dword(pci, 0, 0, PCI_BASE_ADDRESS_0,
+ 0xffffffff);
+ early_fsl_read_config_dword(pci, 0, 0, PCI_BASE_ADDRESS_0,
+ &pcicsrbar_sz);
pcicsrbar_sz = ~pcicsrbar_sz + 1;
if (paddr_hi < (0x100000000ull - pcicsrbar_sz) ||
@@ -357,11 +369,12 @@ static void setup_pci_atmu(struct pci_controller *hose)
pcicsrbar = 0x100000000ull - pcicsrbar_sz;
else
pcicsrbar = (paddr_lo - pcicsrbar_sz) & -pcicsrbar_sz;
- early_write_config_dword(hose, 0, 0, PCI_BASE_ADDRESS_0, pcicsrbar);
+ early_fsl_write_config_dword(pci, 0, 0, PCI_BASE_ADDRESS_0,
+ pcicsrbar);
- paddr_lo = min(paddr_lo, (u64)pcicsrbar);
+ paddr_lo = min_t(u64, paddr_lo, pcicsrbar);
- pr_info("%s: PCICSRBAR @ 0x%x\n", name, pcicsrbar);
+ dev_info(pci->dev, "PCICSRBAR @ 0x%x\n", pcicsrbar);
/* Setup inbound mem window */
mem = memblock_end_of_DRAM();
@@ -378,17 +391,19 @@ static void setup_pci_atmu(struct pci_controller *hose)
* can avoid allocating a new ATMU by extending the DDR ATMU by one
* page.
*/
- reg = of_get_property(hose->dn, "msi-address-64", &len);
+ reg = of_get_property(pci->dn, "msi-address-64", &len);
if (reg && (len == sizeof(u64))) {
u64 address = be64_to_cpup(reg);
if ((address >= mem) && (address < (mem + PAGE_SIZE))) {
- pr_info("%s: extending DDR ATMU to cover MSIIR", name);
+ dev_info(pci->dev,
+ "extending DDR ATMU to cover MSIIR\n");
mem += PAGE_SIZE;
} else {
/* TODO: Create a new ATMU for MSIIR */
- pr_warn("%s: msi-address-64 address of %llx is "
- "unsupported\n", name, address);
+ dev_warn(pci->dev,
+ "msi-address-64 address of %llx is "
+ "unsupported\n", address);
}
}
@@ -396,25 +411,26 @@ static void setup_pci_atmu(struct pci_controller *hose)
mem_log = ilog2(sz);
/* PCIe can overmap inbound & outbound since RX & TX are separated */
- if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
+ if (pci->is_pcie) {
/* Size window to exact size if power-of-two or one size up */
if ((1ull << mem_log) != mem) {
mem_log++;
if ((1ull << mem_log) > mem)
- pr_info("%s: Setting PCI inbound window "
- "greater than memory size\n", name);
+ dev_info(pci->dev,
+ "Setting PCI inbound window "
+ "greater than memory size\n");
}
piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
/* Setup inbound memory window */
- out_be32(&pci->piw[win_idx].pitar, 0x00000000);
- out_be32(&pci->piw[win_idx].piwbar, 0x00000000);
- out_be32(&pci->piw[win_idx].piwar, piwar);
+ iowrite32be(0, &pci->regs->piw[win_idx].pitar);
+ iowrite32be(0, &pci->regs->piw[win_idx].piwbar);
+ iowrite32be(piwar, &pci->regs->piw[win_idx].piwar);
win_idx--;
- hose->dma_window_base_cur = 0x00000000;
- hose->dma_window_size = (resource_size_t)sz;
+ pci->dma_window_base_cur = 0x00000000;
+ pci->dma_window_size = (resource_size_t)sz;
/*
* if we have >4G of memory setup second PCI inbound window to
@@ -431,28 +447,22 @@ static void setup_pci_atmu(struct pci_controller *hose)
piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
/* Setup inbound memory window */
- out_be32(&pci->piw[win_idx].pitar, 0x00000000);
- out_be32(&pci->piw[win_idx].piwbear,
- pci64_dma_offset >> 44);
- out_be32(&pci->piw[win_idx].piwbar,
- pci64_dma_offset >> 12);
- out_be32(&pci->piw[win_idx].piwar, piwar);
-
- /*
- * install our own dma_set_mask handler to fixup dma_ops
- * and dma_offset
- */
- ppc_md.dma_set_mask = fsl_pci_dma_set_mask;
-
- pr_info("%s: Setup 64-bit PCI DMA window\n", name);
+ iowrite32be(0, &pci->regs->piw[win_idx].pitar);
+ iowrite32be(fsl_arch_pci64_dma_offset() >> 44,
+ &pci->regs->piw[win_idx].piwbear);
+ iowrite32be(fsl_arch_pci64_dma_offset() >> 12,
+ &pci->regs->piw[win_idx].piwbar);
+ iowrite32be(piwar,
+ &pci->regs->piw[win_idx].piwar);
}
} else {
u64 paddr = 0;
/* Setup inbound memory window */
- out_be32(&pci->piw[win_idx].pitar, paddr >> 12);
- out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
- out_be32(&pci->piw[win_idx].piwar, (piwar | (mem_log - 1)));
+ iowrite32be(paddr >> 12, &pci->regs->piw[win_idx].pitar);
+ iowrite32be(paddr >> 12, &pci->regs->piw[win_idx].piwbar);
+ iowrite32be((piwar | (mem_log - 1)),
+ &pci->regs->piw[win_idx].piwar);
win_idx--;
paddr += 1ull << mem_log;
@@ -462,35 +472,36 @@ static void setup_pci_atmu(struct pci_controller *hose)
mem_log = ilog2(sz);
piwar |= (mem_log - 1);
- out_be32(&pci->piw[win_idx].pitar, paddr >> 12);
- out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
- out_be32(&pci->piw[win_idx].piwar, piwar);
+ iowrite32be(paddr >> 12,
+ &pci->regs->piw[win_idx].pitar);
+ iowrite32be(paddr >> 12,
+ &pci->regs->piw[win_idx].piwbar);
+ iowrite32be(piwar,
+ &pci->regs->piw[win_idx].piwar);
win_idx--;
paddr += 1ull << mem_log;
}
- hose->dma_window_base_cur = 0x00000000;
- hose->dma_window_size = (resource_size_t)paddr;
+ pci->dma_window_base_cur = 0x00000000;
+ pci->dma_window_size = (resource_size_t)paddr;
}
- if (hose->dma_window_size < mem) {
-#ifdef CONFIG_SWIOTLB
- ppc_swiotlb_enable = 1;
-#else
- pr_err("%s: ERROR: Memory size exceeds PCI ATMU ability to "
- "map - enable CONFIG_SWIOTLB to avoid dma errors.\n",
- name);
+ if (pci->dma_window_size < mem) {
+#ifndef CONFIG_SWIOTLB
+ dev_err(pci->dev,
+ "Memory size exceeds PCI ATMU ability to "
+ "map - enable CONFIG_SWIOTLB to avoid dma errors.\n");
#endif
/* adjusting outbound windows could reclaim space in mem map */
if (paddr_hi < 0xffffffffull)
- pr_warning("%s: WARNING: Outbound window cfg leaves "
+ dev_warn(pci->dev,
+ "Outbound window cfg leaves "
"gaps in memory map. Adjusting the memory map "
- "could reduce unnecessary bounce buffering.\n",
- name);
+ "could reduce unnecessary bounce buffering.\n");
- pr_info("%s: DMA window size is 0x%llx\n", name,
- (u64)hose->dma_window_size);
+ dev_info(pci->dev, "DMA window size is 0x%llx\n",
+ (u64)pci->dma_window_size);
}
}
diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h
index a3aca29..490ee53 100644
--- a/include/linux/fsl/pci-common.h
+++ b/include/linux/fsl/pci-common.h
@@ -156,5 +156,8 @@ int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn);
*/
extern struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr);
+/* Return PCI64 DMA offset */
+u64 fsl_arch_pci64_dma_offset(void);
+
#endif /* __PCI_COMMON_H */
#endif /* __KERNEL__ */
--
1.8.1.2
^ permalink raw reply related
* [PATCH 07/12][v3] pci: fsl: port PCI platform driver
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
1. The patch ports FSL PCI platform driver. probe function
initialize fsl_pci and register it to architecture PCI system,
remove function removes fsl_pci from architecture PCI system.
fsl_arch_pci_sys_register() and fsl_arch_pci_sys_remove() should
be implemented in architecture-specific driver to provide
register/remove functionality.
2. Remove architecture-specific header and unnecessary header.
3. Change Kconfig and Makefile to support FSL PCI common driver
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
arch/powerpc/Kconfig | 1 +
drivers/pci/host/Kconfig | 10 ++++++++
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pci-fsl-common.c | 53 +++++++++++++++++++++++++--------------
include/linux/fsl/pci-common.h | 6 +++++
5 files changed, 52 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 38f3b7e..7447d97d 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -690,6 +690,7 @@ config FSL_SOC
config FSL_PCI
bool
+ select PCI_FSL_COMMON if FSL_SOC_BOOKE || PPC_86xx
select PPC_INDIRECT_PCI
select PCI_QUIRKS
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 3d95048..48242b33 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -19,4 +19,14 @@ config PCI_TEGRA
bool "NVIDIA Tegra PCIe controller"
depends on ARCH_TEGRA
+config PCI_FSL_COMMON
+ bool "Common driver for Freescale PCI/PCIe controller"
+ depends on FSL_SOC_BOOKE || PPC_86xx
+ help
+ This driver provides common support for PCI/PCIE controller
+ on Freescale embedded processors 85xx/86xx/QorIQ/Layerscape.
+ Additional drivers must be enabled in order to provide some
+ architecture-dependent functions and register the controller
+ to PCI subsystem.
+
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index c9a997b..7c338a7 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
+obj-$(CONFIG_PCI_FSL_COMMON) += pci-fsl-common.o
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index e09a0ec..c7bc472 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -16,26 +16,12 @@
*/
#include <linux/kernel.h>
#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
#include <linux/init.h>
-#include <linux/bootmem.h>
#include <linux/memblock.h>
#include <linux/log2.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc-pci.h>
-#include <asm/machdep.h>
-#include <asm/disassemble.h>
-#include <asm/ppc-opcode.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
+#include <linux/fsl/pci-common.h>
/* Indirect type */
#define INDIRECT_TYPE_EXT_REG 0x00000002
@@ -672,12 +658,40 @@ static const struct of_device_id pci_ids[] = {
static int fsl_pci_probe(struct platform_device *pdev)
{
int ret;
- struct device_node *node;
+ struct fsl_pci *pci;
+
+ if (!of_device_is_available(pdev->dev.of_node)) {
+ dev_dbg(&pdev->dev, "disabled\n");
+ return -ENODEV;
+ }
+
+ pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL);
+ if (!pci) {
+ dev_err(&pdev->dev, "no memory for fsl_pci\n");
+ return -ENOMEM;
+ }
+
+ ret = fsl_pci_setup(pdev, pci);
+ if (ret)
+ return ret;
+
+ ret = fsl_arch_pci_sys_register(pci);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register pcie to Arch\n");
+ return ret;
+ }
+
+ return 0;
+}
- node = pdev->dev.of_node;
- ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
+static int fsl_pci_remove(struct platform_device *pdev)
+{
+ struct fsl_pci *pci = platform_get_drvdata(pdev);
+
+ if (!pci)
+ return -ENODEV;
- mpc85xx_pci_err_probe(pdev);
+ fsl_arch_pci_sys_remove(pci);
return 0;
}
@@ -721,6 +735,7 @@ static struct platform_driver fsl_pci_driver = {
.of_match_table = pci_ids,
},
.probe = fsl_pci_probe,
+ .remove = fsl_pci_remove,
};
static int __init fsl_pci_init(void)
diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h
index 490ee53..bfb1f03 100644
--- a/include/linux/fsl/pci-common.h
+++ b/include/linux/fsl/pci-common.h
@@ -159,5 +159,11 @@ extern struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr);
/* Return PCI64 DMA offset */
u64 fsl_arch_pci64_dma_offset(void);
+/* Register PCI/PCIe controller to architecture system */
+extern int fsl_arch_pci_sys_register(struct fsl_pci *pci);
+
+/* Remove PCI/PCIe controller from architecture system */
+extern void fsl_arch_pci_sys_remove(struct fsl_pci *pci);
+
#endif /* __PCI_COMMON_H */
#endif /* __KERNEL__ */
--
1.8.1.2
^ permalink raw reply related
* [PATCH 09/12][v3] pci: fsl: update PCI PM driver
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
The patch updates PCI PM driver, uses fsl_pci instead of
pci_controller.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
drivers/pci/host/pci-fsl-common.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index c7bc472..729a5f4 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -699,19 +699,12 @@ static int fsl_pci_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int fsl_pci_resume(struct device *dev)
{
- struct pci_controller *hose;
- struct resource pci_rsrc;
+ struct fsl_pci *pci = dev_get_drvdata(dev);
- hose = pci_find_hose_for_OF_device(dev->of_node);
- if (!hose)
+ if (!pci)
return -ENODEV;
- if (of_address_to_resource(dev->of_node, 0, &pci_rsrc)) {
- dev_err(dev, "Get pci register base failed.");
- return -ENODEV;
- }
-
- setup_pci_atmu(hose);
+ setup_pci_atmu(pci);
return 0;
}
--
1.8.1.2
^ permalink raw reply related
* [PATCH 08/12][v3] pci: fsl: add PowerPC PCI driver
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
1. Implement fsl_arch_pci64_dma_offset() to return PowerPC PCI64
DMA offset
2. Implement fsl_arch_sys_to_pci() to convert pci_controller
to fsl_pci
3. Implement fsl_arch_fake_pci_bus() to fake pci_controller
and PCI bus.
4. Implement fsl_arch_pci_exclude_device() to call
ppc_md.pci_exclude_device()
5. Implement fsl_arch_pci_sys_register() to initialize pci_controller
according to fsl_pci, add register PCI controller to PowerPC PCI
subsystem.
6. Implement fsl_arch_pci_sys_remove() to remove PCI controller from
PowerPC PCI subsystem.
7. Add mpc83xx_pcie_check_link() because pci-fsl-common dose not
support mpc83xx.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
arch/powerpc/sysdev/fsl_pci.c | 142 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 135 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 26039e3..0a0c240 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -62,7 +62,11 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
#define MAX_PHYS_ADDR_BITS 40
-static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
+
+u64 fsl_arch_pci64_dma_offset(void)
+{
+ return 1ull << MAX_PHYS_ADDR_BITS;
+}
static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
{
@@ -77,17 +81,44 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
if ((dev->bus == &pci_bus_type) &&
dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
set_dma_ops(dev, &dma_direct_ops);
- set_dma_offset(dev, pci64_dma_offset);
+ set_dma_offset(dev, fsl_arch_pci64_dma_offset());
}
*dev->dma_mask = dma_mask;
return 0;
}
+struct fsl_pci *fsl_arch_sys_to_pci(void *sys)
+{
+ struct pci_controller *hose = sys;
+ struct fsl_pci *pci = hose->private_data;
+
+ /* Update the first bus number */
+ if (pci->first_busno != hose->first_busno)
+ pci->first_busno = hose->first_busno;
+
+ return pci;
+}
+
+struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr)
+{
+ static struct pci_bus bus;
+ static struct pci_controller hose;
+
+ bus.number = busnr;
+ bus.sysdata = &hose;
+ hose.private_data = pci;
+ bus.ops = pci->ops;
+
+ return &bus;
+}
+
void fsl_pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_controller *hose = pci_bus_to_host(bus);
- int i, is_pcie = 0, no_link;
+ bool is_pcie, no_link;
+ int i;
+ struct fsl_pci *pci = fsl_arch_sys_to_pci(hose);
/* The root complex bridge comes up with bogus resources,
* we copy the PHB ones in.
@@ -97,9 +128,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
* tricky.
*/
- if (fsl_pcie_bus_fixup)
- is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
- no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK);
+ is_pcie = pci->is_pcie;
+ no_link = !fsl_pci_check_link(pci);
if (bus->parent == hose->bus && (is_pcie || no_link)) {
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) {
@@ -121,6 +151,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
}
}
+int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn)
+{
+ struct pci_controller *hose = pci->sys;
+
+ if (!hose)
+ return PCIBIOS_SUCCESSFUL;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(hose, bus, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int fsl_arch_pci_sys_register(struct fsl_pci *pci)
+{
+ struct pci_controller *hose;
+
+ pci_add_flags(PCI_REASSIGN_ALL_BUS);
+ hose = pcibios_alloc_controller(pci->dn);
+ if (!hose)
+ return -ENOMEM;
+
+ /* set platform device as the parent */
+ hose->private_data = pci;
+ hose->parent = pci->dev;
+ hose->first_busno = pci->first_busno;
+ hose->last_busno = pci->last_busno;
+ hose->ops = pci->ops;
+
+#ifdef CONFIG_PPC32
+ /* On 32 bits, limit I/O space to 16MB */
+ if (pci->pci_io_size > 0x01000000)
+ pci->pci_io_size = 0x01000000;
+
+ /* 32 bits needs to map IOs here */
+ hose->io_base_virt = ioremap(pci->io_base_phys + pci->io_resource.start,
+ pci->pci_io_size);
+
+ /* Expect trouble if pci_addr is not 0 */
+ if (fsl_pci_primary == pci->dn)
+ isa_io_base = (unsigned long)hose->io_base_virt;
+#endif /* CONFIG_PPC32 */
+
+ hose->pci_io_size = pci->io_resource.start + pci->pci_io_size;
+ hose->io_base_phys = pci->io_base_phys;
+ hose->io_resource = pci->io_resource;
+
+ memcpy(hose->mem_offset, pci->mem_offset, sizeof(hose->mem_offset));
+ memcpy(hose->mem_resources, pci->mem_resources,
+ sizeof(hose->mem_resources));
+ hose->dma_window_base_cur = pci->dma_window_base_cur;
+ hose->dma_window_size = pci->dma_window_size;
+
+ pci->sys = hose;
+
+ /*
+ * Install our own dma_set_mask handler to fixup dma_ops
+ * and dma_offset when memory is more than dma window size
+ */
+ if (pci->is_pcie && memblock_end_of_DRAM() > hose->dma_window_size)
+ ppc_md.dma_set_mask = fsl_pci_dma_set_mask;
+
+#ifdef CONFIG_SWIOTLB
+ /*
+ * if we couldn't map all of DRAM via the dma windows
+ * we need SWIOTLB to handle buffers located outside of
+ * dma capable memory region
+ */
+ if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
+ hose->dma_window_size)
+ ppc_swiotlb_enable = 1;
+#endif
+
+ mpc85xx_pci_err_probe(to_platform_device(pci->dev));
+ return 0;
+}
+
+void fsl_arch_pci_sys_remove(struct fsl_pci *pci)
+{
+ struct pci_controller *hose = pci->sys;
+
+ if (!hose)
+ return;
+
+ pcibios_free_controller(hose);
+}
+
#endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
@@ -260,6 +378,16 @@ static struct pci_ops mpc83xx_pcie_ops = {
.write = mpc83xx_pcie_write_config,
};
+static int mpc83xx_pcie_check_link(struct pci_controller *hose)
+{
+ u32 val = 0;
+
+ early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+ if (val < PCIE_LTSSM_L0)
+ return 1;
+ return 0;
+}
+
static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
struct resource *reg)
{
@@ -294,7 +422,7 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
- if (fsl_pcie_check_link(hose))
+ if (mpc83xx_pcie_check_link(hose))
hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
return 0;
--
1.8.1.2
^ permalink raw reply related
* [PATCH 10/12][v3] pci: fsl: support function fsl_pci_assign_primary
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
Change pci_ids to fsl_pci_ids Freescale-specific name and change
static to extern modifier for using in fsl_pci_assign_primary().
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
arch/powerpc/sysdev/fsl_pci.c | 5 +++--
drivers/pci/host/pci-fsl-common.c | 4 ++--
include/linux/fsl/pci-common.h | 2 ++
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 0a0c240..40d2e1d 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -735,7 +735,8 @@ void fsl_pci_assign_primary(void)
of_node_put(np);
np = fsl_pci_primary;
- if (of_match_node(pci_ids, np) && of_device_is_available(np))
+ if (of_match_node(fsl_pci_ids, np) &&
+ of_device_is_available(np))
return;
}
@@ -744,7 +745,7 @@ void fsl_pci_assign_primary(void)
* designate one as primary. This can go away once
* various bugs with primary-less systems are fixed.
*/
- for_each_matching_node(np, pci_ids) {
+ for_each_matching_node(np, fsl_pci_ids) {
if (of_device_is_available(np)) {
fsl_pci_primary = np;
of_node_put(np);
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index 729a5f4..8b4f793 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -634,7 +634,7 @@ no_bridge:
return -ENODEV;
}
-static const struct of_device_id pci_ids[] = {
+const struct of_device_id fsl_pci_ids[] = {
{ .compatible = "fsl,mpc8540-pci", },
{ .compatible = "fsl,mpc8548-pcie", },
{ .compatible = "fsl,mpc8610-pci", },
@@ -725,7 +725,7 @@ static struct platform_driver fsl_pci_driver = {
.driver = {
.name = "fsl-pci",
.pm = PCI_PM_OPS,
- .of_match_table = pci_ids,
+ .of_match_table = fsl_pci_ids,
},
.probe = fsl_pci_probe,
.remove = fsl_pci_remove,
diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h
index bfb1f03..84b0801 100644
--- a/include/linux/fsl/pci-common.h
+++ b/include/linux/fsl/pci-common.h
@@ -136,6 +136,8 @@ struct fsl_pci {
void *sys;
};
+extern const struct of_device_id fsl_pci_ids[];
+
/*
* Convert architecture specific pci controller structure to fsl_pci
* PowerPC uses structure pci_controller and ARM uses structure pci_sys_data
--
1.8.1.2
^ permalink raw reply related
* [PATCH 06/12][v3] pci: fsl: port PCI controller setup code
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
PCI controller setup code will initialize structure fsl_pci
according to PCI dts node and initialize PCI command register
and ATMU. The patch uses general API of_pci_parse_bus_range
to parse PCI bus range, uses general of_address's API to parse
PCI IO/MEM ranges.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
drivers/pci/host/pci-fsl-common.c | 179 +++++++++++++++++++++-----------------
1 file changed, 97 insertions(+), 82 deletions(-)
diff --git a/drivers/pci/host/pci-fsl-common.c b/drivers/pci/host/pci-fsl-common.c
index f15b605..e09a0ec 100644
--- a/drivers/pci/host/pci-fsl-common.c
+++ b/drivers/pci/host/pci-fsl-common.c
@@ -24,6 +24,8 @@
#include <linux/log2.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -505,131 +507,144 @@ static void setup_pci_atmu(struct fsl_pci *pci)
}
}
-static void __init setup_pci_cmd(struct pci_controller *hose)
+static void __init setup_pci_cmd(struct fsl_pci *pci)
{
u16 cmd;
int cap_x;
- early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
+ early_fsl_read_config_word(pci, 0, 0, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
| PCI_COMMAND_IO;
- early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
+ early_fsl_write_config_word(pci, 0, 0, PCI_COMMAND, cmd);
- cap_x = early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX);
+ cap_x = early_fsl_find_capability(pci, 0, 0, PCI_CAP_ID_PCIX);
if (cap_x) {
int pci_x_cmd = cap_x + PCI_X_CMD;
cmd = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
| PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
- early_write_config_word(hose, 0, 0, pci_x_cmd, cmd);
- } else {
- early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
- }
+ early_fsl_write_config_word(pci, 0, 0, pci_x_cmd, cmd);
+ } else
+ early_fsl_write_config_byte(pci, 0, 0, PCI_LATENCY_TIMER,
+ 0x80);
}
-int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
+static int __init
+fsl_pci_setup(struct platform_device *pdev, struct fsl_pci *pci)
{
- int len;
- struct pci_controller *hose;
- struct resource rsrc;
- const int *bus_range;
+ struct resource *rsrc;
u8 hdr_type, progif;
- struct device_node *dev;
- struct ccsr_pci __iomem *pci;
-
- dev = pdev->dev.of_node;
+ struct device_node *dn;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
+ int mem = 0;
- if (!of_device_is_available(dev)) {
- pr_warning("%s: disabled\n", dev->full_name);
- return -ENODEV;
- }
+ dn = pdev->dev.of_node;
+ pci->dn = dn;
+ pci->dev = &pdev->dev;
- pr_debug("Adding PCI host bridge %s\n", dev->full_name);
+ dev_info(&pdev->dev, "Find controller %s\n", dn->full_name);
/* Fetch host bridge registers address */
- if (of_address_to_resource(dev, 0, &rsrc)) {
- printk(KERN_WARNING "Can't get pci register base!");
- return -ENOMEM;
+ rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!rsrc) {
+ dev_err(&pdev->dev, "Can't get pci register base!");
+ return -EINVAL;
}
+ dev_info(&pdev->dev, "REG 0x%016llx..0x%016llx\n",
+ (u64)rsrc->start, (u64)rsrc->end);
- /* Get bus range if any */
- bus_range = of_get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int))
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", dev->full_name);
-
- pci_add_flags(PCI_REASSIGN_ALL_BUS);
- hose = pcibios_alloc_controller(dev);
- if (!hose)
- return -ENOMEM;
+ /* Parse pci range resources from device tree */
+ if (of_pci_range_parser_init(&parser, dn)) {
+ dev_err(&pdev->dev, "missing ranges property\n");
+ return -EINVAL;
+ }
- /* set platform device as the parent */
- hose->parent = &pdev->dev;
- hose->first_busno = bus_range ? bus_range[0] : 0x0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
+ /* Get the I/O and memory ranges from device tree */
+ for_each_of_pci_range(&parser, &range) {
+ unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
+ if (restype == IORESOURCE_IO) {
+ of_pci_range_to_resource(&range, dn,
+ &pci->io_resource);
+ pci->io_resource.name = "I/O";
+ pci->io_resource.start = range.pci_addr;
+ pci->io_resource.end = range.pci_addr + range.size - 1;
+ pci->pci_io_size = range.size;
+ pci->io_base_phys = range.cpu_addr - range.pci_addr;
+ dev_info(&pdev->dev,
+ " IO 0x%016llx..0x%016llx -> 0x%016llx\n",
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1,
+ range.pci_addr);
+ }
+ if (restype == IORESOURCE_MEM) {
+ if (mem >= 3)
+ continue;
+ of_pci_range_to_resource(&range, dn,
+ &pci->mem_resources[mem]);
+ pci->mem_resources[mem].name = "MEM";
+ pci->mem_offset[mem] = range.cpu_addr - range.pci_addr;
+ dev_info(&pdev->dev,
+ "MEM 0x%016llx..0x%016llx -> 0x%016llx\n",
+ (u64)pci->mem_resources[mem].start,
+ (u64)pci->mem_resources[mem].end,
+ range.pci_addr);
+ }
+ }
- pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
- (u64)rsrc.start, (u64)resource_size(&rsrc));
+ /* Get bus range */
+ if (of_pci_parse_bus_range(dn, &pci->busn)) {
+ dev_err(&pdev->dev, "failed to parse bus-range property\n");
+ pci->first_busno = 0x0;
+ pci->last_busno = 0xff;
+ } else {
+ pci->first_busno = pci->busn.start;
+ pci->last_busno = pci->busn.end;
+ }
+ dev_info(&pdev->dev, "Firmware bus number %d->%d\n",
+ pci->first_busno, pci->last_busno);
- pci = hose->private_data = ioremap(rsrc.start, resource_size(&rsrc));
- if (!hose->private_data)
- goto no_bridge;
+ pci->regs = devm_ioremap_resource(&pdev->dev, rsrc);
+ if (IS_ERR(pci->regs))
+ return PTR_ERR(pci->regs);
- setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
- PPC_INDIRECT_TYPE_BIG_ENDIAN);
+ pci->ops = &fsl_indirect_pci_ops;
+ pci->indirect_type = INDIRECT_TYPE_BIG_ENDIAN;
- if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
- hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
+ if (in_be32(&pci->regs->block_rev1) < PCIE_IP_REV_3_0)
+ pci->indirect_type |= INDIRECT_TYPE_FSL_CFG_REG_LINK;
- if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
- /* use fsl_indirect_read_config for PCIe */
- hose->ops = &fsl_indirect_pcie_ops;
- /* For PCIE read HEADER_TYPE to identify controler mode */
- early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
- if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
+ pci->is_pcie = !!early_fsl_find_capability(pci, 0, 0, PCI_CAP_ID_EXP);
+ if (pci->is_pcie) {
+ /* For PCIE read HEADER_TYPE to identify controller mode */
+ early_fsl_read_config_byte(pci, 0, 0, PCI_HEADER_TYPE,
+ &hdr_type);
+ if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL)
goto no_bridge;
-
} else {
/* For PCI read PROG to identify controller mode */
- early_read_config_byte(hose, 0, 0, PCI_CLASS_PROG, &progif);
+ early_fsl_read_config_byte(pci, 0, 0, PCI_CLASS_PROG, &progif);
if ((progif & 1) == 1)
goto no_bridge;
}
- setup_pci_cmd(hose);
+ setup_pci_cmd(pci);
/* check PCI express link status */
- if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
- hose->indirect_type |= PPC_INDIRECT_TYPE_EXT_REG |
- PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
- if (fsl_pcie_check_link(hose))
- hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+ if (pci->is_pcie) {
+ pci->indirect_type |= INDIRECT_TYPE_EXT_REG |
+ INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
+ if (!fsl_pci_check_link(pci))
+ pci->indirect_type |= INDIRECT_TYPE_NO_PCIE_LINK;
}
- printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
- "Firmware bus number: %d->%d\n",
- (unsigned long long)rsrc.start, hose->first_busno,
- hose->last_busno);
-
- pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
- hose, hose->cfg_addr, hose->cfg_data);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, is_primary);
-
/* Setup PEX window registers */
- setup_pci_atmu(hose);
+ setup_pci_atmu(pci);
+
+ platform_set_drvdata(pdev, pci);
return 0;
no_bridge:
- iounmap(hose->private_data);
- /* unmap cfg_data & cfg_addr separately if not on same page */
- if (((unsigned long)hose->cfg_data & PAGE_MASK) !=
- ((unsigned long)hose->cfg_addr & PAGE_MASK))
- iounmap(hose->cfg_data);
- iounmap(hose->cfg_addr);
- pcibios_free_controller(hose);
return -ENODEV;
}
--
1.8.1.2
^ permalink raw reply related
* [PATCH 11/12][v3] pci: fsl: update PCI EDAC driver
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
1. The pci-fsl-common driver has set fsl_pci to device as drvdata,
so EDAC driver can not call dev_set_drvdata() again. fsl_pci
contains regs field to point PCI CCSR, so EDAC may directly use
the pointer and not need to call devm_ioremap().
2. Add mpc85xx_pci_err_remove() to disable PCI error interrupt
and delete PCI EDAC from EDAC subsystem.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/
Added mpc85xx_pci_err_remove()
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
arch/powerpc/sysdev/fsl_pci.c | 1 +
arch/powerpc/sysdev/fsl_pci.h | 6 ++++++
drivers/edac/mpc85xx_edac.c | 46 +++++++++++++++----------------------------
drivers/edac/mpc85xx_edac.h | 1 +
4 files changed, 24 insertions(+), 30 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 40d2e1d..4a03e1a 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -236,6 +236,7 @@ void fsl_arch_pci_sys_remove(struct fsl_pci *pci)
if (!hose)
return;
+ mpc85xx_pci_err_remove(to_platform_device(pci->dev));
pcibios_free_controller(hose);
}
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index ce77aad..ae4dbe2 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -35,11 +35,17 @@ static inline void fsl_pci_assign_primary(void) {}
#ifdef CONFIG_EDAC_MPC85XX
int mpc85xx_pci_err_probe(struct platform_device *op);
+int mpc85xx_pci_err_remove(struct platform_device *op);
#else
static inline int mpc85xx_pci_err_probe(struct platform_device *op)
{
return -ENOTSUPP;
}
+static inline int mpc85xx_pci_err_remove(struct platform_device *op)
+{
+ return -ENOTSUPP;
+}
+
#endif
#ifdef CONFIG_FSL_PCI
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 3eb32f6..14a4116 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
+#include <linux/fsl/pci-common.h>
#include "edac_module.h"
#include "edac_core.h"
#include "mpc85xx_edac.h"
@@ -214,11 +215,13 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
int mpc85xx_pci_err_probe(struct platform_device *op)
{
+ struct fsl_pci *fslpci;
struct edac_pci_ctl_info *pci;
struct mpc85xx_pci_pdata *pdata;
- struct resource r;
int res = 0;
+ fslpci = platform_get_drvdata(op);
+
if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
return -ENOMEM;
@@ -239,7 +242,6 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata = pci->pvt_info;
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
- dev_set_drvdata(&op->dev, pci);
pci->dev = &op->dev;
pci->mod_name = EDAC_MOD_STR;
pci->ctl_name = pdata->name;
@@ -250,30 +252,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata->edac_idx = edac_pci_idx++;
- res = of_address_to_resource(op->dev.of_node, 0, &r);
- if (res) {
- printk(KERN_ERR "%s: Unable to get resource for "
- "PCI err regs\n", __func__);
- goto err;
- }
-
/* we only need the error registers */
- r.start += 0xe00;
-
- if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
- pdata->name)) {
- printk(KERN_ERR "%s: Error while requesting mem region\n",
- __func__);
- res = -EBUSY;
- goto err;
- }
-
- pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
- if (!pdata->pci_vbase) {
- printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
- res = -ENOMEM;
- goto err;
- }
+ pdata->pci_vbase = (void *)fslpci->regs + MPC85XX_PCI_ERR_OFFSET;
orig_pci_err_cap_dr =
in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
@@ -327,20 +307,25 @@ err:
}
EXPORT_SYMBOL(mpc85xx_pci_err_probe);
-static int mpc85xx_pci_err_remove(struct platform_device *op)
+int mpc85xx_pci_err_remove(struct platform_device *op)
{
- struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
- struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+ struct edac_pci_ctl_info *pci;
+ struct mpc85xx_pci_pdata *pdata;
edac_dbg(0, "\n");
+ pci = edac_pci_del_device(&op->dev);
+
+ if (!pci)
+ return -EINVAL;
+
+ pdata = pci->pvt_info;
+
out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR,
orig_pci_err_cap_dr);
out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
- edac_pci_del_device(pci->dev);
-
if (edac_op_state == EDAC_OPSTATE_INT)
irq_dispose_mapping(pdata->irq);
@@ -348,6 +333,7 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
return 0;
}
+EXPORT_SYMBOL(mpc85xx_pci_err_remove);
#endif /* CONFIG_PCI */
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 932016f..3ba235a 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -131,6 +131,7 @@
#define PCI_EDE_PERR_MASK (PCI_EDE_TGT_PERR | PCI_EDE_MST_PERR | \
PCI_EDE_ADDR_PERR)
+#define MPC85XX_PCI_ERR_OFFSET 0x0e00
#define MPC85XX_PCI_ERR_DR 0x0000
#define MPC85XX_PCI_ERR_CAP_DR 0x0004
#define MPC85XX_PCI_ERR_EN 0x0008
--
1.8.1.2
^ permalink raw reply related
* [PATCH 12/12][v3] pci: fsl: fix function check_pci_ctl_endpt_part
From: Minghuan Lian @ 2013-10-23 10:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Minghuan Lian, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood
In-Reply-To: <1382524894-15164-1-git-send-email-Minghuan.Lian@freescale.com>
The new FSL PCI driver does not use cfg_addr of pci_controller,
we may directly access PCI CCSR using fsl_pci->regs.
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
---
change log:
v1-v3:
The new patch to fix function check_pci_ctl_endpt_part
Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/
arch/powerpc/sysdev/fsl_pci.h | 5 -----
drivers/iommu/fsl_pamu_domain.c | 6 ++++--
include/linux/fsl/pci-common.h | 1 +
3 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index ae4dbe2..3176eb2 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -16,11 +16,6 @@
struct platform_device;
-
-/* FSL PCI controller BRR1 register */
-#define PCI_FSL_BRR1 0xbf8
-#define PCI_FSL_BRR1_VER 0xffff
-
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
extern int mpc83xx_add_bridge(struct device_node *dev);
u64 fsl_pci_immrbar_base(struct pci_controller *hose);
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index c857c30..dd7bc25 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -36,6 +36,7 @@
#include <asm/pci-bridge.h>
#include <sysdev/fsl_pci.h>
+#include <linux/fsl/pci-common.h>
#include "fsl_pamu_domain.h"
#include "pci.h"
@@ -908,10 +909,11 @@ static struct iommu_group *get_device_iommu_group(struct device *dev)
static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
{
u32 version;
+ struct fsl_pci *pci = fsl_arch_sys_to_pci(pci_ctl);
/* Check the PCI controller version number by readding BRR1 register */
- version = in_be32(pci_ctl->cfg_addr + (PCI_FSL_BRR1 >> 2));
- version &= PCI_FSL_BRR1_VER;
+ version = in_be32(&pci->regs->block_rev1);
+ version &= PCIE_IP_REV_MASK;
/* If PCI controller version is >= 0x204 we can partition endpoints*/
if (version >= 0x204)
return 1;
diff --git a/include/linux/fsl/pci-common.h b/include/linux/fsl/pci-common.h
index 84b0801..6112adf 100644
--- a/include/linux/fsl/pci-common.h
+++ b/include/linux/fsl/pci-common.h
@@ -18,6 +18,7 @@
#define PCIE_LTSSM_L0 0x16 /* L0 state */
#define PCIE_IP_REV_2_2 0x02080202 /* PCIE IP block version Rev2.2 */
#define PCIE_IP_REV_3_0 0x02080300 /* PCIE IP block version Rev3.0 */
+#define PCIE_IP_REV_MASK 0xffff
#define PIWAR_EN 0x80000000 /* Enable */
#define PIWAR_PF 0x20000000 /* prefetch */
#define PIWAR_TGI_LOCAL 0x00f00000 /* target - local memory */
--
1.8.1.2
^ permalink raw reply related
* Re: Missing _restvr_20 and _savevr_20 subroutines for lib/raid6/altivec8.o
From: Ben Hutchings @ 2013-10-23 10:54 UTC (permalink / raw)
To: Kumar Gala
Cc: debian-powerpc, linuxppc-dev@lists.ozlabs.org list,
Anton Blanchard, Debian kernel maintainers
In-Reply-To: <9A520C29-492E-4FFF-9A0C-190182428FBE@kernel.crashing.org>
[-- Attachment #1: Type: text/plain, Size: 1468 bytes --]
On Wed, 2013-10-23 at 00:28 -0500, Kumar Gala wrote:
> On Oct 19, 2013, at 5:24 PM, Ben Hutchings wrote:
>
> > When building lib/raid6/altivec8.o with gcc 4.8 on Debian, the compiler
> > is generating references to two new runtime subroutines which are
> > apparently not included in the kernel:
> >
> > ERROR: "_restvr_20" [lib/raid6/raid6_pq.ko] undefined!
> > ERROR: "_savevr_20" [lib/raid6/raid6_pq.ko] undefined!
> >
> > The save/restore subroutines are specified in
> > http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.7.1.html#SAVE-RESTORE
> > and we do have the _restgpr_* and _savegpr_* subroutines in
> > arch/powerpc/boot/crtsavres.S. I'm not sure whether these subroutines
> > should be added or whether this indicates the compiler is doing
> > something wrong.
> >
> > A configuration that triggers this is included below.
> >
> > Ben.
>
> Try with CONFIG_CC_OPTIMIZE_FOR_SIZE=n. A feature was added to gcc
> for -Os to "outline" the save/restore routines. I'm surprised this
> hasn't shown up sooner.
That does avoid the problem, thanks.
Ben.
> Well need to add _restvr_* / _savevr_* to the version in lib/crtsaveres.S.
>
> http://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=libgcc/config/rs6000/crtrestvr.S;hb=HEAD
> http://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=libgcc/config/rs6000/crtsavevr.S;hb=HEAD
>
> - k
--
Ben Hutchings
friends: People who know you well, but like you anyway.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
^ permalink raw reply
* Re: perf events ring buffer memory barrier on powerpc
From: Frederic Weisbecker @ 2013-10-23 14:19 UTC (permalink / raw)
To: Michael Neuling, Peter Zijlstra
Cc: Mathieu Desnoyers, linux-kernel, Linux PPC dev, anton,
Victor Kaplansky
In-Reply-To: <12083.1382486094@ale.ozlabs.ibm.com>
On Wed, Oct 23, 2013 at 10:54:54AM +1100, Michael Neuling wrote:
> Frederic,
>
> In the perf ring buffer code we have this in perf_output_get_handle():
>
> if (!local_dec_and_test(&rb->nest))
> goto out;
>
> /*
> * Publish the known good head. Rely on the full barrier implied
> * by atomic_dec_and_test() order the rb->head read and this
> * write.
> */
> rb->user_page->data_head = head;
>
> The comment says atomic_dec_and_test() but the code is
> local_dec_and_test().
>
> On powerpc, local_dec_and_test() doesn't have a memory barrier but
> atomic_dec_and_test() does. Is the comment wrong, or is
> local_dec_and_test() suppose to imply a memory barrier too and we have
> it wrongly implemented in powerpc?
>
> My guess is that local_dec_and_test() is correct but we to add an
> explicit memory barrier like below:
>
> (Kudos to Victor Kaplansky for finding this)
>
> Mikey
>
> diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
> index cd55144..95768c6 100644
> --- a/kernel/events/ring_buffer.c
> +++ b/kernel/events/ring_buffer.c
> @@ -87,10 +87,10 @@ again:
> goto out;
>
> /*
> - * Publish the known good head. Rely on the full barrier implied
> - * by atomic_dec_and_test() order the rb->head read and this
> - * write.
> + * Publish the known good head. We need a memory barrier to order the
> + * order the rb->head read and this write.
> */
> + smp_mb ();
> rb->user_page->data_head = head;
>
> /*
I'm adding Peter in Cc since he wrote that code.
I agree that local_dec_and_test() doesn't need to imply an smp barrier.
All it has to provide as a guarantee is the atomicity against local concurrent
operations (interrupts, preemption, ...).
Now I'm a bit confused about this barrier.
I think we want this ordering:
Kernel User
READ rb->user_page->data_tail READ rb->user_page->data_head
smp_mb() smp_mb()
WRITE rb data READ rb data
smp_mb() smp_mb()
rb->user_page->data_head WRITE rb->user_page->data_tail
So yeah we want a berrier between the data published and the user data_head.
But this ordering concerns wider layout than just rb->head and rb->user_page->data_head
And BTW I can see an smp_rmb() after we read rb->user_page->data_tail. This is probably the
first kernel barrier in my above example. (not sure if rmb() alone is enough though).
^ permalink raw reply
* Re: perf events ring buffer memory barrier on powerpc
From: Frederic Weisbecker @ 2013-10-23 14:25 UTC (permalink / raw)
To: Michael Neuling, Peter Zijlstra
Cc: Mathieu Desnoyers, LKML, Linux PPC dev, Anton Blanchard,
Victor Kaplansky
In-Reply-To: <20131023141948.GB3566@localhost.localdomain>
2013/10/23 Frederic Weisbecker <fweisbec@gmail.com>:
> On Wed, Oct 23, 2013 at 10:54:54AM +1100, Michael Neuling wrote:
>> Frederic,
>>
>> In the perf ring buffer code we have this in perf_output_get_handle():
>>
>> if (!local_dec_and_test(&rb->nest))
>> goto out;
>>
>> /*
>> * Publish the known good head. Rely on the full barrier implied
>> * by atomic_dec_and_test() order the rb->head read and this
>> * write.
>> */
>> rb->user_page->data_head = head;
>>
>> The comment says atomic_dec_and_test() but the code is
>> local_dec_and_test().
>>
>> On powerpc, local_dec_and_test() doesn't have a memory barrier but
>> atomic_dec_and_test() does. Is the comment wrong, or is
>> local_dec_and_test() suppose to imply a memory barrier too and we have
>> it wrongly implemented in powerpc?
>>
>> My guess is that local_dec_and_test() is correct but we to add an
>> explicit memory barrier like below:
>>
>> (Kudos to Victor Kaplansky for finding this)
>>
>> Mikey
>>
>> diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
>> index cd55144..95768c6 100644
>> --- a/kernel/events/ring_buffer.c
>> +++ b/kernel/events/ring_buffer.c
>> @@ -87,10 +87,10 @@ again:
>> goto out;
>>
>> /*
>> - * Publish the known good head. Rely on the full barrier implied
>> - * by atomic_dec_and_test() order the rb->head read and this
>> - * write.
>> + * Publish the known good head. We need a memory barrier to order the
>> + * order the rb->head read and this write.
>> */
>> + smp_mb ();
>> rb->user_page->data_head = head;
>>
>> /*
>
>
> I'm adding Peter in Cc since he wrote that code.
> I agree that local_dec_and_test() doesn't need to imply an smp barrier.
> All it has to provide as a guarantee is the atomicity against local concurrent
> operations (interrupts, preemption, ...).
>
> Now I'm a bit confused about this barrier.
>
> I think we want this ordering:
>
> Kernel User
>
> READ rb->user_page->data_tail READ rb->user_page->data_head
> smp_mb() smp_mb()
> WRITE rb data READ rb data
> smp_mb() smp_mb()
> rb->user_page->data_head WRITE rb->user_page->data_tail
^^ I meant a write above for data_head.
^ permalink raw reply
* Re: powerpc: Don't corrupt user registers on 32-bit
From: Alexander Graf @ 2013-10-23 15:07 UTC (permalink / raw)
To: Scott Wood; +Cc: Paul Mackerras, <linuxppc-dev@ozlabs.org>
In-Reply-To: <20131023102045.GA23685@SnaresPenguin>
Am 23.10.2013 um 11:20 schrieb Scott Wood <scottwood@freescale.com>:
> On Wed, Oct 23, 2013 at 09:40:02AM +0100, Paul Mackerras wrote:
>> Commit de79f7b9f6 ("powerpc: Put FP/VSX and VR state into structures")
>> modified load_up_fpu() and load_up_altivec() in such a way that they
>> now use r7 and r8. Unfortunately, the callers of these functions on
>> 32-bit machines then return to userspace via fast_exception_return,
>> which doesn't restore all of the volatile GPRs, but only r1, r3 -- r6
>> and r9 -- r12. This was causing userspace segfaults and other
>> userspace misbehaviour on 32-bit machines.
>>
>> This fixes the problem by changing the register usage of load_up_fpu()
>> and load_up_altivec() to avoid using r7 and r8 and instead use r6 and
>> r10. This also adds comments to those functions saying which registers
>> may be used.
>>
>> Signed-off-by: Paul Mackerras <paulus@samba.org>
>>
>> ---
>> arch/powerpc/kernel/fpu.S | 14 ++++++++------
>> arch/powerpc/kernel/vector.S | 15 +++++++++------
>> 2 files changed, 17 insertions(+), 12 deletions(-)
>
> Tested-by: Scott Wood <scottwood@freescale.com> (on e500mc, so no altivec)
Tested-by: Alexander Graf <agraf@suse.de> (on a G4 iBook and 970)
>
> -Scott
>
^ permalink raw reply
* Re: [PATCH 1/3] sched: Fix nohz_kick_needed to consider the nr_busy of the parent domain's group
From: Vincent Guittot @ 2013-10-23 15:28 UTC (permalink / raw)
To: Preeti U Murthy
Cc: Michael Neuling, Peter Zijlstra, linuxppc-dev, linux-kernel,
Mike Galbraith, Anton Blanchard, Paul Turner, Ingo Molnar
In-Reply-To: <52679BD6.6090507@linux.vnet.ibm.com>
Hi Preeti
On 23 October 2013 11:50, Preeti U Murthy <preeti@linux.vnet.ibm.com> wrote:
> Hi Peter
>
> On 10/23/2013 03:41 AM, Peter Zijlstra wrote:
>> This nohz stuff really needs to be re-thought and made more scalable --
>> its a royal pain :/
>
> Why not do something like the below instead? It does the following.
>
> This patch introduces sd_busy just like your suggested patch, except that
> it points to the parent of the highest level sched domain which has the
> SD_SHARE_PKG_RESOURCES set and initializes it in update_top_cache_domain().
> This is the sched domain that is relevant in nohz_kick_needed().
>
> sd_set_sd_state_busy(), sd_set_sd_state_idle() and nohz_kick_needed() query
> and update *only* this sched domain(sd_busy) for nr_busy_cpus. They are the
> only users of this parameter. While we are at it, we might as well change
> the nohz_idle parameter to be updated at the sd_busy domain level alone and
> not the base domain level of a CPU. This will unify the concept of busy cpus
> at just one level of sched domain.
>
> There is no need to iterate through all levels of sched domains of a cpu to
> update nr_busy_cpus since it is irrelevant at all other sched domains except
> at sd_busy level.
>
> De-couple asymmetric load balancing from the nr_busy parameter which the
> PATCH 2/3 anyway does. sd_busy therefore is irrelevant for asymmetric load
> balancing.
>
> Regards
> Preeti U Murthy
> --------------------START_PATCH-------------------------------
>
> sched: Fix nohz_kick_needed()
>
> ---
> kernel/sched/core.c | 4 ++++
> kernel/sched/fair.c | 40 ++++++++++++++++++++++------------------
> kernel/sched/sched.h | 1 +
> 3 files changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index c06b8d3..c1dd11c 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
> @@ -5271,6 +5271,7 @@ DEFINE_PER_CPU(struct sched_domain *, sd_llc);
> DEFINE_PER_CPU(int, sd_llc_size);
> DEFINE_PER_CPU(int, sd_llc_id);
> DEFINE_PER_CPU(struct sched_domain *, sd_numa);
> +DEFINE_PER_CPU(struct sched_domain *, sd_busy);
>
> static void update_top_cache_domain(int cpu)
> {
> @@ -5290,6 +5291,9 @@ static void update_top_cache_domain(int cpu)
>
> sd = lowest_flag_domain(cpu, SD_NUMA);
> rcu_assign_pointer(per_cpu(sd_numa, cpu), sd);
> +
> + sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES)->parent;
highest_flag_domain can return null pointer
> + rcu_assign_pointer(per_cpu(sd_busy, cpu), sd);
> }
>
> /*
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 813dd61..71e6f14 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -6515,16 +6515,16 @@ static inline void nohz_balance_exit_idle(int cpu)
> static inline void set_cpu_sd_state_busy(void)
> {
> struct sched_domain *sd;
> + int cpu = smp_processor_id();
>
> rcu_read_lock();
> - sd = rcu_dereference_check_sched_domain(this_rq()->sd);
> + sd = per_cpu(sd_busy, cpu);
Don't you need to use rcu_dereference when using sd_busy ?
>
> if (!sd || !sd->nohz_idle)
> goto unlock;
> sd->nohz_idle = 0;
>
> - for (; sd; sd = sd->parent)
> - atomic_inc(&sd->groups->sgp->nr_busy_cpus);
> + atomic_inc(&sd->groups->sgp->nr_busy_cpus);
> unlock:
> rcu_read_unlock();
> }
> @@ -6532,16 +6532,16 @@ unlock:
> void set_cpu_sd_state_idle(void)
> {
> struct sched_domain *sd;
> + int cpu = smp_processor_id();
>
> rcu_read_lock();
> - sd = rcu_dereference_check_sched_domain(this_rq()->sd);
> + sd = per_cpu(sd_busy, cpu);
>
> if (!sd || sd->nohz_idle)
> goto unlock;
> sd->nohz_idle = 1;
>
> - for (; sd; sd = sd->parent)
> - atomic_dec(&sd->groups->sgp->nr_busy_cpus);
> + atomic_dec(&sd->groups->sgp->nr_busy_cpus);
> unlock:
> rcu_read_unlock();
> }
> @@ -6748,6 +6748,9 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
> {
> unsigned long now = jiffies;
> struct sched_domain *sd;
> + struct sched_group *sg;
> + struct sched_group_power *sgp;
> + int nr_busy;
>
> if (unlikely(idle_cpu(cpu)))
> return 0;
> @@ -6773,22 +6776,23 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
> goto need_kick;
>
> rcu_read_lock();
> - for_each_domain(cpu, sd) {
> - struct sched_group *sg = sd->groups;
> - struct sched_group_power *sgp = sg->sgp;
> - int nr_busy = atomic_read(&sgp->nr_busy_cpus);
> + sd = per_cpu(sd_busy, cpu);
>
> - if (sd->flags & SD_SHARE_PKG_RESOURCES && nr_busy > 1)
> - goto need_kick_unlock;
> + if (sd) {
> + sg = sd->groups;
sg is not needed anymore
> + sgp = sg->sgp;
> + nr_busy = atomic_read(&sgp->nr_busy_cpus);
>
> - if (sd->flags & SD_ASYM_PACKING && nr_busy != sg->group_weight
> - && (cpumask_first_and(nohz.idle_cpus_mask,
> - sched_domain_span(sd)) < cpu))
> + if (nr_busy > 1)
> goto need_kick_unlock;
> -
> - if (!(sd->flags & (SD_SHARE_PKG_RESOURCES | SD_ASYM_PACKING)))
> - break;
> }
> +
> + sd = highest_flag_domain(cpu, SD_ASYM_PACKING);
> +
> + if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
> + sched_domain_span(sd)) < cpu))
> + goto need_kick_unlock;
> +
> rcu_read_unlock();
> return 0;
>
> diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
> index ffc7087..0f1253f 100644
> --- a/kernel/sched/sched.h
> +++ b/kernel/sched/sched.h
> @@ -623,6 +623,7 @@ DECLARE_PER_CPU(struct sched_domain *, sd_llc);
> DECLARE_PER_CPU(int, sd_llc_size);
> DECLARE_PER_CPU(int, sd_llc_id);
> DECLARE_PER_CPU(struct sched_domain *, sd_numa);
> +DECLARE_PER_CPU(struct sched_domain *, sd_busy);
>
> struct sched_group_power {
> atomic_t ref;
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* [PATCH 0/8] treewide: Remove OOM message after input_alloc_device
From: Joe Perches @ 2013-10-23 19:14 UTC (permalink / raw)
To: linux-kernel
Cc: cbe-oss-dev, devel, alsa-devel, linux-samsung-soc, linux-doc,
linux-iio, acpi4asus-user, platform-driver-x86, ibm-acpi-devel,
linux-input, linuxppc-dev, linux-arm-kernel, linux-media
Joe Perches (8):
Documentation: Remove OOM message after input_allocate_device
cell: Remove OOM message after input_allocate_device
hid: Remove OOM message after input_allocate_device
input: Remove OOM message after input_allocate_device
media: Remove OOM message after input_allocate_device
platform:x86: Remove OOM message after input_allocate_device
staging: Remove OOM message after input_allocate_device
sound: Remove OOM message after input_allocate_device
Documentation/input/input-programming.txt | 1 -
arch/powerpc/platforms/cell/cbe_powerbutton.c | 1 -
drivers/hid/hid-input.c | 1 -
drivers/hid/hid-picolcd_core.c | 5 ++---
drivers/input/joystick/as5011.c | 2 --
drivers/input/joystick/db9.c | 1 -
drivers/input/joystick/gamecon.c | 4 +---
drivers/input/joystick/turbografx.c | 1 -
drivers/input/joystick/walkera0701.c | 1 -
drivers/input/keyboard/amikbd.c | 4 +---
drivers/input/keyboard/davinci_keyscan.c | 1 -
drivers/input/keyboard/gpio_keys.c | 1 -
drivers/input/keyboard/lpc32xx-keys.c | 1 -
drivers/input/keyboard/max7359_keypad.c | 1 -
drivers/input/keyboard/mcs_touchkey.c | 1 -
drivers/input/keyboard/mpr121_touchkey.c | 1 -
drivers/input/keyboard/nomadik-ske-keypad.c | 1 -
drivers/input/keyboard/opencores-kbd.c | 1 -
drivers/input/keyboard/pmic8xxx-keypad.c | 1 -
drivers/input/keyboard/pxa27x_keypad.c | 1 -
drivers/input/keyboard/pxa930_rotary.c | 1 -
drivers/input/keyboard/qt1070.c | 1 -
drivers/input/keyboard/qt2160.c | 1 -
drivers/input/keyboard/sh_keysc.c | 1 -
drivers/input/keyboard/tc3589x-keypad.c | 1 -
drivers/input/keyboard/tnetv107x-keypad.c | 1 -
drivers/input/keyboard/w90p910_keypad.c | 1 -
drivers/input/misc/88pm80x_onkey.c | 1 -
drivers/input/misc/88pm860x_onkey.c | 1 -
drivers/input/misc/arizona-haptics.c | 4 +---
drivers/input/misc/atlas_btns.c | 4 +---
drivers/input/misc/da9052_onkey.c | 1 -
drivers/input/misc/da9055_onkey.c | 4 +---
drivers/input/misc/ideapad_slidebar.c | 1 -
drivers/input/misc/ims-pcu.c | 7 +------
drivers/input/misc/kxtj9.c | 4 +---
drivers/input/misc/max8997_haptic.c | 1 -
drivers/input/misc/mc13783-pwrbutton.c | 4 +---
drivers/input/misc/mpu3050.c | 1 -
drivers/input/misc/pcf8574_keypad.c | 1 -
drivers/input/misc/pm8xxx-vibrator.c | 1 -
drivers/input/misc/pmic8xxx-pwrkey.c | 1 -
drivers/input/misc/pwm-beeper.c | 1 -
drivers/input/misc/twl4030-pwrbutton.c | 4 +---
drivers/input/misc/twl6040-vibra.c | 1 -
drivers/input/mouse/appletouch.c | 4 +---
drivers/input/mouse/bcm5974.c | 4 +---
drivers/input/mouse/cyapa.c | 4 +---
drivers/input/mouse/inport.c | 1 -
drivers/input/mouse/logibm.c | 1 -
drivers/input/mouse/pc110pad.c | 1 -
drivers/input/mouse/pxa930_trkball.c | 1 -
drivers/input/tablet/aiptek.c | 5 +----
drivers/input/tablet/gtco.c | 1 -
drivers/input/touchscreen/88pm860x-ts.c | 1 -
drivers/input/touchscreen/atmel_mxt_ts.c | 1 -
drivers/input/touchscreen/atmel_tsadcc.c | 1 -
drivers/input/touchscreen/bu21013_ts.c | 1 -
drivers/input/touchscreen/cyttsp4_core.c | 2 --
drivers/input/touchscreen/da9034-ts.c | 1 -
drivers/input/touchscreen/edt-ft5x06.c | 1 -
drivers/input/touchscreen/eeti_ts.c | 5 +----
drivers/input/touchscreen/htcpen.c | 1 -
drivers/input/touchscreen/intel-mid-touch.c | 1 -
drivers/input/touchscreen/lpc32xx_ts.c | 1 -
drivers/input/touchscreen/mcs5000_ts.c | 1 -
drivers/input/touchscreen/migor_ts.c | 1 -
drivers/input/touchscreen/mk712.c | 1 -
drivers/input/touchscreen/pixcir_i2c_ts.c | 1 -
drivers/input/touchscreen/s3c2410_ts.c | 1 -
drivers/input/touchscreen/ti_am335x_tsc.c | 1 -
drivers/input/touchscreen/tnetv107x-ts.c | 1 -
drivers/media/rc/imon.c | 8 ++------
drivers/media/usb/em28xx/em28xx-input.c | 4 +---
drivers/media/usb/pwc/pwc-if.c | 1 -
drivers/platform/x86/asus-laptop.c | 5 ++---
drivers/platform/x86/eeepc-laptop.c | 4 +---
drivers/platform/x86/ideapad-laptop.c | 4 +---
drivers/platform/x86/intel_mid_powerbtn.c | 4 +---
drivers/platform/x86/panasonic-laptop.c | 5 +----
drivers/platform/x86/thinkpad_acpi.c | 1 -
drivers/platform/x86/topstar-laptop.c | 4 +---
drivers/platform/x86/toshiba_acpi.c | 4 +---
drivers/staging/cptm1217/clearpad_tm1217.c | 2 --
drivers/staging/iio/adc/mxs-lradc.c | 4 +---
drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c | 2 --
sound/pci/hda/hda_beep.c | 4 +---
87 files changed, 29 insertions(+), 152 deletions(-)
--
1.8.1.2.459.gbcd45b4.dirty
^ permalink raw reply
* [PATCH 2/8] cell: Remove OOM message after input_allocate_device
From: Joe Perches @ 2013-10-23 19:14 UTC (permalink / raw)
To: linux-kernel; +Cc: cbe-oss-dev, Paul Mackerras, linuxppc-dev, Arnd Bergmann
In-Reply-To: <cover.1382555436.git.joe@perches.com>
Emitting an OOM message isn't necessary after input_allocate_device
as there's a generic OOM and a dump_stack already done.
Signed-off-by: Joe Perches <joe@perches.com>
---
arch/powerpc/platforms/cell/cbe_powerbutton.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c
index 2bb8031..8804dbd 100644
--- a/arch/powerpc/platforms/cell/cbe_powerbutton.c
+++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c
@@ -58,7 +58,6 @@ static int __init cbe_powerbutton_init(void)
dev = input_allocate_device();
if (!dev) {
ret = -ENOMEM;
- printk(KERN_ERR "%s: Not enough memory.\n", __func__);
goto out;
}
--
1.8.1.2.459.gbcd45b4.dirty
^ permalink raw reply related
* Re: [Cbe-oss-dev] [PATCH 2/8] cell: Remove OOM message after input_allocate_device
From: Geoff Levand @ 2013-10-23 20:49 UTC (permalink / raw)
To: Joe Perches, Arnd Bergmann
Cc: cbe-oss-dev, linuxppc-dev, Paul Mackerras, linux-kernel
In-Reply-To: <d4dc0be1a19693fca1d8d6bbd3a7ee75163cc269.1382555436.git.joe@perches.com>
Hi Joe,
On Wed, 2013-10-23 at 12:14 -0700, Joe Perches wrote:
> Emitting an OOM message isn't necessary after input_allocate_device
> as there's a generic OOM and a dump_stack already done.
>
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> arch/powerpc/platforms/cell/cbe_powerbutton.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c
> index 2bb8031..8804dbd 100644
> --- a/arch/powerpc/platforms/cell/cbe_powerbutton.c
> +++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c
> @@ -58,7 +58,6 @@ static int __init cbe_powerbutton_init(void)
> dev = input_allocate_device();
> if (!dev) {
> ret = -ENOMEM;
> - printk(KERN_ERR "%s: Not enough memory.\n", __func__);
> goto out;
> }
Arnd is out on leave, so I'll say that this looks OK.
Acked-by: Geoff Levand <geoff@infradead.org>
^ permalink raw reply
* Re: [PATCH] [RFC] Emulate "lwsync" to run standard user land on e500 cores
From: Kumar Gala @ 2013-10-24 4:06 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev, Wolfgang Denk
In-Reply-To: <1382523314.3926.21.camel@aoeu.buserror.net>
On Oct 23, 2013, at 5:15 AM, Scott Wood wrote:
> On Wed, 2013-10-23 at 00:07 -0500, Kumar Gala wrote:
>> On Oct 18, 2013, at 2:38 AM, Wolfgang Denk wrote:
>>> diff --git a/arch/powerpc/kernel/traps.c =
b/arch/powerpc/kernel/traps.c
>>> index f783c93..f330374 100644
>>> --- a/arch/powerpc/kernel/traps.c
>>> +++ b/arch/powerpc/kernel/traps.c
>>> @@ -986,6 +986,13 @@ static int emulate_instruction(struct pt_regs =
*regs)
>>> return 0;
>>> }
>>>=20
>>> + /* Emulating the lwsync insn as a sync insn */
>>> + if (instword =3D=3D PPC_INST_LWSYNC) {
>>> + PPC_WARN_EMULATED(lwsync, regs);
>>> + asm volatile("sync" : : : "memory");
>>=20
>> Do we really need the inline asm? Doesn't the fact of just taking an =
exception and returning from it equate to a sync.
>=20
> No, it doesn't equate to a sync. See the discussion here:
> http://patchwork.ozlabs.org/patch/256747/
>=20
Thanks.=20
I'm not sure I'm a fan of doing this as it silently hides a significant =
performance impact.
Could we possible re-write the userspace instruction to be a 'sync' when =
we hit this?
- k
^ permalink raw reply
* Re: [PATCH 3/3] sched: Aggressive balance in domains whose groups share package resources
From: Preeti U Murthy @ 2013-10-24 4:04 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Michael Neuling, Mike Galbraith, linuxppc-dev, linux-kernel,
Anton Blanchard, Paul Turner, Ingo Molnar
In-Reply-To: <20131022222326.GL2490@laptop.programming.kicks-ass.net>
Hi Peter,
On 10/23/2013 03:53 AM, Peter Zijlstra wrote:
> On Mon, Oct 21, 2013 at 05:15:02PM +0530, Vaidyanathan Srinivasan wrote:
>> kernel/sched/fair.c | 18 ++++++++++++++++++
>> 1 file changed, 18 insertions(+)
>>
>> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
>> index 828ed97..bbcd96b 100644
>> --- a/kernel/sched/fair.c
>> +++ b/kernel/sched/fair.c
>> @@ -5165,6 +5165,8 @@ static int load_balance(int this_cpu, struct rq *this_rq,
>> {
>> int ld_moved, cur_ld_moved, active_balance = 0;
>> struct sched_group *group;
>> + struct sched_domain *child;
>> + int share_pkg_res = 0;
>> struct rq *busiest;
>> unsigned long flags;
>> struct cpumask *cpus = __get_cpu_var(load_balance_mask);
>> @@ -5190,6 +5192,10 @@ static int load_balance(int this_cpu, struct rq *this_rq,
>>
>> schedstat_inc(sd, lb_count[idle]);
>>
>> + child = sd->child;
>> + if (child && child->flags & SD_SHARE_PKG_RESOURCES)
>> + share_pkg_res = 1;
>> +
>> redo:
>> if (!should_we_balance(&env)) {
>> *continue_balancing = 0;
>> @@ -5202,6 +5208,7 @@ redo:
>> goto out_balanced;
>> }
>>
>> +redo_grp:
>> busiest = find_busiest_queue(&env, group);
>> if (!busiest) {
>> schedstat_inc(sd, lb_nobusyq[idle]);
>> @@ -5292,6 +5299,11 @@ more_balance:
>> if (!cpumask_empty(cpus)) {
>> env.loop = 0;
>> env.loop_break = sched_nr_migrate_break;
>> + if (share_pkg_res &&
>> + cpumask_intersects(cpus,
>> + to_cpumask(group->cpumask)))
>
> sched_group_cpus()
>
>> + goto redo_grp;
>> +
>> goto redo;
>> }
>> goto out_balanced;
>> @@ -5318,9 +5330,15 @@ more_balance:
>> */
>> if (!cpumask_test_cpu(this_cpu,
>> tsk_cpus_allowed(busiest->curr))) {
>> + cpumask_clear_cpu(cpu_of(busiest), cpus);
>> raw_spin_unlock_irqrestore(&busiest->lock,
>> flags);
>> env.flags |= LBF_ALL_PINNED;
>> + if (share_pkg_res &&
>> + cpumask_intersects(cpus,
>> + to_cpumask(group->cpumask)))
>> + goto redo_grp;
>> +
>> goto out_one_pinned;
>> }
>
> Man this retry logic is getting annoying.. isn't there anything saner we
> can do?
Let me give this a thought and get back.
Regards
Preeti U Murthy
>
^ permalink raw reply
* Re: [PATCH 02/12][v3] pci: fsl: add structure fsl_pci
From: Kumar Gala @ 2013-10-24 4:11 UTC (permalink / raw)
To: Minghuan Lian
Cc: Arnd Bergmann, linux-pci, Zang Roy-R61911, Bjorn Helgaas,
Scott Wood, linuxppc-dev@lists.ozlabs.org list, linux-arm-kernel
In-Reply-To: <1382524894-15164-2-git-send-email-Minghuan.Lian@freescale.com>
On Oct 23, 2013, at 5:41 AM, Minghuan Lian wrote:
> PowerPC uses structure pci_controller to describe PCI controller,
> but ARM uses structure pci_sys_data. In order to support PowerPC
> and ARM simultaneously, the patch adds a structure fsl_pci that
> contains most of the members of the pci_controller and pci_sys_data.
> Meanwhile, it defines a interface fsl_arch_sys_to_pci() which should
> be implemented in architecture-specific PCI controller driver to
> convert pci_controller or pci_sys_data to fsl_pci.
>=20
> Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
> ---
> change log:
> v1-v3:
> Derived from http://patchwork.ozlabs.org/patch/278965/
>=20
> Based on upstream master.
> Based on the discussion of RFC version here
> http://patchwork.ozlabs.org/patch/274487/
>=20
> include/linux/fsl/pci-common.h | 41 =
+++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
NAK.
We discussed this some at the ARM Summit this week and the feeling is we =
need to move to a common interface between the various ARCHs.
- k
>=20
> diff --git a/include/linux/fsl/pci-common.h =
b/include/linux/fsl/pci-common.h
> index 5e4f683..e56a040 100644
> --- a/include/linux/fsl/pci-common.h
> +++ b/include/linux/fsl/pci-common.h
> @@ -102,5 +102,46 @@ struct ccsr_pci {
>=20
> };
>=20
> +/*
> + * Structure of a PCI controller (host bridge)
> + */
> +struct fsl_pci {
> + struct list_head node;
> + bool is_pcie;
> + struct device_node *dn;
> + struct device *dev;
> +
> + int first_busno;
> + int last_busno;
> + int self_busno;
> + struct resource busn;
> +
> + struct pci_ops *ops;
> + struct ccsr_pci __iomem *regs;
> +
> + u32 indirect_type;
> +
> + struct resource io_resource;
> + resource_size_t io_base_phys;
> + resource_size_t pci_io_size;
> +
> + struct resource mem_resources[3];
> + resource_size_t mem_offset[3];
> +
> + int global_number; /* PCI domain number */
> +
> + resource_size_t dma_window_base_cur;
> + resource_size_t dma_window_size;
> +
> + void *sys;
> +};
> +
> +/*
> + * Convert architecture specific pci controller structure to fsl_pci
> + * PowerPC uses structure pci_controller and ARM uses structure =
pci_sys_data
> + * to describe pci controller.
> + */
> +extern struct fsl_pci *fsl_arch_sys_to_pci(void *sys);
> +
> #endif /* __PCI_COMMON_H */
> #endif /* __KERNEL__ */
> --=20
> 1.8.1.2
>=20
^ permalink raw reply
* RE: [PATCH 02/12][v3] pci: fsl: add structure fsl_pci
From: Zang Roy-R61911 @ 2013-10-24 4:15 UTC (permalink / raw)
To: Kumar Gala, Lian Minghuan-B31939
Cc: Wood Scott-B07421, Arnd Bergmann, linux-pci@vger.kernel.org,
Bjorn Helgaas, linuxppc-dev@lists.ozlabs.org list,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <2B28E421-9B64-4CEC-9E00-8893502CE12F@kernel.crashing.org>
> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Wednesday, October 23, 2013 11:11 PM
> To: Lian Minghuan-B31939
> Cc: linuxppc-dev@lists.ozlabs.org list; Arnd Bergmann; Zang Roy-R61911;
> Wood Scott-B07421; Bjorn Helgaas; linux-pci@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [PATCH 02/12][v3] pci: fsl: add structure fsl_pci
>=20
>=20
> On Oct 23, 2013, at 5:41 AM, Minghuan Lian wrote:
>=20
> > PowerPC uses structure pci_controller to describe PCI controller, but
> > ARM uses structure pci_sys_data. In order to support PowerPC and ARM
> > simultaneously, the patch adds a structure fsl_pci that contains most
> > of the members of the pci_controller and pci_sys_data.
> > Meanwhile, it defines a interface fsl_arch_sys_to_pci() which should
> > be implemented in architecture-specific PCI controller driver to
> > convert pci_controller or pci_sys_data to fsl_pci.
> >
> > Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
> > ---
> > change log:
> > v1-v3:
> > Derived from http://patchwork.ozlabs.org/patch/278965/
> >
> > Based on upstream master.
> > Based on the discussion of RFC version here
> > http://patchwork.ozlabs.org/patch/274487/
> >
> > include/linux/fsl/pci-common.h | 41
> > +++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 41 insertions(+)
>=20
> NAK.
>=20
> We discussed this some at the ARM Summit this week and the feeling is we
> need to move to a common interface between the various ARCHs.
Can you share more about the *common interface*?
Any plan to implement the * common interface*?
Thanks.
Roy
^ permalink raw reply
* Re: [PATCH 1/3] sched: Fix nohz_kick_needed to consider the nr_busy of the parent domain's group
From: Preeti U Murthy @ 2013-10-24 8:07 UTC (permalink / raw)
To: Vincent Guittot, Peter Zijlstra, Ingo Molnar
Cc: Michael Neuling, Mike Galbraith, linuxppc-dev, linux-kernel,
Anton Blanchard, Paul Turner
In-Reply-To: <CAKfTPtAUFdmc7PasebNksYztMwRrWsGWPgN6JJJurddu+UP-hQ@mail.gmail.com>
Hi Vincent,
I have addressed your comments and below is the fresh patch. This patch
applies on PATCH 2/3 posted in this thread.
Regards
Preeti U Murthy
sched:Remove un-necessary iterations over sched domains to update/query nr_busy_cpus
From: Preeti U Murthy <preeti@linux.vnet.ibm.com>
nr_busy_cpus parameter is used by nohz_kick_needed() to find out the number
of busy cpus in a sched domain which has SD_SHARE_PKG_RESOURCES flag set.
Therefore instead of updating nr_busy_cpus at every level of sched domain,
since it is irrelevant, we can update this parameter only at the parent
domain of the sd which has this flag set. Introduce a per-cpu parameter
sd_busy which represents this parent domain.
In nohz_kick_needed() we directly query the nr_busy_cpus parameter
associated with the groups of sd_busy.
By associating sd_busy with the highest domain which has
SD_SHARE_PKG_RESOURCES flag set, we cover all lower level domains which could
have this flag set and trigger nohz_idle_balancing if any of the levels have
more than one busy cpu.
sd_busy is irrelevant for asymmetric load balancing.
While we are at it, we might as well change the nohz_idle parameter to be
updated at the sd_busy domain level alone and not the base domain level of a CPU.
This will unify the concept of busy cpus at just one level of sched domain
where it is currently used.
Signed-off-by: Preeti U Murthy<preeti@linux.vnet.ibm.com>
---
kernel/sched/core.c | 5 +++++
kernel/sched/fair.c | 38 ++++++++++++++++++++------------------
kernel/sched/sched.h | 1 +
3 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index c06b8d3..c540392 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5271,6 +5271,7 @@ DEFINE_PER_CPU(struct sched_domain *, sd_llc);
DEFINE_PER_CPU(int, sd_llc_size);
DEFINE_PER_CPU(int, sd_llc_id);
DEFINE_PER_CPU(struct sched_domain *, sd_numa);
+DEFINE_PER_CPU(struct sched_domain *, sd_busy);
static void update_top_cache_domain(int cpu)
{
@@ -5290,6 +5291,10 @@ static void update_top_cache_domain(int cpu)
sd = lowest_flag_domain(cpu, SD_NUMA);
rcu_assign_pointer(per_cpu(sd_numa, cpu), sd);
+
+ sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES);
+ if (sd)
+ rcu_assign_pointer(per_cpu(sd_busy, cpu), sd->parent);
}
/*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e9c9549..f66cfd9 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6515,16 +6515,16 @@ static inline void nohz_balance_exit_idle(int cpu)
static inline void set_cpu_sd_state_busy(void)
{
struct sched_domain *sd;
+ int cpu = smp_processor_id();
rcu_read_lock();
- sd = rcu_dereference_check_sched_domain(this_rq()->sd);
+ sd = rcu_dereference(per_cpu(sd_busy, cpu));
if (!sd || !sd->nohz_idle)
goto unlock;
sd->nohz_idle = 0;
- for (; sd; sd = sd->parent)
- atomic_inc(&sd->groups->sgp->nr_busy_cpus);
+ atomic_inc(&sd->groups->sgp->nr_busy_cpus);
unlock:
rcu_read_unlock();
}
@@ -6532,16 +6532,16 @@ unlock:
void set_cpu_sd_state_idle(void)
{
struct sched_domain *sd;
+ int cpu = smp_processor_id();
rcu_read_lock();
- sd = rcu_dereference_check_sched_domain(this_rq()->sd);
+ sd = rcu_dereference(per_cpu(sd_busy, cpu));
if (!sd || sd->nohz_idle)
goto unlock;
sd->nohz_idle = 1;
- for (; sd; sd = sd->parent)
- atomic_dec(&sd->groups->sgp->nr_busy_cpus);
+ atomic_dec(&sd->groups->sgp->nr_busy_cpus);
unlock:
rcu_read_unlock();
}
@@ -6748,6 +6748,8 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
{
unsigned long now = jiffies;
struct sched_domain *sd;
+ struct sched_group_power *sgp;
+ int nr_busy;
if (unlikely(idle_cpu(cpu)))
return 0;
@@ -6773,22 +6775,22 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)
goto need_kick;
rcu_read_lock();
- for_each_domain(cpu, sd) {
- struct sched_group *sg = sd->groups;
- struct sched_group_power *sgp = sg->sgp;
- int nr_busy = atomic_read(&sgp->nr_busy_cpus);
+ sd = rcu_dereference(per_cpu(sd_busy, cpu));
- if (sd->flags & SD_SHARE_PKG_RESOURCES && nr_busy > 1)
- goto need_kick_unlock;
+ if (sd) {
+ sgp = sd->groups->sgp;
+ nr_busy = atomic_read(&sgp->nr_busy_cpus);
- if (sd->flags & SD_ASYM_PACKING
- && (cpumask_first_and(nohz.idle_cpus_mask,
- sched_domain_span(sd)) < cpu))
+ if (nr_busy > 1)
goto need_kick_unlock;
-
- if (!(sd->flags & (SD_SHARE_PKG_RESOURCES | SD_ASYM_PACKING)))
- break;
}
+
+ sd = highest_flag_domain(cpu, SD_ASYM_PACKING);
+
+ if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
+ sched_domain_span(sd)) < cpu))
+ goto need_kick_unlock;
+
rcu_read_unlock();
return 0;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index ffc7087..0f1253f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -623,6 +623,7 @@ DECLARE_PER_CPU(struct sched_domain *, sd_llc);
DECLARE_PER_CPU(int, sd_llc_size);
DECLARE_PER_CPU(int, sd_llc_id);
DECLARE_PER_CPU(struct sched_domain *, sd_numa);
+DECLARE_PER_CPU(struct sched_domain *, sd_busy);
struct sched_group_power {
atomic_t ref;
^ permalink raw reply related
* Re: [PATCH] [RFC] Emulate "lwsync" to run standard user land on e500 cores
From: Benjamin Herrenschmidt @ 2013-10-24 9:45 UTC (permalink / raw)
To: Kumar Gala; +Cc: Scott Wood, linuxppc-dev, Wolfgang Denk
In-Reply-To: <BE5B0245-4ED1-4E3F-ADB1-F6A70C8FE3E1@kernel.crashing.org>
On Wed, 2013-10-23 at 23:06 -0500, Kumar Gala wrote:
> On Oct 23, 2013, at 5:15 AM, Scott Wood wrote:
>
> > On Wed, 2013-10-23 at 00:07 -0500, Kumar Gala wrote:
> >> On Oct 18, 2013, at 2:38 AM, Wolfgang Denk wrote:
> >>> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> >>> index f783c93..f330374 100644
> >>> --- a/arch/powerpc/kernel/traps.c
> >>> +++ b/arch/powerpc/kernel/traps.c
> >>> @@ -986,6 +986,13 @@ static int emulate_instruction(struct pt_regs *regs)
> >>> return 0;
> >>> }
> >>>
> >>> + /* Emulating the lwsync insn as a sync insn */
> >>> + if (instword == PPC_INST_LWSYNC) {
> >>> + PPC_WARN_EMULATED(lwsync, regs);
> >>> + asm volatile("sync" : : : "memory");
> >>
> >> Do we really need the inline asm? Doesn't the fact of just taking an exception and returning from it equate to a sync.
> >
> > No, it doesn't equate to a sync. See the discussion here:
> > http://patchwork.ozlabs.org/patch/256747/
> >
>
> Thanks.
>
> I'm not sure I'm a fan of doing this as it silently hides a significant performance impact.
>
> Could we possible re-write the userspace instruction to be a 'sync' when we hit this?
Rewriting user space is a can of worms I wouldn't get into ... is any
other arch doing it ?
I'm not too worried as long as we warn and account them.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] [RFC] Emulate "lwsync" to run standard user land on e500 cores
From: Kumar Gala @ 2013-10-24 9:55 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Scott Wood, linuxppc-dev, Wolfgang Denk
In-Reply-To: <1382607919.9395.56.camel@pasglop>
On Oct 24, 2013, at 4:45 AM, Benjamin Herrenschmidt wrote:
> On Wed, 2013-10-23 at 23:06 -0500, Kumar Gala wrote:
>> On Oct 23, 2013, at 5:15 AM, Scott Wood wrote:
>>=20
>>> On Wed, 2013-10-23 at 00:07 -0500, Kumar Gala wrote:
>>>> On Oct 18, 2013, at 2:38 AM, Wolfgang Denk wrote:
>>>>> diff --git a/arch/powerpc/kernel/traps.c =
b/arch/powerpc/kernel/traps.c
>>>>> index f783c93..f330374 100644
>>>>> --- a/arch/powerpc/kernel/traps.c
>>>>> +++ b/arch/powerpc/kernel/traps.c
>>>>> @@ -986,6 +986,13 @@ static int emulate_instruction(struct pt_regs =
*regs)
>>>>> return 0;
>>>>> }
>>>>>=20
>>>>> + /* Emulating the lwsync insn as a sync insn */
>>>>> + if (instword =3D=3D PPC_INST_LWSYNC) {
>>>>> + PPC_WARN_EMULATED(lwsync, regs);
>>>>> + asm volatile("sync" : : : "memory");
>>>>=20
>>>> Do we really need the inline asm? Doesn't the fact of just taking =
an exception and returning from it equate to a sync.
>>>=20
>>> No, it doesn't equate to a sync. See the discussion here:
>>> http://patchwork.ozlabs.org/patch/256747/
>>>=20
>>=20
>> Thanks.=20
>>=20
>> I'm not sure I'm a fan of doing this as it silently hides a =
significant performance impact.
>>=20
>> Could we possible re-write the userspace instruction to be a 'sync' =
when we hit this?
>=20
> Rewriting user space is a can of worms I wouldn't get into ... is any
> other arch doing it ?
Fair enough
>=20
> I'm not too worried as long as we warn and account them.
Than, I'd ask this be under a Kconfig option that is disabled by =
default. Users should have to explicitly enable this so they know what =
they are doing.
- k
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox