* Re: [PATCH 2/3] powerpc: Enable boot_vga sysfs attribute for graphics adapters on Power
From: Michael Ellerman @ 2013-04-08 5:25 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: linux-pci@vger.kernel.org, klebers, sparclinux,
Lucas Kannebley Tavares, Brian King, linuxppc-dev
In-Reply-To: <CAErSpo5ReUcSPvyBs_u0HLh=90anEREZn4p6EUX4yO52bDBaeg@mail.gmail.com>
On Fri, Apr 05, 2013 at 02:11:01PM -0600, Bjorn Helgaas wrote:
> On Thu, Apr 4, 2013 at 3:58 PM, Brian King <brking@linux.vnet.ibm.com> wrote:
> >
> > Initialize dev->dev.type such that the PCI group attributes for boot_vga
> > and SR-IOV can be displayed if appropriate. This fixes an issue seen on
> > Power preventing X from auto initializing a graphics adapter when using KMS.
> >
> > Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
> > ---
> >
> > arch/powerpc/kernel/pci_of_scan.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff -puN arch/powerpc/kernel/pci_of_scan.c~powerpc_set_pci_dev_type arch/powerpc/kernel/pci_of_scan.c
> > --- linux/arch/powerpc/kernel/pci_of_scan.c~powerpc_set_pci_dev_type 2013-04-03 09:43:19.000000000 -0500
> > +++ linux-bjking1/arch/powerpc/kernel/pci_of_scan.c 2013-04-03 09:43:19.000000000 -0500
> > @@ -141,6 +141,7 @@ struct pci_dev *of_create_pci_dev(struct
> > dev->dev.of_node = of_node_get(node);
> > dev->dev.parent = bus->bridge;
> > dev->dev.bus = &pci_bus_type;
> > + dev->dev.type = &pci_dev_type;
> > dev->devfn = devfn;
> > dev->multifunction = 0; /* maybe a lie? */
> > dev->needs_freset = 0; /* pcie fundamental reset required */
>
> I think sparc has the same issue in its own copy of of_create_pci_dev().
>
> Of course, both of_create_pci_dev() implementations are basically
> copies of the generic pci_setup_device() that most arches use. That's
> the reason why I wish sparc and powerpc had used config space
> accessors that hid the OF mangling internally so they could use the
> generic pci_setup_device() instead of cloning it.
>
> Of course, they don't, and that's too much work for fixing this issue,
> but if anybody wanted to work on that, I think it would be an
> interesting project.
>
> But what if you set dev->dev.type in alloc_pci_dev()? I think if you
> did that, you wouldn't need to export "pci_dev_type," and it should
> fix this for both powerpc and sparc.
That sounds good, Brian can you confirm that works and send a new series
using that technique.
cheers
^ permalink raw reply
* Re: [PATCH 3/3] powerpc: Set default VGA device
From: Benjamin Herrenschmidt @ 2013-04-08 6:39 UTC (permalink / raw)
To: Michael Ellerman
Cc: sparclinux, linux-pci@vger.kernel.org, klebers, Brian King,
Lucas Kannebley Tavares, Bjorn Helgaas, linuxppc-dev
In-Reply-To: <20130408052124.GA9550@concordia>
On Mon, 2013-04-08 at 15:21 +1000, Michael Ellerman wrote:
> Looking at x86, ia64 and ours, there's a fair bit of difference.
>
> x86/ia64 both walk up the parents checking PCI_BRIDGE_CTL_VGA, which
> powerpc doesn't (though maybe it should?).
Unclear for several reasons.
That bit indicates that the bridge forwards the hard coded legacy VGA IO
ports and memory aperture. These are not necessary to get modern video
cards going. Only if legacy modes are used.
On x86, that tends to be the case (is it always even with EFI
nowadays ?).
On other architectures that is not necessarily the case. The firmware
can (and will) initialize the card using MMIO entirely and even if
possible disabling the legacy stuff, which means that turning those bits
on in the bridge is also unnecessary.
In fact, on such setups, the isn't really a concept of a "primary" video
card to begin with.
On the other hand, that also means that a video card initialized like
that is pretty much out of the grasp of the vga arbiter which has no
effect on it either.
Also be careful that while it may be relevant on x86, the VGA fwd bit is
not on the PCIe root complex on IBM machines.
Finally, P8 has no IO space at all...
> x86/ia64 set IORESOURCE_ROM_SHADOW, which powerpc doesn't.
>
> ia64 doesn't call vga_set_default_device(), x86 and powerpc do.
>
> So we'll merge this and maybe someone can tease out the common bits, but
> personally I don't see that there's an obvious chunk of generic logic.
Cheers,
Ben.
^ permalink raw reply
* [git pull] Please pull another powerpc fix
From: Stephen Rothwell @ 2013-04-08 7:54 UTC (permalink / raw)
To: Linus; +Cc: Michael Wolf, ppc-dev, paulus, LKML
[-- Attachment #1: Type: text/plain, Size: 1046 bytes --]
The following changes since commit 875b7679abbb232b584f2eec59fa6e45690dd6c4:
Merge git://git.kernel.org/pub/scm/virt/kvm/kvm (2013-04-07 13:01:25 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes.git tags/for-linus
for you to fetch changes up to 9fb2640159f9d4f5a2a9d60e490482d4cbecafdb:
powerpc: pSeries_lpar_hpte_remove fails from Adjunct partition being performed before the ANDCOND test (2013-04-08 15:19:09 +1000)
----------------------------------------------------------------
A single BUG_ON fix for a condition that could happen for machines with
certain hardware installed.
----------------------------------------------------------------
Michael Wolf (1):
powerpc: pSeries_lpar_hpte_remove fails from Adjunct partition being performed before the ANDCOND test
arch/powerpc/platforms/pseries/lpar.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [RFC][PATCH 2/2] powerpc/fsl-pci Make PCIe hotplug work with Freescale
From: Rojhalat Ibrahim @ 2013-04-08 8:15 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <CE155C19-35DF-4394-9608-BF923B5DA6EB@kernel.crashing.org>
Up to now the PCIe link status on Freescale PCIe controllers was only
checked once at boot time. So hotplug did not work. With this patch the
link status is checked on every config read. PCIe devices not present at
boot time are found after doing 'echo 1 >/sys/bus/pci/rescan'.
Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de>
---
arch/powerpc/include/asm/pci-bridge.h | 6 ++++
arch/powerpc/sysdev/fsl_pci.c | 51 +++++++++++++++++++++++++++++-----
arch/powerpc/sysdev/indirect_pci.c | 10 ++----
3 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index c0278f0..ffbc5fd 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -120,6 +120,12 @@ extern void setup_indirect_pci(struct pci_controller* hose,
resource_size_t cfg_addr,
resource_size_t cfg_data, u32 flags);
+extern int indirect_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val);
+
+extern int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val);
+
static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
{
return bus->sysdata;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 83918c3..82e3317 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -54,12 +54,22 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
return;
}
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
+static int fsl_indirect_read_config(struct pci_bus *, unsigned int,
+ int, int, u32 *);
+
+static int fsl_pcie_check_link(struct pci_controller *hose)
{
- u32 val;
+ u32 val = 0;
if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
- early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+ if (hose->ops->read == fsl_indirect_read_config) {
+ struct pci_bus bus;
+ bus.number = 0;
+ 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 (val < PCIE_LTSSM_L0)
return 1;
} else {
@@ -74,6 +84,33 @@ static int __init fsl_pcie_check_link(struct pci_controller *hose)
return 0;
}
+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);
+
+ if (fsl_pcie_check_link(hose))
+ hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+ else
+ hose->indirect_type &= ~PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+
+ return indirect_read_config(bus, devfn, offset, len, val);
+}
+
+static struct pci_ops fsl_indirect_pci_ops =
+{
+ .read = fsl_indirect_read_config,
+ .write = indirect_write_config,
+};
+
+static void __init fsl_setup_indirect_pci(struct pci_controller* hose,
+ resource_size_t cfg_addr,
+ resource_size_t cfg_data, u32 flags)
+{
+ setup_indirect_pci(hose, cfg_addr, cfg_data, flags);
+ hose->ops = &fsl_indirect_pci_ops;
+}
+
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
#define MAX_PHYS_ADDR_BITS 40
@@ -469,8 +506,8 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
if (!hose->private_data)
goto no_bridge;
- setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
- PPC_INDIRECT_TYPE_BIG_ENDIAN);
+ fsl_setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
+ PPC_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;
@@ -779,8 +816,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
if (ret)
goto err0;
} else {
- setup_indirect_pci(hose, rsrc_cfg.start,
- rsrc_cfg.start + 4, 0);
+ fsl_setup_indirect_pci(hose, rsrc_cfg.start,
+ rsrc_cfg.start + 4, 0);
}
printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index 82fdad8..c6c8b52 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -20,9 +20,8 @@
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
-static int
-indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
+int 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);
volatile void __iomem *cfg_data;
@@ -78,9 +77,8 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
return PCIBIOS_SUCCESSFUL;
}
-static int
-indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
+int indirect_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
{
struct pci_controller *hose = pci_bus_to_host(bus);
volatile void __iomem *cfg_data;
---
1.8.1.5
^ permalink raw reply related
* Re: [RFC][PATCH 1/2] powerpc/fsl-pci: Keep PCI SoC controller registers in
From: Rojhalat Ibrahim @ 2013-04-08 8:20 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1363201636-7318-1-git-send-email-galak@kernel.crashing.org>
On Wednesday 13 March 2013 14:07:15 Kumar Gala wrote:
> Move to keeping the SoC registers that control and config the PCI
> controllers on FSL SoCs in the pci_controller struct. This allows us to
> not need to ioremap() the registers in multiple different places that
> use them.
>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Acked-by: Rojhalat Ibrahim <imr@rtschenk.de>
> ---
> arch/powerpc/include/asm/pci-bridge.h | 5 ++-
> arch/powerpc/sysdev/fsl_pci.c | 69
> ++++++++++++++------------------- 2 files changed, 34 insertions(+), 40
> deletions(-)
>
> diff --git a/arch/powerpc/include/asm/pci-bridge.h
> b/arch/powerpc/include/asm/pci-bridge.h index 025a130..c0278f0 100644
> --- a/arch/powerpc/include/asm/pci-bridge.h
> +++ b/arch/powerpc/include/asm/pci-bridge.h
> @@ -70,6 +70,8 @@ struct pci_controller {
> * BIG_ENDIAN - cfg_addr is a big endian register
> * BROKEN_MRM - the 440EPx/GRx chips have an errata that causes hangs on
> * the PLB4. Effectively disable MRM commands by setting this.
> + * FSL_CFG_REG_LINK - Freescale controller version in which the PCIe
> + * link status is in a RC PCIe cfg register (vs being a SoC register)
> */
> #define PPC_INDIRECT_TYPE_SET_CFG_TYPE 0x00000001
> #define PPC_INDIRECT_TYPE_EXT_REG 0x00000002
> @@ -77,6 +79,7 @@ struct pci_controller {
> #define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008
> #define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010
> #define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020
> +#define PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK 0x00000040
> u32 indirect_type;
> /* Currently, we limit ourselves to 1 IO range and 3 mem
> * ranges since the common pci_bus structure can't handle more
> @@ -90,9 +93,9 @@ struct pci_controller {
>
> #ifdef CONFIG_PPC64
> unsigned long buid;
> +#endif /* CONFIG_PPC64 */
>
> void *private_data;
> -#endif /* CONFIG_PPC64 */
> };
>
> /* These are used for config access before all the PCI probing
> diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
> index 3271177..41bbcc4 100644
> --- a/arch/powerpc/sysdev/fsl_pci.c
> +++ b/arch/powerpc/sysdev/fsl_pci.c
> @@ -54,34 +54,22 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
> return;
> }
>
> -static int __init fsl_pcie_check_link(struct pci_controller *hose,
> - struct resource *rsrc)
> +static int __init fsl_pcie_check_link(struct pci_controller *hose)
> {
> - struct ccsr_pci __iomem *pci = NULL;
> u32 val;
>
> - /* for PCIe IP rev 3.0 or greater use CSR0 for link state */
> - if (rsrc) {
> - pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
> - (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
> - pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
> - if (!pci) {
> - dev_err(hose->parent, "Unable to map PCIe registers\n");
> - return -ENOMEM;
> - }
> - if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_3_0) {
> - val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK)
> - >> PEX_CSR0_LTSSM_SHIFT;
> - if (val != PEX_CSR0_LTSSM_L0)
> - return 1;
> - iounmap(pci);
> - return 0;
> - }
> - iounmap(pci);
> + if (hose->indirect_type & PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK) {
> + early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
> + if (val < PCIE_LTSSM_L0)
> + return 1;
> + } 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)
> + >> PEX_CSR0_LTSSM_SHIFT;
> + if (val != PEX_CSR0_LTSSM_L0)
> + return 1;
> }
> - early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
> - if (val < PCIE_LTSSM_L0)
> - return 1;
>
> return 0;
> }
> @@ -148,10 +136,9 @@ 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,
> - struct resource *rsrc)
> +static void setup_pci_atmu(struct pci_controller *hose)
> {
> - struct ccsr_pci __iomem *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 paddr_lo = ULLONG_MAX;
> @@ -162,15 +149,6 @@ static void setup_pci_atmu(struct pci_controller *hose,
> const u64 *reg;
> int len;
>
> - pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
> - (u64)rsrc->start, (u64)resource_size(rsrc));
> -
> - pci = ioremap(rsrc->start, resource_size(rsrc));
> - if (!pci) {
> - dev_err(hose->parent, "Unable to map ATMU registers\n");
> - return;
> - }
> -
> if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
> if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
> win_idx = 2;
> @@ -451,6 +429,7 @@ int __init fsl_add_bridge(struct platform_device *pdev,
> int is_primary) const int *bus_range;
> u8 hdr_type, progif;
> struct device_node *dev;
> + struct ccsr_pci __iomem *pci;
>
> dev = pdev->dev.of_node;
>
> @@ -483,9 +462,19 @@ int __init fsl_add_bridge(struct platform_device *pdev,
> int is_primary) hose->first_busno = bus_range ? bus_range[0] : 0x0;
> hose->last_busno = bus_range ? bus_range[1] : 0xff;
>
> + pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
> + (u64)rsrc.start, (u64)resource_size(&rsrc));
> +
> + pci = hose->private_data = ioremap(rsrc.start, resource_size(&rsrc));
> + if (!hose->private_data)
> + goto no_bridge;
> +
> setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
> PPC_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 (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
> /* For PCIE read HEADER_TYPE to identify controler mode */
> early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
> @@ -505,7 +494,7 @@ int __init fsl_add_bridge(struct platform_device *pdev,
> int is_primary) 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, &rsrc))
> + if (fsl_pcie_check_link(hose))
> hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
> }
>
> @@ -522,11 +511,12 @@ int __init fsl_add_bridge(struct platform_device
> *pdev, int is_primary) pci_process_bridge_OF_ranges(hose, dev, is_primary);
>
> /* Setup PEX window registers */
> - setup_pci_atmu(hose, &rsrc);
> + setup_pci_atmu(hose);
>
> 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))
> @@ -703,11 +693,12 @@ static int __init mpc83xx_pcie_setup(struct
> pci_controller *hose, WARN_ON(hose->dn->data);
> hose->dn->data = pcie;
> hose->ops = &mpc83xx_pcie_ops;
> + hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
>
> out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
> out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
>
> - if (fsl_pcie_check_link(hose, NULL))
> + if (fsl_pcie_check_link(hose))
> hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
>
> return 0;
^ permalink raw reply
* Re: [RFC PATCH v2 2/6] powerpc: Exception hooks for context tracking subsystem
From: Li Zhong @ 2013-04-08 9:03 UTC (permalink / raw)
To: Paul Mackerras; +Cc: fweisbec, paulmck, linuxppc-dev, linux-kernel
In-Reply-To: <20130405025025.GB22465@drongo>
On Fri, 2013-04-05 at 13:50 +1100, Paul Mackerras wrote:
> On Fri, Mar 29, 2013 at 06:00:17PM +0800, Li Zhong wrote:
> > This is the exception hooks for context tracking subsystem, including
> > data access, program check, single step, instruction breakpoint, machine check,
> > alignment, fp unavailable, altivec assist, unknown exception, whose handlers
> > might use RCU.
> >
> > This patch corresponds to
> > [PATCH] x86: Exception hooks for userspace RCU extended QS
> > commit 6ba3c97a38803883c2eee489505796cb0a727122
> >
> > Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com>
Hi Paul,
Thanks for your review! Please check my answers below, and correct me if
any errors.
> Is there a reason why you didn't put the exception_exit() call in
> ret_from_except_lite in entry_64.S, and the exception_entry() call in
> EXCEPTION_PROLOG_COMMON? That would seem to catch all these cases in
> a more centralized place.
It seems to me that ret_from_except_lite and EXCEPTION_PROLOG_COMMON are
also used by interrupts, where I think we don't need the hooks. So using
this way could help to avoid adding overhead to these code path
(interrupts, and some exit path of syscall).
And I think adding the hook on higher level code seems a little easier
for reading and checking. It seems that some exceptions don't use
EXCEPTION_PROLOG_COMMON, and some don't go ret_from_except_lite exit
path (like fp unavailable might go directly to fast_exception_return ).
Maybe fast_exception_return is a centralized place for us to return to
user space? But it still adds some overheads which is not necessarily
needed.
And I think it also makes the implementation here consistent with the
style that x86 uses.
> Also, I notice that with the exception_exit calls where they are, we
> can still deliver signals (thus possibly taking a page fault) or call
> schedule() for preemption after the exception_exit() call. Is that
> OK, or is it a potential problem?
If I understand correctly, I guess you are talking about the cases where
we might return to user space without context state correctly being set
as in user?
There is user_enter() called in do_notify_resume() in patch #3, so after
handling the signals we always call user_enter().
There are also some changes of the context_tracking code from Frederic,
which might be related: ( they are now in tip tree, and url of the
patches for your convenience https://lkml.org/lkml/2013/3/1/266 )
6c1e0256fad84a843d915414e4b5973b7443d48d
context_tracking: Restore correct previous context state on exception
exit.
With this patch, if a later exception happened after user_enter(),
before the CPU actually returns to user space, the correct context
state(in user) is saved and restored when handling the later exception.
Patch #6 converts the code to use these new APIs, which is currently not
available in powerpc tree.
b22366cd54c6fe05db426f20adb10f461c19ec06
context_tracking: Restore preempted context state after
preempt_schedule_irq
With this patch, the user context state could be correctly restored
after schedule returns.
Thanks, Zhong
> Paul.
>
^ permalink raw reply
* [PATCH V5] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao @ 2013-04-08 8:26 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: B07421, hongtao.jia
A PCIe erratum of mpc85xx may causes a core hang when a link of PCIe
goes down. when the link goes down, Non-posted transactions issued
via the ATMU requiring completion result in an instruction stall.
At the same time a machine-check exception is generated to the core
to allow further processing by the handler. We implements the handler
which skips the instruction caused the stall.
This patch depends on patch:
powerpc/85xx: Add platform_device declaration to fsl_pci.h
Signed-off-by: Zhao Chenhui <b35336@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Liu Shuo <soniccat.liu@gmail.com>
Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
---
Changes for V4:
* Fill rd with all-Fs if the skipped instruction is load and emulate the
instruction.
* Let KVM/QEMU deal with the exception if the machine check comes from KVM.
arch/powerpc/kernel/cpu_setup_fsl_booke.S | 2 +-
arch/powerpc/kernel/traps.c | 3 +
arch/powerpc/sysdev/fsl_pci.c | 121 ++++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_pci.h | 6 ++
4 files changed, 131 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index dcd8819..f1bde90 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -66,7 +66,7 @@ _GLOBAL(__setup_cpu_e500v2)
bl __e500_icache_setup
bl __e500_dcache_setup
bl __setup_e500_ivors
-#ifdef CONFIG_FSL_RIO
+#if defined(CONFIG_FSL_RIO) || defined(CONFIG_FSL_PCI)
/* Ensure that RFXE is set */
mfspr r3,SPRN_HID1
oris r3,r3,HID1_RFXE@h
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index a008cf5..dd275a4 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -59,6 +59,7 @@
#include <asm/fadump.h>
#include <asm/switch_to.h>
#include <asm/debug.h>
+#include <sysdev/fsl_pci.h>
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
int (*__debugger)(struct pt_regs *regs) __read_mostly;
@@ -556,6 +557,8 @@ int machine_check_e500(struct pt_regs *regs)
if (reason & MCSR_BUS_RBERR) {
if (fsl_rio_mcheck_exception(regs))
return 1;
+ if (fsl_pci_mcheck_exception(regs))
+ return 1;
}
printk("Machine check in kernel mode.\n");
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 682084d..48326cd 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -26,11 +26,14 @@
#include <linux/memblock.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/uaccess.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 <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
@@ -826,6 +829,124 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
return 0;
}
+#ifdef CONFIG_E500
+
+#define OP_LWZ 32
+#define OP_LWZU 33
+#define OP_LBZ 34
+#define OP_LBZU 35
+#define OP_LHZ 40
+#define OP_LHZU 41
+#define OP_LHA 42
+#define OP_LHAU 43
+
+static int mcheck_handle_load(struct pt_regs *regs, u32 inst)
+{
+ unsigned int rd, ra, d;
+
+ rd = get_rt(inst);
+ ra = get_ra(inst);
+ d = get_d(inst);
+
+ switch (get_op(inst)) {
+ case OP_LWZ:
+ regs->gpr[rd] = 0xffffffff;
+ break;
+
+ case OP_LWZU:
+ regs->gpr[rd] = 0xffffffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LBZ:
+ regs->gpr[rd] = 0xff;
+ break;
+
+ case OP_LBZU:
+ regs->gpr[rd] = 0xff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LHZ:
+ regs->gpr[rd] = 0xffff;
+ break;
+
+ case OP_LHZU:
+ regs->gpr[rd] = 0xffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ case OP_LHA:
+ regs->gpr[rd] = 0xffff;
+ break;
+
+ case OP_LHAU:
+ regs->gpr[rd] = 0xffff;
+ regs->gpr[ra] += (s16)d;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int is_in_pci_mem_space(phys_addr_t addr)
+{
+ struct pci_controller *hose;
+ struct resource *res;
+ int i;
+
+ list_for_each_entry(hose, &hose_list, list_node) {
+ if (!early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP))
+ continue;
+
+ for (i = 0; i < 3; i++) {
+ res = &hose->mem_resources[i];
+ if ((res->flags & IORESOURCE_MEM) &&
+ addr >= res->start && addr <= res->end)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int fsl_pci_mcheck_exception(struct pt_regs *regs)
+{
+ u32 inst;
+ int ret;
+ phys_addr_t addr = 0;
+
+ /* Let KVM/QEMU deal with the exception */
+ if (regs->msr & MSR_GS)
+ return 0;
+
+#ifdef CONFIG_PHYS_64BIT
+ addr = mfspr(SPRN_MCARU);
+ addr <<= 32;
+#endif
+ addr += mfspr(SPRN_MCAR);
+
+ if (is_in_pci_mem_space(addr)) {
+ if (user_mode(regs)) {
+ pagefault_disable();
+ ret = get_user(regs->nip, &inst);
+ pagefault_enable();
+ } else {
+ ret = probe_kernel_address(regs->nip, inst);
+ }
+
+ if (mcheck_handle_load(regs, inst)) {
+ regs->nip += 4;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static const struct of_device_id pci_ids[] = {
{ .compatible = "fsl,mpc8540-pci", },
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 851dd56..b0d01ea 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -115,5 +115,11 @@ static inline int mpc85xx_pci_err_probe(struct platform_device *op)
}
#endif
+#ifdef CONFIG_FSL_PCI
+extern int fsl_pci_mcheck_exception(struct pt_regs *);
+#else
+static inline int fsl_pci_mcheck_exception(struct pt_regs *regs) {return 0; }
+#endif
+
#endif /* __POWERPC_FSL_PCI_H */
#endif /* __KERNEL__ */
--
1.8.0
^ permalink raw reply related
* [PATCH] powerpc: remove unused "config 405EP"
From: Paul Bolle @ 2013-04-08 11:27 UTC (permalink / raw)
To: Josh Boyer, Matt Porter, Benjamin Herrenschmidt, Paul Mackerras
Cc: linuxppc-dev, linux-kernel
All users of Kconfig symbol 405EP were removed in release v2.6.27.
Remove this symbol (and a useless select of it) too.
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
---
0) Tested by grepping the tree only.
1) There's also a Kconfig symbol EP405. Let's hope no one ever made a
typo with either of these two symbols!
arch/powerpc/platforms/40x/Kconfig | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index 7b7a77c..bd40bbb 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -20,7 +20,6 @@ config HOTFOOT
bool "Hotfoot"
depends on 40x
default n
- select 405EP
select PPC40x_SIMPLE
select PCI
help
@@ -105,9 +104,6 @@ config 405GP
select IBM405_ERR51
select IBM_EMAC_ZMII
-config 405EP
- bool
-
config 405EX
bool
select IBM_EMAC_EMAC4
--
1.7.11.7
^ permalink raw reply related
* Re: [PATCH] powerpc: remove unused "config 405EP"
From: Josh Boyer @ 2013-04-08 12:13 UTC (permalink / raw)
To: Paul Bolle; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <1365420434.1830.94.camel@x61.thuisdomein>
On Mon, Apr 8, 2013 at 7:27 AM, Paul Bolle <pebolle@tiscali.nl> wrote:
> All users of Kconfig symbol 405EP were removed in release v2.6.27.
> Remove this symbol (and a useless select of it) too.
>
> Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
Acked-by: Josh Boyer <jwboyer@gmail.com>
> ---
> 0) Tested by grepping the tree only.
>
> 1) There's also a Kconfig symbol EP405. Let's hope no one ever made a
> typo with either of these two symbols!
>
> arch/powerpc/platforms/40x/Kconfig | 4 ----
> 1 file changed, 4 deletions(-)
>
> diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
> index 7b7a77c..bd40bbb 100644
> --- a/arch/powerpc/platforms/40x/Kconfig
> +++ b/arch/powerpc/platforms/40x/Kconfig
> @@ -20,7 +20,6 @@ config HOTFOOT
> bool "Hotfoot"
> depends on 40x
> default n
> - select 405EP
> select PPC40x_SIMPLE
> select PCI
> help
> @@ -105,9 +104,6 @@ config 405GP
> select IBM405_ERR51
> select IBM_EMAC_ZMII
>
> -config 405EP
> - bool
> -
> config 405EX
> bool
> select IBM_EMAC_EMAC4
> --
> 1.7.11.7
>
^ permalink raw reply
* [PATCH 2/2] powerpc: Set default VGA device
From: Brian King @ 2013-04-08 13:05 UTC (permalink / raw)
To: linux-pci; +Cc: klebers, brking, lucaskt, bhelgaas, linuxppc-dev
Add a PCI quirk for VGA devices on Power to set the default VGA device.
Ensures a default VGA is always set if a graphics adapter is present,
even if firmware did not initialize it. If more than one graphics
adapter is present, ensure the one initialized by firmware is set
as the default VGA device. This ensures that X autoconfiguration
will work.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---
arch/powerpc/kernel/pci-common.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff -puN arch/powerpc/kernel/pci-common.c~powerpc_vga_default_device arch/powerpc/kernel/pci-common.c
--- linux/arch/powerpc/kernel/pci-common.c~powerpc_vga_default_device 2013-04-08 06:16:37.000000000 -0500
+++ linux-bjking1/arch/powerpc/kernel/pci-common.c 2013-04-08 06:16:37.000000000 -0500
@@ -30,6 +30,7 @@
#include <linux/irq.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/vgaarb.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -1725,3 +1726,15 @@ static void fixup_hide_host_resource_fsl
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl);
+
+static void fixup_vga(struct pci_dev *pdev)
+{
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ if ((cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) || !vga_default_device())
+ vga_set_default_device(pdev);
+
+}
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_DISPLAY_VGA, 8, fixup_vga);
_
^ permalink raw reply
* [PATCH 1/2] pci: Set dev->dev.type in alloc_pci_dev
From: Brian King @ 2013-04-08 13:05 UTC (permalink / raw)
To: linux-pci; +Cc: klebers, brking, lucaskt, bhelgaas, linuxppc-dev
Set dev->dev.type in alloc_pci_dev so that archs that have their own
versions of pci_setup_device get this set properly in order to ensure
things like the boot_vga sysfs parameter get created as expected.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---
drivers/pci/probe.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff -puN drivers/pci/probe.c~pci_set_dev_type_early drivers/pci/probe.c
--- linux/drivers/pci/probe.c~pci_set_dev_type_early 2013-04-08 06:12:51.000000000 -0500
+++ linux-bjking1/drivers/pci/probe.c 2013-04-08 06:14:33.000000000 -0500
@@ -988,7 +988,6 @@ int pci_setup_device(struct pci_dev *dev
dev->sysdata = dev->bus->sysdata;
dev->dev.parent = dev->bus->bridge;
dev->dev.bus = &pci_bus_type;
- dev->dev.type = &pci_dev_type;
dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal;
@@ -1208,6 +1207,7 @@ struct pci_dev *alloc_pci_dev(void)
return NULL;
INIT_LIST_HEAD(&dev->bus_list);
+ dev->dev.type = &pci_dev_type;
return dev;
}
_
^ permalink raw reply
* Re: [PATCH 2/3] powerpc: Enable boot_vga sysfs attribute for graphics adapters on Power
From: Brian King @ 2013-04-08 13:07 UTC (permalink / raw)
To: Michael Ellerman
Cc: linux-pci@vger.kernel.org, klebers, sparclinux,
Lucas Kannebley Tavares, Bjorn Helgaas, linuxppc-dev
In-Reply-To: <20130408052522.GB9550@concordia>
On 04/08/2013 12:25 AM, Michael Ellerman wrote:
> On Fri, Apr 05, 2013 at 02:11:01PM -0600, Bjorn Helgaas wrote:
>> On Thu, Apr 4, 2013 at 3:58 PM, Brian King <brking@linux.vnet.ibm.com> wrote:
>>>
>>> Initialize dev->dev.type such that the PCI group attributes for boot_vga
>>> and SR-IOV can be displayed if appropriate. This fixes an issue seen on
>>> Power preventing X from auto initializing a graphics adapter when using KMS.
>>>
>>> Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
>>> ---
>>>
>>> arch/powerpc/kernel/pci_of_scan.c | 1 +
>>> 1 file changed, 1 insertion(+)
>>>
>>> diff -puN arch/powerpc/kernel/pci_of_scan.c~powerpc_set_pci_dev_type arch/powerpc/kernel/pci_of_scan.c
>>> --- linux/arch/powerpc/kernel/pci_of_scan.c~powerpc_set_pci_dev_type 2013-04-03 09:43:19.000000000 -0500
>>> +++ linux-bjking1/arch/powerpc/kernel/pci_of_scan.c 2013-04-03 09:43:19.000000000 -0500
>>> @@ -141,6 +141,7 @@ struct pci_dev *of_create_pci_dev(struct
>>> dev->dev.of_node = of_node_get(node);
>>> dev->dev.parent = bus->bridge;
>>> dev->dev.bus = &pci_bus_type;
>>> + dev->dev.type = &pci_dev_type;
>>> dev->devfn = devfn;
>>> dev->multifunction = 0; /* maybe a lie? */
>>> dev->needs_freset = 0; /* pcie fundamental reset required */
>>
>> I think sparc has the same issue in its own copy of of_create_pci_dev().
>>
>> Of course, both of_create_pci_dev() implementations are basically
>> copies of the generic pci_setup_device() that most arches use. That's
>> the reason why I wish sparc and powerpc had used config space
>> accessors that hid the OF mangling internally so they could use the
>> generic pci_setup_device() instead of cloning it.
>>
>> Of course, they don't, and that's too much work for fixing this issue,
>> but if anybody wanted to work on that, I think it would be an
>> interesting project.
>>
>> But what if you set dev->dev.type in alloc_pci_dev()? I think if you
>> did that, you wouldn't need to export "pci_dev_type," and it should
>> fix this for both powerpc and sparc.
>
> That sounds good, Brian can you confirm that works and send a new series
> using that technique.
It does indeed work. I've sent a new series using this technique.
Thanks,
Brian
--
Brian King
Power Linux I/O
IBM Linux Technology Center
^ permalink raw reply
* Re: [PATCH] [RFC] powerpc: Add VDSO version of time
From: Adhemerval Zanella @ 2013-04-08 14:05 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20130405062137.GA5082@concordia>
On 04/05/2013 03:21 AM, Michael Ellerman wrote:
> On Tue, Mar 19, 2013 at 04:55:31PM -0300, Adhemerval Zanella wrote:
>> Hi all,
>>
>> This patch implement the time syscall as vDSO. I have a glibc patch
>> to use it as IFUNC (as latest gettimeofday patch). Below the perf
>> numbers:
>>
>> Baseline PPC32: 380 nsec
>> Baseline PPC64: 352 nsec
>> vdso PPC32: 20 nsec
>> vdso PPC64: 20 nsec
>>
>> I focused on 64 bit kernel, do I need to provide a scheme for 32 bits
>> as well?
> You did provide a 32-bit implementation. I take it you haven't tested
> that though? Can you test it?
Hi,
I didn't build a 32 bit kernel, but I tested 32 bits binaries (that uses
the VDSO32 implantation) without any issue. Performance gains are similar.
^ permalink raw reply
* Re: [PATCH 1/2] pci: Set dev->dev.type in alloc_pci_dev
From: Bjorn Helgaas @ 2013-04-08 17:20 UTC (permalink / raw)
To: Brian King
Cc: klebers, linux-pci@vger.kernel.org, Lucas Kannebley Tavares,
linuxppc-dev
In-Reply-To: <201304081305.r38D5765032748@d01av04.pok.ibm.com>
On Mon, Apr 8, 2013 at 7:05 AM, Brian King <brking@linux.vnet.ibm.com> wrote:
>
> Set dev->dev.type in alloc_pci_dev so that archs that have their own
> versions of pci_setup_device get this set properly in order to ensure
> things like the boot_vga sysfs parameter get created as expected.
>
> Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Feel free to put this in the powerpc tree along with the "set default
VGA device" patch.
> ---
>
> drivers/pci/probe.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff -puN drivers/pci/probe.c~pci_set_dev_type_early drivers/pci/probe.c
> --- linux/drivers/pci/probe.c~pci_set_dev_type_early 2013-04-08 06:12:51.000000000 -0500
> +++ linux-bjking1/drivers/pci/probe.c 2013-04-08 06:14:33.000000000 -0500
> @@ -988,7 +988,6 @@ int pci_setup_device(struct pci_dev *dev
> dev->sysdata = dev->bus->sysdata;
> dev->dev.parent = dev->bus->bridge;
> dev->dev.bus = &pci_bus_type;
> - dev->dev.type = &pci_dev_type;
> dev->hdr_type = hdr_type & 0x7f;
> dev->multifunction = !!(hdr_type & 0x80);
> dev->error_state = pci_channel_io_normal;
> @@ -1208,6 +1207,7 @@ struct pci_dev *alloc_pci_dev(void)
> return NULL;
>
> INIT_LIST_HEAD(&dev->bus_list);
> + dev->dev.type = &pci_dev_type;
>
> return dev;
> }
> _
>
^ permalink raw reply
* Re: [PATCH] powerpc: add Book E support to 64-bit hibernation
From: Scott Wood @ 2013-04-08 18:24 UTC (permalink / raw)
To: Wang Dongsheng-B40534
Cc: Wood Scott-B07421, Johannes Berg, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <ABB05CD9C9F68C46A5CEDC7F15439259EDDCAE@039-SN2MPN1-021.039d.mgd.msft.net>
On 04/06/2013 10:01:45 PM, Wang Dongsheng-B40534 wrote:
>=20
>=20
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Thursday, April 04, 2013 4:16 AM
> > To: Wang Dongsheng-B40534
> > Cc: Wood Scott-B07421; Johannes Berg; linuxppc-dev@lists.ozlabs.org
> > Subject: Re: [PATCH] powerpc: add Book E support to 64-bit =20
> hibernation
> >
> > On 04/03/2013 12:36:41 AM, Wang Dongsheng-B40534 wrote:
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wood Scott-B07421
> > > > Sent: Wednesday, April 03, 2013 8:35 AM
> > > > To: Wang Dongsheng-B40534
> > > > Cc: Wood Scott-B07421; Johannes Berg; =20
> linuxppc-dev@lists.ozlabs.org
> > > > Subject: Re: [PATCH] powerpc: add Book E support to 64-bit
> > > hibernation
> > > >
> > > > On 04/02/2013 12:28:40 AM, Wang Dongsheng-B40534 wrote:
> > > > > Hi scott & Johannes,
> > > > >
> > > > > Thanks for reviewing.
> > > > >
> > > > > @scott, About this patch, could you please help ack this =20
> patch?
> > > >
> > > > Please investigate the issue of whether we are loading kernel =20
> module
> > > > code in this step, and whether cache flushing is needed as a =20
> result.
> > > >
> > > Sorry, I am not very clear what you mean.
> > > When the kernel boot end, modprobe some xx.ko?
> >
> > Suppose, before the kernel was suspended, modules had been loaded. =20
> At
> > what point do those modules get restored, and when does the cache =20
> get
> > flushed?
> >
> Before the kernel was suspended, modules had been loaded, the modules =20
> is
> already in memory.
They *were* in memory, until the hardware was powered down.
> And /lib/modules/* is belong to vfs.
Huh? I'm talking about modules that have been loaded, not where in the =20
filesystem they were loaded from. Loading a module is not like =20
mmap()ing a file.
> When suspend to disk, all used pages will be saved.(Include VFS, =20
> Loaded modules)
> When restore, the kernel will not modprobe again.
Of course it won't modprobe again. Still, at some point during the =20
resume process, the code has to be loaded from disk into RAM. What I =20
don't know is if this is where that happens.
> The non-bootcpu will restore all pages.(Include VFS, Loaded modules)
I don't know what "non-bootcpu" has to do with anything. What matters =20
is what piece of code does the restoring, and if the cache flush =20
properly happens then.
-Scott=
^ permalink raw reply
* [PATCH] powerpc: remove "config MPC10X_OPENPIC"
From: Paul Bolle @ 2013-04-08 19:35 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras; +Cc: linuxppc-dev, linux-kernel
The last users of Kconfig symbol MPC10X_OPENPIC were removed in v2.6.27.
Its Kconfig entry can be removed now.
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
---
Untested.
arch/powerpc/platforms/embedded6xx/Kconfig | 5 -----
1 file changed, 5 deletions(-)
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 5a8f50a9..302ba43 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -9,7 +9,6 @@ config LINKSTATION
select FSL_SOC
select PPC_UDBG_16550 if SERIAL_8250
select DEFAULT_UIMAGE
- select MPC10X_OPENPIC
select MPC10X_BRIDGE
help
Select LINKSTATION if configuring for one of PPC- (MPC8241)
@@ -24,7 +23,6 @@ config STORCENTER
select MPIC
select FSL_SOC
select PPC_UDBG_16550 if SERIAL_8250
- select MPC10X_OPENPIC
select MPC10X_BRIDGE
help
Select STORCENTER if configuring for the iomega StorCenter
@@ -84,9 +82,6 @@ config MV64X60
select PPC_INDIRECT_PCI
select CHECK_CACHE_COHERENCY
-config MPC10X_OPENPIC
- bool
-
config GAMECUBE_COMMON
bool
--
1.7.11.7
^ permalink raw reply related
* [PATCH v3 1/4] powerpc/mpic: add irq_set_wake support
From: Wang Dongsheng @ 2013-04-09 2:22 UTC (permalink / raw)
To: scottwood; +Cc: linuxppc-dev, Wang Dongsheng
Add irq_set_wake support. Just add IRQF_NO_SUSPEND to desc->action->flag.
So the wake up interrupt will not be disable in suspend_device_irqs.
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
---
v3:
* Modify: Change "EINVAL" to "ENXIO" in mpic_irq_set_wake()
v2:
* Add: Check freescale chip in mpic_irq_set_wake().
* Remove: Support mpic_irq_set_wake() in ht_chip.
arch/powerpc/sysdev/mpic.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 3b2efd4..ae709d2 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -920,6 +920,22 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
return IRQ_SET_MASK_OK_NOCOPY;
}
+static int mpic_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ struct irq_desc *desc = container_of(d, struct irq_desc, irq_data);
+ struct mpic *mpic = mpic_from_irq_data(d);
+
+ if (!(mpic->flags & MPIC_FSL))
+ return -ENXIO;
+
+ if (on)
+ desc->action->flags |= IRQF_NO_SUSPEND;
+ else
+ desc->action->flags &= ~IRQF_NO_SUSPEND;
+
+ return 0;
+}
+
void mpic_set_vector(unsigned int virq, unsigned int vector)
{
struct mpic *mpic = mpic_from_irq(virq);
@@ -957,6 +973,7 @@ static struct irq_chip mpic_irq_chip = {
.irq_unmask = mpic_unmask_irq,
.irq_eoi = mpic_end_irq,
.irq_set_type = mpic_set_irq_type,
+ .irq_set_wake = mpic_irq_set_wake,
};
#ifdef CONFIG_SMP
@@ -971,6 +988,7 @@ static struct irq_chip mpic_tm_chip = {
.irq_mask = mpic_mask_tm,
.irq_unmask = mpic_unmask_tm,
.irq_eoi = mpic_end_irq,
+ .irq_set_wake = mpic_irq_set_wake,
};
#ifdef CONFIG_MPIC_U3_HT_IRQS
--
1.8.0
^ permalink raw reply related
* [PATCH v3 2/4] powerpc/mpic: add global timer support
From: Wang Dongsheng @ 2013-04-09 2:22 UTC (permalink / raw)
To: scottwood; +Cc: linuxppc-dev, Wang Dongsheng
In-Reply-To: <1365474152-21524-1-git-send-email-dongsheng.wang@freescale.com>
The MPIC global timer is a hardware timer inside the Freescale PIC complying
with OpenPIC standard. When the specified interval times out, the hardware
timer generates an interrupt. The driver currently is only tested on fsl chip,
but it can potentially support other global timers complying to OpenPIC
standard.
The two independent groups of global timer on fsl chip, group A and group B,
are identical in their functionality, except that they appear at different
locations within the PIC register map. The hardware timer can be cascaded to
create timers larger than the default 31-bit global timers. Timer cascade
fields allow configuration of up to two 63-bit timers. But These two groups
of timers cannot be cascaded together.
It can be used as a wakeup source for low power modes. It also could be used
as periodical timer for protocols, drivers and etc.
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
v2:
* Modify: Set timer clock frequency in timer_group_get_freq().
* Modify: Change some of the comments.
arch/powerpc/include/asm/mpic_timer.h | 46 +++
arch/powerpc/platforms/Kconfig | 12 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/mpic_timer.c | 593 ++++++++++++++++++++++++++++++++++
4 files changed, 652 insertions(+)
create mode 100644 arch/powerpc/include/asm/mpic_timer.h
create mode 100644 arch/powerpc/sysdev/mpic_timer.c
diff --git a/arch/powerpc/include/asm/mpic_timer.h b/arch/powerpc/include/asm/mpic_timer.h
new file mode 100644
index 0000000..0e23cd4
--- /dev/null
+++ b/arch/powerpc/include/asm/mpic_timer.h
@@ -0,0 +1,46 @@
+/*
+ * arch/powerpc/include/asm/mpic_timer.h
+ *
+ * Header file for Mpic Global Timer
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Wang Dongsheng <Dongsheng.Wang@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MPIC_TIMER__
+#define __MPIC_TIMER__
+
+#include <linux/interrupt.h>
+#include <linux/time.h>
+
+struct mpic_timer {
+ void *dev;
+ struct cascade_priv *cascade_handle;
+ unsigned int num;
+ unsigned int irq;
+};
+
+#ifdef CONFIG_MPIC_TIMER
+struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,
+ const struct timeval *time);
+void mpic_start_timer(struct mpic_timer *handle);
+void mpic_stop_timer(struct mpic_timer *handle);
+void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time);
+void mpic_free_timer(struct mpic_timer *handle);
+#else
+struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,
+ const struct timeval *time) { return NULL; }
+void mpic_start_timer(struct mpic_timer *handle) { }
+void mpic_stop_timer(struct mpic_timer *handle) { }
+void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time) { }
+void mpic_free_timer(struct mpic_timer *handle) { }
+#endif
+
+#endif
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 48a920d..c447b3c 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -87,6 +87,18 @@ config MPIC
bool
default n
+config MPIC_TIMER
+ bool "MPIC Global Timer"
+ depends on MPIC && FSL_SOC
+ default n
+ help
+ The MPIC global timer is a hardware timer inside the
+ Freescale PIC complying with OpenPIC standard. When the
+ specified interval times out, the hardware timer generates
+ an interrupt. The driver currently is only tested on fsl
+ chip, but it can potentially support other global timers
+ complying with the OpenPIC standard.
+
config PPC_EPAPR_HV_PIC
bool
default n
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index a57600b..ff6184a 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
+obj-$(CONFIG_MPIC_TIMER) += mpic_timer.o
mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y)
obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o
diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
new file mode 100644
index 0000000..c06db92
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -0,0 +1,593 @@
+/*
+ * MPIC timer driver
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ * Author: Dongsheng Wang <Dongsheng.Wang@freescale.com>
+ * Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/syscore_ops.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/io.h>
+
+#include <asm/mpic_timer.h>
+
+#define FSL_GLOBAL_TIMER 0x1
+
+/* Clock Ratio
+ * Divide by 64 0x00000300
+ * Divide by 32 0x00000200
+ * Divide by 16 0x00000100
+ * Divide by 8 0x00000000 (Hardware default div)
+ */
+#define MPIC_TIMER_TCR_CLKDIV 0x00000300
+
+#define MPIC_TIMER_TCR_ROVR_OFFSET 24
+
+#define TIMER_STOP 0x80000000
+#define TIMERS_PER_GROUP 4
+#define MAX_TICKS (~0U >> 1)
+#define MAX_TICKS_CASCADE (~0U)
+#define TIMER_OFFSET(num) (1 << (TIMERS_PER_GROUP - 1 - num))
+
+/* tv_usec should be less than ONE_SECOND, otherwise use tv_sec */
+#define ONE_SECOND 1000000
+
+struct timer_regs {
+ u32 gtccr;
+ u32 res0[3];
+ u32 gtbcr;
+ u32 res1[3];
+ u32 gtvpr;
+ u32 res2[3];
+ u32 gtdr;
+ u32 res3[3];
+};
+
+struct cascade_priv {
+ u32 tcr_value; /* TCR register: CASC & ROVR value */
+ unsigned int cascade_map; /* cascade map */
+ unsigned int timer_num; /* cascade control timer */
+};
+
+struct timer_group_priv {
+ struct timer_regs __iomem *regs;
+ struct mpic_timer timer[TIMERS_PER_GROUP];
+ struct list_head node;
+ unsigned int timerfreq;
+ unsigned int idle;
+ unsigned int flags;
+ spinlock_t lock;
+ void __iomem *group_tcr;
+};
+
+static struct cascade_priv cascade_timer[] = {
+ /* cascade timer 0 and 1 */
+ {0x1, 0xc, 0x1},
+ /* cascade timer 1 and 2 */
+ {0x2, 0x6, 0x2},
+ /* cascade timer 2 and 3 */
+ {0x4, 0x3, 0x3}
+};
+
+static LIST_HEAD(timer_group_list);
+
+static void convert_ticks_to_time(struct timer_group_priv *priv,
+ const u64 ticks, struct timeval *time)
+{
+ u64 tmp_sec;
+
+ time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq);
+ tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
+
+ time->tv_usec = (__kernel_suseconds_t)
+ div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
+
+ return;
+}
+
+/* the time set by the user is converted to "ticks" */
+static int convert_time_to_ticks(struct timer_group_priv *priv,
+ const struct timeval *time, u64 *ticks)
+{
+ u64 max_value; /* prevent u64 overflow */
+ u64 tmp = 0;
+
+ u64 tmp_sec;
+ u64 tmp_ms;
+ u64 tmp_us;
+
+ max_value = div_u64(ULLONG_MAX, priv->timerfreq);
+
+ if (time->tv_sec > max_value ||
+ (time->tv_sec == max_value && time->tv_usec > 0))
+ return -EINVAL;
+
+ tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
+ tmp += tmp_sec;
+
+ tmp_ms = time->tv_usec / 1000;
+ tmp_ms = div_u64((u64)tmp_ms * (u64)priv->timerfreq, 1000);
+ tmp += tmp_ms;
+
+ tmp_us = time->tv_usec % 1000;
+ tmp_us = div_u64((u64)tmp_us * (u64)priv->timerfreq, 1000000);
+ tmp += tmp_us;
+
+ *ticks = tmp;
+
+ return 0;
+}
+
+/* detect whether there is a cascade timer available */
+static struct mpic_timer *detect_idle_cascade_timer(
+ struct timer_group_priv *priv)
+{
+ struct cascade_priv *casc_priv;
+ unsigned int map;
+ unsigned int array_size = ARRAY_SIZE(cascade_timer);
+ unsigned int num;
+ unsigned int i;
+ unsigned long flags;
+
+ casc_priv = cascade_timer;
+ for (i = 0; i < array_size; i++) {
+ spin_lock_irqsave(&priv->lock, flags);
+ map = casc_priv->cascade_map & priv->idle;
+ if (map == casc_priv->cascade_map) {
+ num = casc_priv->timer_num;
+ priv->timer[num].cascade_handle = casc_priv;
+
+ /* set timer busy */
+ priv->idle &= ~casc_priv->cascade_map;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return &priv->timer[num];
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ casc_priv++;
+ }
+
+ return NULL;
+}
+
+static int set_cascade_timer(struct timer_group_priv *priv, u64 ticks,
+ unsigned int num)
+{
+ struct cascade_priv *casc_priv;
+ u32 tcr;
+ u32 tmp_ticks;
+ u32 rem_ticks;
+
+ /* set group tcr reg for cascade */
+ casc_priv = priv->timer[num].cascade_handle;
+ if (!casc_priv)
+ return -EINVAL;
+
+ tcr = casc_priv->tcr_value |
+ (casc_priv->tcr_value << MPIC_TIMER_TCR_ROVR_OFFSET);
+ setbits32(priv->group_tcr, tcr);
+
+ tmp_ticks = div_u64_rem(ticks, MAX_TICKS_CASCADE, &rem_ticks);
+
+ out_be32(&priv->regs[num].gtccr, 0);
+ out_be32(&priv->regs[num].gtbcr, tmp_ticks | TIMER_STOP);
+
+ out_be32(&priv->regs[num - 1].gtccr, 0);
+ out_be32(&priv->regs[num - 1].gtbcr, rem_ticks);
+
+ return 0;
+}
+
+static struct mpic_timer *get_cascade_timer(struct timer_group_priv *priv,
+ u64 ticks)
+{
+ struct mpic_timer *allocated_timer;
+
+ /* Two cascade timers: Support the maximum time */
+ const u64 max_ticks = (u64)MAX_TICKS * (u64)MAX_TICKS_CASCADE;
+ int ret;
+
+ if (ticks > max_ticks)
+ return NULL;
+
+ /* detect idle timer */
+ allocated_timer = detect_idle_cascade_timer(priv);
+ if (!allocated_timer)
+ return NULL;
+
+ /* set ticks to timer */
+ ret = set_cascade_timer(priv, ticks, allocated_timer->num);
+ if (ret < 0)
+ return NULL;
+
+ return allocated_timer;
+}
+
+static struct mpic_timer *get_timer(const struct timeval *time)
+{
+ struct timer_group_priv *priv;
+ struct mpic_timer *timer;
+
+ u64 ticks;
+ unsigned int num;
+ unsigned int i;
+ unsigned long flags;
+ int ret;
+
+ list_for_each_entry(priv, &timer_group_list, node) {
+ ret = convert_time_to_ticks(priv, time, &ticks);
+ if (ret < 0)
+ return NULL;
+
+ if (ticks > MAX_TICKS) {
+ if (!(priv->flags & FSL_GLOBAL_TIMER))
+ return NULL;
+
+ timer = get_cascade_timer(priv, ticks);
+ if (!timer)
+ continue;
+
+ return timer;
+ }
+
+ for (i = 0; i < TIMERS_PER_GROUP; i++) {
+ /* one timer: Reverse allocation */
+ num = TIMERS_PER_GROUP - 1 - i;
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->idle & (1 << i)) {
+ /* set timer busy */
+ priv->idle &= ~(1 << i);
+ /* set ticks & stop timer */
+ out_be32(&priv->regs[num].gtbcr,
+ ticks | TIMER_STOP);
+ out_be32(&priv->regs[num].gtccr, 0);
+ priv->timer[num].cascade_handle = NULL;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return &priv->timer[num];
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * mpic_start_timer - start hardware timer
+ * @handle: the timer to be started.
+ *
+ * It will do ->fn(->dev) callback from the hardware interrupt at
+ * the ->timeval point in the future.
+ */
+void mpic_start_timer(struct mpic_timer *handle)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+
+ clrbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+}
+EXPORT_SYMBOL(mpic_start_timer);
+
+/**
+ * mpic_stop_timer - stop hardware timer
+ * @handle: the timer to be stoped
+ *
+ * The timer periodically generates an interrupt. Unless user stops the timer.
+ */
+void mpic_stop_timer(struct mpic_timer *handle)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+ struct cascade_priv *casc_priv;
+
+ setbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+
+ casc_priv = priv->timer[handle->num].cascade_handle;
+ if (casc_priv) {
+ out_be32(&priv->regs[handle->num].gtccr, 0);
+ out_be32(&priv->regs[handle->num - 1].gtccr, 0);
+ } else {
+ out_be32(&priv->regs[handle->num].gtccr, 0);
+ }
+}
+EXPORT_SYMBOL(mpic_stop_timer);
+
+/**
+ * mpic_get_remain_time - get timer time
+ * @handle: the timer to be selected.
+ * @time: time for timer
+ *
+ * Query timer remaining time.
+ */
+void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+ struct cascade_priv *casc_priv;
+
+ u64 ticks;
+ u32 tmp_ticks;
+
+ casc_priv = priv->timer[handle->num].cascade_handle;
+ if (casc_priv) {
+ tmp_ticks = in_be32(&priv->regs[handle->num].gtccr);
+ ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE;
+ tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtccr);
+ ticks += tmp_ticks;
+ } else {
+ ticks = in_be32(&priv->regs[handle->num].gtccr);
+ }
+
+ convert_ticks_to_time(priv, ticks, time);
+}
+EXPORT_SYMBOL(mpic_get_remain_time);
+
+/**
+ * mpic_free_timer - free hardware timer
+ * @handle: the timer to be removed.
+ *
+ * Free the timer.
+ *
+ * Note: can not be used in interrupt context.
+ */
+void mpic_free_timer(struct mpic_timer *handle)
+{
+ struct timer_group_priv *priv = container_of(handle,
+ struct timer_group_priv, timer[handle->num]);
+
+ struct cascade_priv *casc_priv;
+ unsigned long flags;
+
+ mpic_stop_timer(handle);
+
+ casc_priv = priv->timer[handle->num].cascade_handle;
+
+ free_irq(priv->timer[handle->num].irq, priv->timer[handle->num].dev);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (casc_priv) {
+ u32 tcr;
+ tcr = casc_priv->tcr_value | (casc_priv->tcr_value <<
+ MPIC_TIMER_TCR_ROVR_OFFSET);
+ clrbits32(priv->group_tcr, tcr);
+ priv->idle |= casc_priv->cascade_map;
+ priv->timer[handle->num].cascade_handle = NULL;
+ } else {
+ priv->idle |= TIMER_OFFSET(handle->num);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+EXPORT_SYMBOL(mpic_free_timer);
+
+/**
+ * mpic_request_timer - get a hardware timer
+ * @fn: interrupt handler function
+ * @dev: callback function of the data
+ * @time: time for timer
+ *
+ * This executes the "request_irq", returning NULL
+ * else "handle" on success.
+ */
+struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,
+ const struct timeval *time)
+{
+ struct mpic_timer *allocated_timer;
+ int ret;
+
+ if (list_empty(&timer_group_list))
+ return NULL;
+
+ if (!(time->tv_sec + time->tv_usec) ||
+ time->tv_sec < 0 || time->tv_usec < 0)
+ return NULL;
+
+ if (time->tv_usec > ONE_SECOND)
+ return NULL;
+
+ allocated_timer = get_timer(time);
+ if (!allocated_timer)
+ return NULL;
+
+ ret = request_irq(allocated_timer->irq, fn,
+ IRQF_TRIGGER_LOW, "global-timer", dev);
+ if (ret) {
+ mpic_free_timer(allocated_timer);
+ return NULL;
+ }
+
+ allocated_timer->dev = dev;
+
+ return allocated_timer;
+}
+EXPORT_SYMBOL(mpic_request_timer);
+
+static int timer_group_get_freq(struct device_node *np,
+ struct timer_group_priv *priv)
+{
+ u32 div;
+
+ if (priv->flags & FSL_GLOBAL_TIMER) {
+ struct device_node *dn;
+
+ dn = of_find_compatible_node(NULL, NULL, "fsl,mpic");
+ if (dn) {
+ of_property_read_u32(dn, "clock-frequency",
+ &priv->timerfreq);
+ of_node_put(dn);
+ }
+ }
+
+ if (priv->timerfreq <= 0)
+ return -EINVAL;
+
+ if (priv->flags & FSL_GLOBAL_TIMER) {
+ div = (1 << (MPIC_TIMER_TCR_CLKDIV >> 8)) * 8;
+ priv->timerfreq /= div;
+ }
+
+ return 0;
+}
+
+static int timer_group_get_irq(struct device_node *np,
+ struct timer_group_priv *priv)
+{
+ const u32 all_timer[] = { 0, TIMERS_PER_GROUP };
+ const u32 *p;
+ u32 offset;
+ u32 count;
+
+ unsigned int i;
+ unsigned int j;
+ unsigned int irq_index = 0;
+ unsigned int irq;
+ int len;
+
+ p = of_get_property(np, "fsl,available-ranges", &len);
+ if (p && len % (2 * sizeof(u32)) != 0) {
+ pr_err("%s: malformed available-ranges property.\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ if (!p) {
+ p = all_timer;
+ len = sizeof(all_timer);
+ }
+
+ len /= 2 * sizeof(u32);
+
+ for (i = 0; i < len; i++) {
+ offset = p[i * 2];
+ count = p[i * 2 + 1];
+ for (j = 0; j < count; j++) {
+ irq = irq_of_parse_and_map(np, irq_index);
+ if (!irq) {
+ pr_err("%s: irq parse and map failed.\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ /* Set timer idle */
+ priv->idle |= TIMER_OFFSET((offset + j));
+ priv->timer[offset + j].irq = irq;
+ priv->timer[offset + j].num = offset + j;
+ irq_index++;
+ }
+ }
+
+ return 0;
+}
+
+static void timer_group_init(struct device_node *np)
+{
+ struct timer_group_priv *priv;
+ unsigned int i = 0;
+ int ret;
+
+ priv = kzalloc(sizeof(struct timer_group_priv), GFP_KERNEL);
+ if (!priv) {
+ pr_err("%s: cannot allocate memory for group.\n",
+ np->full_name);
+ return;
+ }
+
+ if (of_device_is_compatible(np, "fsl,mpic-global-timer"))
+ priv->flags |= FSL_GLOBAL_TIMER;
+
+ priv->regs = of_iomap(np, i++);
+ if (!priv->regs) {
+ pr_err("%s: cannot ioremap timer register address.\n",
+ np->full_name);
+ goto out;
+ }
+
+ if (priv->flags & FSL_GLOBAL_TIMER) {
+ priv->group_tcr = of_iomap(np, i++);
+ if (!priv->group_tcr) {
+ pr_err("%s: cannot ioremap tcr address.\n",
+ np->full_name);
+ goto out;
+ }
+ }
+
+ ret = timer_group_get_freq(np, priv);
+ if (ret < 0) {
+ pr_err("%s: cannot get timer frequency.\n", np->full_name);
+ goto out;
+ }
+
+ ret = timer_group_get_irq(np, priv);
+ if (ret < 0) {
+ pr_err("%s: cannot get timer irqs.\n", np->full_name);
+ goto out;
+ }
+
+ spin_lock_init(&priv->lock);
+
+ /* Init FSL timer hardware */
+ if (priv->flags & FSL_GLOBAL_TIMER)
+ setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV);
+
+ list_add_tail(&priv->node, &timer_group_list);
+
+ return;
+
+out:
+ if (priv->regs)
+ iounmap(priv->regs);
+
+ if (priv->group_tcr)
+ iounmap(priv->group_tcr);
+
+ kfree(priv);
+}
+
+static void mpic_timer_resume(void)
+{
+ struct timer_group_priv *priv;
+
+ list_for_each_entry(priv, &timer_group_list, node) {
+ /* Init FSL timer hardware */
+ if (priv->flags & FSL_GLOBAL_TIMER)
+ setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV);
+ }
+}
+
+static const struct of_device_id mpic_timer_ids[] = {
+ { .compatible = "fsl,mpic-global-timer", },
+ {},
+};
+
+static struct syscore_ops mpic_timer_syscore_ops = {
+ .resume = mpic_timer_resume,
+};
+
+static int __init mpic_timer_init(void)
+{
+ struct device_node *np = NULL;
+
+ for_each_matching_node(np, mpic_timer_ids)
+ timer_group_init(np);
+
+ register_syscore_ops(&mpic_timer_syscore_ops);
+
+ if (list_empty(&timer_group_list))
+ return -ENODEV;
+
+ return 0;
+}
+subsys_initcall(mpic_timer_init);
--
1.8.0
^ permalink raw reply related
* [PATCH v3 3/4] powerpc/mpic: create mpic subsystem object
From: Wang Dongsheng @ 2013-04-09 2:22 UTC (permalink / raw)
To: scottwood; +Cc: linuxppc-dev, Wang Dongsheng
In-Reply-To: <1365474152-21524-1-git-send-email-dongsheng.wang@freescale.com>
Register a mpic subsystem at /sys/devices/system/
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
---
arch/powerpc/include/asm/mpic.h | 2 ++
arch/powerpc/sysdev/mpic.c | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index c0f9ef9..fa70e9b 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -339,6 +339,8 @@ struct mpic
#endif
};
+extern struct bus_type mpic_subsys;
+
/*
* MPIC flags (passed to mpic_alloc)
*
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index ae709d2..58e7661 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -48,6 +48,12 @@
#define DBG(fmt...)
#endif
+struct bus_type mpic_subsys = {
+ .name = "mpic",
+ .dev_name = "mpic",
+};
+EXPORT_SYMBOL_GPL(mpic_subsys);
+
static struct mpic *mpics;
static struct mpic *mpic_primary;
static DEFINE_RAW_SPINLOCK(mpic_lock);
@@ -1989,6 +1995,8 @@ static struct syscore_ops mpic_syscore_ops = {
static int mpic_init_sys(void)
{
register_syscore_ops(&mpic_syscore_ops);
+ subsys_system_register(&mpic_subsys, NULL);
+
return 0;
}
--
1.8.0
^ permalink raw reply related
* [PATCH v3 4/4] powerpc/fsl: add MPIC timer wakeup support
From: Wang Dongsheng @ 2013-04-09 2:22 UTC (permalink / raw)
To: scottwood; +Cc: linuxppc-dev, Wang Dongsheng, Zhao Chenhui
In-Reply-To: <1365474152-21524-1-git-send-email-dongsheng.wang@freescale.com>
The driver provides a way to wake up the system by the MPIC timer.
For example,
echo 5 > /sys/devices/system/mpic/timer_wakeup
echo standby > /sys/power/state
After 5 seconds the MPIC timer will generate an interrupt to wake up
the system.
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
v2:
* Remove: Create mpic subsystem.
arch/powerpc/platforms/Kconfig | 9 ++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c | 161 ++++++++++++++++++++++++++++
3 files changed, 171 insertions(+)
create mode 100644 arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index c447b3c..3d934ba 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -99,6 +99,15 @@ config MPIC_TIMER
chip, but it can potentially support other global timers
complying with the OpenPIC standard.
+config FSL_MPIC_TIMER_WAKEUP
+ tristate "Freescale MPIC global timer wakeup driver"
+ depends on FSL_SOC && MPIC_TIMER && PM
+ default n
+ help
+ The driver provides a way to wake up the system by MPIC
+ timer.
+ e.g. "echo 5 > /sys/devices/system/mpic/timer_wakeup"
+
config PPC_EPAPR_HV_PIC
bool
default n
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index ff6184a..e1b8a80 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
obj-$(CONFIG_MPIC_TIMER) += mpic_timer.o
+obj-$(CONFIG_FSL_MPIC_TIMER_WAKEUP) += fsl_mpic_timer_wakeup.o
mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o
obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y)
obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o
diff --git a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
new file mode 100644
index 0000000..1707bf0
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
@@ -0,0 +1,161 @@
+/*
+ * MPIC timer wakeup driver
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <asm/mpic_timer.h>
+#include <asm/mpic.h>
+
+struct fsl_mpic_timer_wakeup {
+ struct mpic_timer *timer;
+ struct work_struct free_work;
+};
+
+static struct fsl_mpic_timer_wakeup *fsl_wakeup;
+static DEFINE_MUTEX(sysfs_lock);
+
+static void fsl_free_resource(struct work_struct *ws)
+{
+ struct fsl_mpic_timer_wakeup *wakeup =
+ container_of(ws, struct fsl_mpic_timer_wakeup, free_work);
+
+ mutex_lock(&sysfs_lock);
+
+ if (wakeup->timer) {
+ disable_irq_wake(wakeup->timer->irq);
+ mpic_free_timer(wakeup->timer);
+ }
+
+ wakeup->timer = NULL;
+ mutex_unlock(&sysfs_lock);
+}
+
+static irqreturn_t fsl_mpic_timer_irq(int irq, void *dev_id)
+{
+ struct fsl_mpic_timer_wakeup *wakeup = dev_id;
+
+ schedule_work(&wakeup->free_work);
+
+ return wakeup->timer ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static ssize_t fsl_timer_wakeup_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct timeval interval;
+ int val = 0;
+
+ mutex_lock(&sysfs_lock);
+ if (fsl_wakeup->timer) {
+ mpic_get_remain_time(fsl_wakeup->timer, &interval);
+ val = interval.tv_sec + 1;
+ }
+ mutex_unlock(&sysfs_lock);
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t fsl_timer_wakeup_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct timeval interval;
+ int ret;
+
+ interval.tv_usec = 0;
+ if (kstrtol(buf, 0, &interval.tv_sec))
+ return -EINVAL;
+
+ mutex_lock(&sysfs_lock);
+
+ if (fsl_wakeup->timer) {
+ disable_irq_wake(fsl_wakeup->timer->irq);
+ mpic_free_timer(fsl_wakeup->timer);
+ fsl_wakeup->timer = NULL;
+ }
+
+ if (!interval.tv_sec) {
+ mutex_unlock(&sysfs_lock);
+ return count;
+ }
+
+ fsl_wakeup->timer = mpic_request_timer(fsl_mpic_timer_irq,
+ fsl_wakeup, &interval);
+ if (!fsl_wakeup->timer) {
+ mutex_unlock(&sysfs_lock);
+ return -EINVAL;
+ }
+
+ ret = enable_irq_wake(fsl_wakeup->timer->irq);
+ if (ret) {
+ mpic_free_timer(fsl_wakeup->timer);
+ fsl_wakeup->timer = NULL;
+ mutex_unlock(&sysfs_lock);
+
+ return ret;
+ }
+
+ mpic_start_timer(fsl_wakeup->timer);
+
+ mutex_unlock(&sysfs_lock);
+
+ return count;
+}
+
+static struct device_attribute mpic_attributes = __ATTR(timer_wakeup, 0644,
+ fsl_timer_wakeup_show, fsl_timer_wakeup_store);
+
+static int __init fsl_wakeup_sys_init(void)
+{
+ int ret;
+
+ fsl_wakeup = kzalloc(sizeof(struct fsl_mpic_timer_wakeup), GFP_KERNEL);
+ if (!fsl_wakeup)
+ return -ENOMEM;
+
+ INIT_WORK(&fsl_wakeup->free_work, fsl_free_resource);
+
+ ret = device_create_file(mpic_subsys.dev_root, &mpic_attributes);
+ if (ret)
+ kfree(fsl_wakeup);
+
+ return ret;
+}
+
+static void __exit fsl_wakeup_sys_exit(void)
+{
+ device_remove_file(mpic_subsys.dev_root, &mpic_attributes);
+
+ mutex_lock(&sysfs_lock);
+
+ if (fsl_wakeup->timer) {
+ disable_irq_wake(fsl_wakeup->timer->irq);
+ mpic_free_timer(fsl_wakeup->timer);
+ }
+
+ kfree(fsl_wakeup);
+
+ mutex_unlock(&sysfs_lock);
+}
+
+module_init(fsl_wakeup_sys_init);
+module_exit(fsl_wakeup_sys_exit);
+
+MODULE_DESCRIPTION("Freescale MPIC global timer wakeup driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wang Dongsheng <dongsheng.wang@freescale.com>");
--
1.8.0
^ permalink raw reply related
* RE: [PATCH 1/4][v2] powerpc/fsl-booke: Add initial silicon device tree files for B4860 and B4420
From: Aggrwal Poonam-B10812 @ 2013-04-09 5:42 UTC (permalink / raw)
To: Leekha Shaveta-B20052, Kumar Gala; +Cc: linuxppc-dev@lists.ozlabs.org list
In-Reply-To: <E12D2F89F87F4A49B0320A4C2DE7E749152991@039-SN2MPN1-011.039d.mgd.msft.net>
> -----Original Message-----
> From: Linuxppc-dev [mailto:linuxppc-dev-
> bounces+poonam.aggrwal=3Dfreescale.com@lists.ozlabs.org] On Behalf Of
> Leekha Shaveta-B20052
> Sent: Monday, April 08, 2013 10:18 AM
> To: Kumar Gala
> Cc: linuxppc-dev@lists.ozlabs.org list
> Subject: RE: [PATCH 1/4][v2] powerpc/fsl-booke: Add initial silicon
> device tree files for B4860 and B4420
>=20
>=20
>=20
> -----Original Message-----
> From: Leekha Shaveta-B20052
> Sent: Friday, April 05, 2013 9:13 PM
> To: 'Kumar Gala'
> Cc: linuxppc-dev@lists.ozlabs.org list
> Subject: RE: [PATCH 1/4][v2] powerpc/fsl-booke: Add initial silicon
> device tree files for B4860 and B4420
>=20
>=20
>=20
> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]
> Sent: Friday, April 05, 2013 7:53 PM
> To: Leekha Shaveta-B20052
> Cc: linuxppc-dev@lists.ozlabs.org list
> Subject: Re: [PATCH 1/4][v2] powerpc/fsl-booke: Add initial silicon
> device tree files for B4860 and B4420
>=20
>=20
> On Apr 5, 2013, at 1:33 AM, Shaveta Leekha wrote:
>=20
> > B4860 and B4420 are similar that share some commonalities
> >
> > * common features have been added in b4si-pre.dtsi and b4si-post.dtsi
> > * differences are added in respective silicon files of B4860 and B4420
> >
> > There are several things missing from the device trees of B4860 and
> B4420:
> >
> > * DPAA related nodes (Qman, Bman, Fman, Rman)
> > * DSP related nodes/information
> > * serdes, sfp(security fuse processor), thermal, gpio, maple, cpri,
> > quad timers nodes
> >
> > Signed-off-by: Shaveta Leekha <shaveta@freescale.com>
> > Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
> > Signed-off-by: Li Yang <leoli@freescale.com>
> > Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
> > Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
> > Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
> > Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
> > Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> > Signed-off-by: Andy Fleming <afleming@freescale.com>
> > Signed-off-by: Vakul Garg <vakul@freescale.com>
> > ---
> > v2:
> > - incorporated review comments on commits message
> > - change unit address of cpu nodes to match the reg property
> >
> > arch/powerpc/boot/dts/fsl/b4420si-post.dtsi | 94 ++++++++++
> > arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi | 49 +++++
> > arch/powerpc/boot/dts/fsl/b4860si-post.dtsi | 138 ++++++++++++++
> > arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi | 59 ++++++
> > arch/powerpc/boot/dts/fsl/b4si-post.dtsi | 262
> +++++++++++++++++++++++++++
> > arch/powerpc/boot/dts/fsl/b4si-pre.dtsi | 65 +++++++
> > 6 files changed, 667 insertions(+), 0 deletions(-) create mode 100644
> > arch/powerpc/boot/dts/fsl/b4420si-post.dtsi
> > create mode 100644 arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
> > create mode 100644 arch/powerpc/boot/dts/fsl/b4860si-post.dtsi
> > create mode 100644 arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi
> > create mode 100644 arch/powerpc/boot/dts/fsl/b4si-post.dtsi
> > create mode 100644 arch/powerpc/boot/dts/fsl/b4si-pre.dtsi
>=20
> Is there a reason you didn't get rid of b4si-pre.dtsi and just merge it
> into b4860si-pre.dtsi & b4420-pre.dtsi?
> [SL] No particular reason. I have just tried to re-factored these files
> as you have suggested. Hence managed the commonalities in B4 files and
> differences in B4860's and B4420's respective files to reduce duplicity.
>=20
> Regards,
> Shaveta
>=20
> [SL] Kumar, please suggest.
Please suggest , if this re-factoring for pre-si dtsi should not be require=
d.
This was done to keep things uniform.
Accordingly we will send a re-spin if required.
Regards
Poonam
>=20
> Regards,
> Shaveta
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH] powerpc: fix compiling CONFIG_PPC_TRANSACTIONAL_MEM when CONFIG_ALTIVEC=n
From: Michael Neuling @ 2013-04-09 6:18 UTC (permalink / raw)
To: benh, sfr; +Cc: Linux PPC dev
We can't compile a kernel with CONFIG_ALTIVEC=n when
CONFIG_PPC_TRANSACTIONAL_MEM=y. We currently get:
arch/powerpc/kernel/tm.S:320: Error: unsupported relocation against THREAD_VSCR
arch/powerpc/kernel/tm.S:323: Error: unsupported relocation against THREAD_VR0
arch/powerpc/kernel/tm.S:323: Error: unsupported relocation against THREAD_VR0
etc.
The below fixes this with a sprinkling of #ifdefs.
This was found by mpe with kisskb:
http://kisskb.ellerman.id.au/kisskb/buildresult/8539442/
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
sfr: this would be nice to get in 3.9.
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 59dd545..16e77a8 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -555,10 +555,12 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
new->thread.regs->msr |=
(MSR_FP | new->thread.fpexc_mode);
}
+#ifdef CONFIG_ALTIVEC
if (msr & MSR_VEC) {
do_load_up_transact_altivec(&new->thread);
new->thread.regs->msr |= MSR_VEC;
}
+#endif
/* We may as well turn on VSX too since all the state is restored now */
if (msr & MSR_VSX)
new->thread.regs->msr |= MSR_VSX;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 3acb28e..95068bf 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -866,10 +866,12 @@ static long restore_tm_user_regs(struct pt_regs *regs,
do_load_up_transact_fpu(¤t->thread);
regs->msr |= (MSR_FP | current->thread.fpexc_mode);
}
+#ifdef CONFIG_ALTIVEC
if (msr & MSR_VEC) {
do_load_up_transact_altivec(¤t->thread);
regs->msr |= MSR_VEC;
}
+#endif
return 0;
}
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 995f854..c179428 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -522,10 +522,12 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
do_load_up_transact_fpu(¤t->thread);
regs->msr |= (MSR_FP | current->thread.fpexc_mode);
}
+#ifdef CONFIG_ALTIVEC
if (msr & MSR_VEC) {
do_load_up_transact_altivec(¤t->thread);
regs->msr |= MSR_VEC;
}
+#endif
return err;
}
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 84dbace..2da67e7 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -309,6 +309,7 @@ _GLOBAL(tm_recheckpoint)
or r5, r6, r5 /* Set MSR.FP+.VSX/.VEC */
mtmsr r5
+#ifdef CONFIG_ALTIVEC
/* FP and VEC registers: These are recheckpointed from thread.fpr[]
* and thread.vr[] respectively. The thread.transact_fpr[] version
* is more modern, and will be loaded subsequently by any FPUnavailable
@@ -323,6 +324,7 @@ _GLOBAL(tm_recheckpoint)
REST_32VRS(0, r5, r3) /* r5 scratch, r3 THREAD ptr */
ld r5, THREAD_VRSAVE(r3)
mtspr SPRN_VRSAVE, r5
+#endif
dont_restore_vec:
andi. r0, r4, MSR_FP
^ permalink raw reply related
* [PATCH] of: remove the unnecessary of_node_put for of_parse_phandle_with_args()
From: Yuantian.Tang @ 2013-04-09 6:56 UTC (permalink / raw)
To: grant.likely
Cc: Tang Yuantian, devicetree-discuss, linuxppc-dev, linux-kernel,
rob.herring
From: Tang Yuantian <yuantian.tang@freescale.com>
As the function itself says it is caller's responsibility to call the
of_node_put(). So, remove it on success to keep the reference count
correct.
Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
---
drivers/of/base.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 321d3ef..e8b4c28 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1168,9 +1168,6 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
out_args->args[i] = be32_to_cpup(list++);
}
- /* Found it! return success */
- if (node)
- of_node_put(node);
return 0;
}
--
1.8.0
^ permalink raw reply related
* Re: [PATCH 17/18] cpufreq: powerpc: move cpufreq driver to drivers/cpufreq
From: Viresh Kumar @ 2013-04-09 8:35 UTC (permalink / raw)
To: rjw, deepthi
Cc: robin.randhawa, linux-pm, Viresh Kumar, patches, Liviu.Dudau,
linux-kernel, cpufreq, Steve.Bannister, Paul Mackerras,
Olof Johansson, arvind.chauhan, linuxppc-dev, linaro-kernel,
charles.garcia-tobin
In-Reply-To: <CAKohpokGkZ9m0v1QaoXEv1m0mZqY70adWpXf3edQGmZnToRRcg@mail.gmail.com>
On 5 April 2013 12:16, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 4 April 2013 18:24, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>> This patch moves cpufreq driver of powerpc platform to drivers/cpufreq.
>>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: Olof Johansson <olof@lixom.net>
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>> ---
>> Compile Tested only.
>>
>> arch/powerpc/platforms/Kconfig | 31 ----------------------
>> arch/powerpc/platforms/pasemi/Makefile | 1 -
>> arch/powerpc/platforms/powermac/Makefile | 2 --
>> drivers/cpufreq/Kconfig.powerpc | 26 ++++++++++++++++++
>> drivers/cpufreq/Makefile | 3 +++
>> .../cpufreq.c => drivers/cpufreq/pasemi-cpufreq.c | 0
>> .../cpufreq/pmac32-cpufreq.c | 0
>> .../cpufreq/pmac64-cpufreq.c | 0
>> 8 files changed, 29 insertions(+), 34 deletions(-)
>> rename arch/powerpc/platforms/pasemi/cpufreq.c => drivers/cpufreq/pasemi-cpufreq.c (100%)
>> rename arch/powerpc/platforms/powermac/cpufreq_32.c => drivers/cpufreq/pmac32-cpufreq.c (100%)
>> rename arch/powerpc/platforms/powermac/cpufreq_64.c => drivers/cpufreq/pmac64-cpufreq.c (100%)
>
> Hi Deepthi,
>
> Can you help testing this please?
Ping!!
^ permalink raw reply
* [PATCH v3] clk: add PowerPC corenet clock driver support
From: Yuantian.Tang @ 2013-04-09 8:46 UTC (permalink / raw)
To: mturquette
Cc: ulf.hansson, linux-doc, viresh.kumar, devicetree-discuss,
linux-kernel, Tang Yuantian, shawn.guo, linuxppc-dev,
linus.walleij
From: Tang Yuantian <yuantian.tang@freescale.com>
This adds the clock driver for Freescale PowerPC corenet
series SoCs using common clock infrastructure.
Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
v3:
- remove the module author and description
v2:
- add the document for device tree clock bindings
arch/powerpc/platforms/Kconfig.cputype | 1 +
drivers/clk/Kconfig | 7 +
drivers/clk/Makefile | 1 +
drivers/clk/clk-ppc-corenet.c | 280 +++++++++++++++++++++++++++++++++
4 files changed, 289 insertions(+)
create mode 100644 drivers/clk/clk-ppc-corenet.c
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 18e3b76..cf065b8 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -158,6 +158,7 @@ config E500
config PPC_E500MC
bool "e500mc Support"
select PPC_FPU
+ select COMMON_CLK
depends on E500
help
This must be enabled for running on e500mc (and derivatives
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a47e6ee..6e2fd9c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -63,6 +63,13 @@ config CLK_TWL6040
McPDM. McPDM module is using the external bit clock on the McPDM bus
as functional clock.
+config CLK_PPC_CORENET
+ bool "Clock driver for PowerPC corenet platforms"
+ depends on PPC_E500MC && OF
+ ---help---
+ This adds the clock driver support for Freescale PowerPC corenet
+ platforms using common clock framework.
+
endmenu
source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 300d477..6720319 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_X86) += x86/
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
+obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-ppc-corenet.c
new file mode 100644
index 0000000..a2d483f
--- /dev/null
+++ b/drivers/clk/clk-ppc-corenet.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * clock driver for Freescale PowerPC corenet SoCs.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+struct cmux_clk {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u32 flags;
+};
+
+#define PLL_KILL BIT(31)
+#define CLKSEL_SHIFT 27
+#define CLKSEL_ADJUST BIT(0)
+#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw)
+
+static void __iomem *base;
+static unsigned int clocks_per_pll;
+
+static int cmux_set_parent(struct clk_hw *hw, u8 idx)
+{
+ struct cmux_clk *clk = to_cmux_clk(hw);
+ u32 clksel;
+
+ clksel = ((idx / clocks_per_pll) << 2) + idx % clocks_per_pll;
+ if (clk->flags & CLKSEL_ADJUST)
+ clksel += 8;
+ clksel = (clksel & 0xf) << CLKSEL_SHIFT;
+ iowrite32be(clksel, clk->reg);
+
+ return 0;
+}
+
+static u8 cmux_get_parent(struct clk_hw *hw)
+{
+ struct cmux_clk *clk = to_cmux_clk(hw);
+ u32 clksel;
+
+ clksel = ioread32be(clk->reg);
+ clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
+ if (clk->flags & CLKSEL_ADJUST)
+ clksel -= 8;
+ clksel = (clksel >> 2) * clocks_per_pll + clksel % 4;
+
+ return clksel;
+}
+
+const struct clk_ops cmux_ops = {
+ .get_parent = cmux_get_parent,
+ .set_parent = cmux_set_parent,
+};
+
+static void __init core_mux_init(struct device_node *np)
+{
+ struct clk *clk;
+ struct clk_init_data init;
+ struct cmux_clk *cmux_clk;
+ struct device_node *node;
+ int rc, count, i;
+ u32 offset;
+ const char *clk_name;
+ const char **parent_names;
+
+ rc = of_property_read_u32(np, "reg", &offset);
+ if (rc) {
+ pr_err("%s: could not get reg property\n", np->name);
+ return;
+ }
+
+ /* get the input clock source count */
+ count = of_property_count_strings(np, "clock-names");
+ if (count < 0) {
+ pr_err("%s: get clock count error\n", np->name);
+ return;
+ }
+ parent_names = kzalloc((sizeof(char *) * count), GFP_KERNEL);
+ if (!parent_names) {
+ pr_err("%s: could not allocate parent_names\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < count; i++)
+ parent_names[i] = of_clk_get_parent_name(np, i);
+
+ cmux_clk = kzalloc(sizeof(struct cmux_clk), GFP_KERNEL);
+ if (!cmux_clk) {
+ pr_err("%s: could not allocate cmux_clk\n", __func__);
+ goto err_name;
+ }
+ cmux_clk->reg = base + offset;
+
+ node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
+ if (node && (offset >= 0x80))
+ cmux_clk->flags = CLKSEL_ADJUST;
+
+ rc = of_property_read_string_index(np, "clock-output-names",
+ 0, &clk_name);
+ if (rc) {
+ pr_err("%s: read clock names error\n", np->name);
+ goto err_clk;
+ }
+
+ init.name = clk_name;
+ init.ops = &cmux_ops;
+ init.parent_names = parent_names;
+ init.num_parents = count;
+ init.flags = 0;
+ cmux_clk->hw.init = &init;
+
+ clk = clk_register(NULL, &cmux_clk->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: could not register clock\n", clk_name);
+ goto err_clk;
+ }
+
+ rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (rc) {
+ pr_err("Could not register clock provider for node:%s\n",
+ np->name);
+ goto err_clk;
+ }
+ goto err_name;
+
+err_clk:
+ kfree(cmux_clk);
+err_name:
+ /* free *_names because they are reallocated when registered */
+ kfree(parent_names);
+}
+
+static void __init core_pll_init(struct device_node *np)
+{
+ u32 offset, mult;
+ int i, rc, count;
+ const char *clk_name, *parent_name;
+ struct clk_onecell_data *onecell_data;
+ struct clk **subclks;
+
+ rc = of_property_read_u32(np, "reg", &offset);
+ if (rc) {
+ pr_err("%s: could not get reg property\n", np->name);
+ return;
+ }
+
+ /* get the multiple of PLL */
+ mult = ioread32be(base + offset);
+
+ /* check if this PLL is disabled */
+ if (mult & PLL_KILL) {
+ pr_debug("PLL:%s is disabled\n", np->name);
+ return;
+ }
+ mult = (mult >> 1) & 0x3f;
+
+ parent_name = of_clk_get_parent_name(np, 0);
+ if (!parent_name) {
+ pr_err("PLL: %s must have a parent\n", np->name);
+ return;
+ }
+
+ count = of_property_count_strings(np, "clock-output-names");
+ if (count < 0 || count > 4) {
+ pr_err("%s: clock is not supported\n", np->name);
+ return;
+ }
+
+ /* output clock number per PLL */
+ clocks_per_pll = count;
+
+ subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL);
+ if (!subclks) {
+ pr_err("%s: could not allocate subclks\n", __func__);
+ return;
+ }
+
+ onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+ if (!onecell_data) {
+ pr_err("%s: could not allocate onecell_data\n", __func__);
+ goto err_clks;
+ }
+
+ for (i = 0; i < count; i++) {
+ rc = of_property_read_string_index(np, "clock-output-names",
+ i, &clk_name);
+ if (rc) {
+ pr_err("%s: could not get clock names\n", np->name);
+ goto err_cell;
+ }
+
+ /*
+ * when count == 4, there are 4 output clocks:
+ * /1, /2, /3, /4 respectively
+ * when count < 4, there are at least 2 output clocks:
+ * /1, /2, (/4, if count == 3) respectively.
+ */
+ if (count == 4)
+ subclks[i] = clk_register_fixed_factor(NULL, clk_name,
+ parent_name, 0, mult, 1 + i);
+ else
+
+ subclks[i] = clk_register_fixed_factor(NULL, clk_name,
+ parent_name, 0, mult, 1 << i);
+
+ if (IS_ERR(subclks[i])) {
+ pr_err("%s: could not register clock\n", clk_name);
+ goto err_cell;
+ }
+ }
+
+ onecell_data->clks = subclks;
+ onecell_data->clk_num = count;
+
+ rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
+ if (rc) {
+ pr_err("Could not register clk provider for node:%s\n",
+ np->name);
+ goto err_cell;
+ }
+
+ return;
+err_cell:
+ kfree(onecell_data);
+err_clks:
+ kfree(subclks);
+}
+
+static const struct of_device_id clk_match[] __initconst = {
+ { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+ { .compatible = "fsl,core-pll-clock", .data = core_pll_init, },
+ { .compatible = "fsl,core-mux-clock", .data = core_mux_init, },
+ {}
+};
+
+static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
+{
+ struct device_node *np;
+
+ np = pdev->dev.of_node;
+ base = of_iomap(np, 0);
+ if (!base) {
+ dev_err(&pdev->dev, "iomap error\n");
+ return -ENOMEM;
+ }
+ of_clk_init(clk_match);
+
+ return 0;
+}
+
+static const struct of_device_id ppc_clk_ids[] __initconst = {
+ { .compatible = "fsl,qoriq-clockgen-1.0", },
+ { .compatible = "fsl,qoriq-clockgen-2", },
+ {}
+};
+
+static struct platform_driver ppc_corenet_clk_driver = {
+ .driver = {
+ .name = "ppc_corenet_clock",
+ .owner = THIS_MODULE,
+ .of_match_table = ppc_clk_ids,
+ },
+ .probe = ppc_corenet_clk_probe,
+};
+
+static int __init ppc_corenet_clk_init(void)
+{
+ return platform_driver_register(&ppc_corenet_clk_driver);
+}
+subsys_initcall(ppc_corenet_clk_init);
--
1.8.0
^ permalink raw reply related
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