* [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Chen Gang @ 2013-03-08 3:38 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <1362636305.3548.58.camel@pasglop>
originally I did not notice src buf len and dest buf len are the same.
so origianlly, it is not a bug issue, it is only for beautify code.
and now, using strcpy is better.
Signed-off-by: Chen Gang <gang.chen@asianux.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/tty/hvc/hvcs.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 81e939e..9330a4b 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -885,8 +885,7 @@ static void hvcs_set_pi(struct hvcs_partner_info
*pi, struct hvcs_struct *hvcsd)
hvcsd->p_partition_ID = pi->partition_ID;
/* copy the null-term char too */
- strlcpy(&hvcsd->p_location_code[0],
- &pi->location_code[0], sizeof(hvcsd->p_location_code));
+ strcpy(&hvcsd->p_location_code[0], &pi->location_code[0]);
}
/*
--
1.7.7.6
^ permalink raw reply related
* Re: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Benjamin Herrenschmidt @ 2013-03-08 3:46 UTC (permalink / raw)
To: Chen Gang; +Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <51395D2C.6040007@asianux.com>
On Fri, 2013-03-08 at 11:38 +0800, Chen Gang wrote:
> originally I did not notice src buf len and dest buf len are the same.
> so origianlly, it is not a bug issue, it is only for beautify code.
> and now, using strcpy is better.
Being the same len doesn't mean it's safe to use strcpy ... the source
might be missing the 0 terminator. In this specific case though, I
believe the source string comes was itself populated with strlcpy
(at least since your patch 6b6680c4ea3952af8ae76915cbca41245147741b) so
strcpy is indeed safe but using strlcpy doesn't hurt does it ?
Ben.
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> ---
> drivers/tty/hvc/hvcs.c | 3 +--
> 1 files changed, 1 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
> index 81e939e..9330a4b 100644
> --- a/drivers/tty/hvc/hvcs.c
> +++ b/drivers/tty/hvc/hvcs.c
> @@ -885,8 +885,7 @@ static void hvcs_set_pi(struct hvcs_partner_info
> *pi, struct hvcs_struct *hvcsd)
> hvcsd->p_partition_ID = pi->partition_ID;
>
> /* copy the null-term char too */
> - strlcpy(&hvcsd->p_location_code[0],
> - &pi->location_code[0], sizeof(hvcsd->p_location_code));
> + strcpy(&hvcsd->p_location_code[0], &pi->location_code[0]);
> }
>
> /*
^ permalink raw reply
* Re: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Chen Gang @ 2013-03-08 4:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <1362714364.6977.4.camel@pasglop>
于 2013年03月08日 11:46, Benjamin Herrenschmidt 写道:
> strcpy is indeed safe but using strlcpy doesn't hurt does it ?
really it is: using strlcpy doesn't hurt.
the comments and subject of original commit are not quite precision:
it is not for a bug issue (originally I say it is for bug issue)
it is really for beautify code.
can I send a fixup patch only for the comments ?
thanks.
--
Chen Gang
Asianux Corporation
^ permalink raw reply
* Re: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Benjamin Herrenschmidt @ 2013-03-08 4:33 UTC (permalink / raw)
To: Chen Gang; +Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <513967BC.2030301@asianux.com>
On Fri, 2013-03-08 at 12:23 +0800, Chen Gang wrote:
> really it is: using strlcpy doesn't hurt.
>
> the comments and subject of original commit are not quite precision:
> it is not for a bug issue (originally I say it is for bug issue)
> it is really for beautify code.
>
> can I send a fixup patch only for the comments ?
No just drop it, it's fine as it is.
Ben.
^ permalink raw reply
* Re: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Chen Gang @ 2013-03-08 4:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <1362717201.6977.5.camel@pasglop>
于 2013年03月08日 12:33, Benjamin Herrenschmidt 写道:
> On Fri, 2013-03-08 at 12:23 +0800, Chen Gang wrote:
>> > really it is: using strlcpy doesn't hurt.
>> >
>> > the comments and subject of original commit are not quite precision:
>> > it is not for a bug issue (originally I say it is for bug issue)
>> > it is really for beautify code.
>> >
>> > can I send a fixup patch only for the comments ?
> No just drop it, it's fine as it is.
I guess your meaning is:
not need additional fix up patch (just drop it).
original commit 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b is valid
(not need drop the original commit)
is it correct ?
thanks.
--
Chen Gang
Asianux Corporation
^ permalink raw reply
* Re: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Benjamin Herrenschmidt @ 2013-03-08 5:08 UTC (permalink / raw)
To: Chen Gang; +Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <51396BAA.2030307@asianux.com>
On Fri, 2013-03-08 at 12:40 +0800, Chen Gang wrote:
> is it correct ?
Yes, the code is fine as it is now.
Ben.
^ permalink raw reply
* Re: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: Chen Gang @ 2013-03-08 6:12 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Greg KH, linuxppc-dev, wfp5p, tklauser, Jiri Slaby, alan
In-Reply-To: <1362719285.6977.6.camel@pasglop>
于 2013年03月08日 13:08, Benjamin Herrenschmidt 写道:
> Yes, the code is fine as it is now.
ok, thanks.
--
Chen Gang
Asianux Corporation
^ permalink raw reply
* Re: PREMPT_RT
From: vneethv @ 2013-03-08 6:48 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <CAFbQSaB=gw3+P0-yDhjOFnP2z_sYzUHbw+MuFp8QLdF7xyuGUA@mail.gmail.com>
huh..My VDSO patch was not the culprit..! the issue was with
spin_lock_irqsave calls...! modify the same to
raw_spin_lock_irqsave..problem solved..!
the rtpatch was not applied properly.
--
View this message in context: http://linuxppc.10917.n7.nabble.com/PREMPT-RT-tp68107p69101.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* Re: Issue with USB Mass storage on P5020
From: vneethv @ 2013-03-08 6:49 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <CAFbQSaDmDfcsV03w5jOX-cSC-jr4d4GXk8rkzxs5QZeRd2z+-Q@mail.gmail.com>
Issue was with the USB mass storage i was using.. problem is specific to that
device.
--
View this message in context: http://linuxppc.10917.n7.nabble.com/Issue-with-USB-Mass-storage-on-P5020-tp67725p69102.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* RE: [PATCH V4] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao-B38951 @ 2013-03-08 8:01 UTC (permalink / raw)
To: Wood Scott-B07421
Cc: David Laight, linuxppc-dev@lists.ozlabs.org, Stuart Yoder
In-Reply-To: <1362674267.23227.1@snotra>
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Friday, March 08, 2013 12:38 AM
> To: Jia Hongtao-B38951
> Cc: David Laight; Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org;
> Stuart Yoder
> Subject: Re: [PATCH V4] powerpc/85xx: Add machine check handler to fix
> PCIe erratum on mpc85xx
>=20
> On 03/07/2013 02:06:05 AM, Jia Hongtao-B38951 wrote:
> > Here is the ideas from Scott:
> > "
> > > + if (is_in_pci_mem_space(addr)) {
> > > + inst =3D *(unsigned int *)regs->nip;
> >
> > Be careful about taking a fault here. A simple TLB miss should be
> > safe given that we shouldn't be accessing PCIe in the middle of
> > exception code, but what if the mapping has gone away (e.g. a
> > userspace driver had its code munmap()ed or swapped out)? What if
> > permissions allow execute but not read (not sure if Linux will allow
> > this, but the hardware does)?
> >
> > What if it happened in a KVM guest? You can't access guest addresses
> > directly.
> > "
>=20
> That means you need to be careful about how you read the instruction, not
> that you shouldn't do it at all.
>=20
> -Scott
I agree.
Do you have a more secure way to get the instruction?
Or what should be done to avoid permission break issue?
Thanks.
-Hongtao
^ permalink raw reply
* [PATCH 1/3] powerpc/mpic: add irq_set_wake support
From: Wang Dongsheng @ 2013-03-08 7:38 UTC (permalink / raw)
To: scottwood, kumar.gala; +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>
---
arch/powerpc/sysdev/mpic.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 3b2efd4..10e474e 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -920,6 +920,18 @@ 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);
+
+ 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 +969,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 +984,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
@@ -981,6 +995,7 @@ static struct irq_chip mpic_irq_ht_chip = {
.irq_unmask = mpic_unmask_ht_irq,
.irq_eoi = mpic_end_ht_irq,
.irq_set_type = mpic_set_irq_type,
+ .irq_set_wake = mpic_irq_set_wake,
};
#endif /* CONFIG_MPIC_U3_HT_IRQS */
--
1.7.5.1
^ permalink raw reply related
* [PATCH 2/3] powerpc/mpic: add global timer support
From: Wang Dongsheng @ 2013-03-08 7:38 UTC (permalink / raw)
To: scottwood, kumar.gala; +Cc: linuxppc-dev, Wang Dongsheng
In-Reply-To: <1362728327-21013-1-git-send-email-dongsheng.wang@freescale.com>
The MPIC global timer is a hardware timer inside the Freescale PIC comply
to Open-PIC standard. When the timer is timeout of the specified interval,
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 Open-PIC 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>
---
arch/powerpc/include/asm/mpic_timer.h | 46 +++
arch/powerpc/platforms/Kconfig | 12 +
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/mpic_timer.c | 606 +++++++++++++++++++++++++++++++++
4 files changed, 665 insertions(+), 0 deletions(-)
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..5af04fa 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 comply to Open-PIC standard. When the
+ timer is timeout of the specified interval, 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 Open-PIC 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..3aaa3d4
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -0,0 +1,606 @@
+/*
+ * 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
+
+#define MPIC_TIMER_TCR_CLKDIV_64 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;
+ u32 rem_us;
+ u32 div;
+
+ if (!(priv->flags & FSL_GLOBAL_TIMER)) {
+ time->tv_sec = (__kernel_time_t)
+ div_u64_rem(ticks, priv->timerfreq, &rem_us);
+ tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
+ time->tv_usec = (__kernel_suseconds_t)
+ div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
+
+ return;
+ }
+
+ div = (1 << (MPIC_TIMER_TCR_CLKDIV_64 >> 8)) * 8;
+
+ time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq / div);
+ tmp_sec = div_u64((u64)time->tv_sec * (u64)priv->timerfreq, div);
+
+ time->tv_usec = (__kernel_suseconds_t)
+ div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq / div);
+
+ 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;
+ u32 div;
+
+ 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;
+
+ if (!(priv->flags & FSL_GLOBAL_TIMER)) {
+ tmp_sec = time->tv_sec * priv->timerfreq;
+ tmp_ms = time->tv_usec / 1000 * priv->timerfreq / 1000;
+ tmp_us = time->tv_usec % 1000 * priv->timerfreq / 1000000;
+
+ *ticks = tmp_sec + tmp_ms + tmp_us;
+
+ return 0;
+ }
+
+ div = (1 << (MPIC_TIMER_TCR_CLKDIV_64 >> 8)) * 8;
+
+ tmp_sec = div_u64((u64)time->tv_sec * (u64)priv->timerfreq, div);
+ tmp += tmp_sec;
+
+ tmp_ms = time->tv_usec / 1000;
+ tmp_ms = div_u64((u64)tmp_ms * (u64)priv->timerfreq, div * 1000);
+ tmp += tmp_ms;
+
+ tmp_us = time->tv_usec % 1000;
+ tmp_us = div_u64((u64)tmp_us * (u64)priv->timerfreq, div * 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;
+ else
+ 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)
+{
+ 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;
+
+ 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_64);
+
+ 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_64);
+ }
+}
+
+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.7.5.1
^ permalink raw reply related
* [PATCH 3/3] powerpc/fsl: add MPIC timer wakeup support
From: Wang Dongsheng @ 2013-03-08 7:38 UTC (permalink / raw)
To: scottwood, kumar.gala; +Cc: linuxppc-dev, Wang Dongsheng, Zhao Chenhui
In-Reply-To: <1362728327-21013-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>
---
arch/powerpc/platforms/Kconfig | 9 ++
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c | 185 +++++++++++++++++++++++++++
3 files changed, 195 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 5af04fa..487c37f 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -99,6 +99,15 @@ config MPIC_TIMER
only tested on fsl chip, but it can potentially support
other global timers complying to Open-PIC standard.
+config FSL_MPIC_TIMER_WAKEUP
+ tristate "Freescale MPIC global timer wakeup driver"
+ depends on FSL_SOC && MPIC_TIMER
+ default n
+ help
+ This is only for freescale powerpc platform. 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..e94ba65
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
@@ -0,0 +1,185 @@
+/*
+ * 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>
+
+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 IRQ_HANDLED;
+}
+
+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 && !interval.tv_sec) {
+ disable_irq_wake(fsl_wakeup->timer->irq);
+ mpic_free_timer(fsl_wakeup->timer);
+ fsl_wakeup->timer = NULL;
+ mutex_unlock(&sysfs_lock);
+
+ return count;
+ }
+
+ if (fsl_wakeup->timer) {
+ mutex_unlock(&sysfs_lock);
+ return -EBUSY;
+ }
+
+ 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 bus_type mpic_subsys = {
+ .name = "mpic",
+ .dev_name = "mpic",
+};
+
+static DEVICE_ATTR(timer_wakeup, 0644,
+ fsl_timer_wakeup_show, fsl_timer_wakeup_store);
+
+static struct device_attribute *mpic_attributes[] = {
+ &dev_attr_timer_wakeup,
+ NULL
+};
+
+static int __init fsl_wakeup_sys_init(void)
+{
+ int ret;
+ int i;
+
+ 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 = subsys_system_register(&mpic_subsys, NULL);
+ if (ret)
+ goto err;
+
+ for (i = 0; mpic_attributes[i]; i++) {
+ ret = device_create_file(mpic_subsys.dev_root,
+ mpic_attributes[i]);
+ if (ret)
+ goto err2;
+ }
+
+ return ret;
+
+err2:
+ while (--i >= 0)
+ device_remove_file(mpic_subsys.dev_root, mpic_attributes[i]);
+
+ bus_unregister(&mpic_subsys);
+
+err:
+ kfree(fsl_wakeup);
+
+ return ret;
+}
+
+static void __exit fsl_wakeup_sys_exit(void)
+{
+ int i;
+
+ for (i = 0; mpic_attributes[i]; i++)
+ device_remove_file(mpic_subsys.dev_root,
+ mpic_attributes[i]);
+ bus_unregister(&mpic_subsys);
+ kfree(fsl_wakeup);
+}
+
+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.7.5.1
^ permalink raw reply related
* [PATCH] edac/85xx: Add PCIe error interrupt edac support
From: Chunhe Lan @ 2013-03-08 8:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: kumar.gala, Chunhe Lan
Adding pcie error interrupt edac support for mpc85xx, p3041, p4080,
and p5020. The mpc85xx uses the legacy interrupt report mechanism -
the error interrupts are reported directly to mpic. While, the p3041/
p4080/p5020 attaches the most of error interrupts to interrupt zero.
And report error interrupts to mpic via interrupt 0.
This patch can handle both of them.
Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
---
drivers/edac/mpc85xx_edac.c | 169 ++++++++++++++++++++++++++++++++++++++++---
drivers/edac/mpc85xx_edac.h | 7 ++
2 files changed, 165 insertions(+), 11 deletions(-)
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 42a840d..085b6b3 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -1,5 +1,6 @@
/*
* Freescale MPC85xx Memory Controller kenel module
+ * Copyright (c) 2013 Freescale Semiconductor, Inc.
*
* Author: Dave Jiang <djiang@mvista.com>
*
@@ -196,6 +197,120 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
edac_pci_handle_npe(pci, pci->ctl_name);
}
+static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
+{
+ struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+ u32 err_detect;
+
+ err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
+
+ pr_err("PCIE error(s) detected\n");
+ pr_err("PCIE ERR_DR register: 0x%08x\n", err_detect);
+ pr_err("PCIE ERR_CAP_STAT register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR));
+ pr_err("PCIE ERR_CAP_R0 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
+ pr_err("PCIE ERR_CAP_R1 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
+ pr_err("PCIE ERR_CAP_R2 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
+ pr_err("PCIE ERR_CAP_R3 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
+
+ /* clear error bits */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
+}
+
+/*
+ * This function is for error interrupt ORed mechanism.
+ * This mechanism attaches most functions' error interrupts to interrupt 0.
+ * And report error interrupt to mpic via interrupt 0.
+ * EIMR0 - Error Interrupt Mask Register 0.
+ *
+ * This function check whether the device support error interrupt ORed
+ * mechanism via device tree. If supported, umask pcie error interrupt
+ * bit in EIMR0.
+ */
+static int mpc85xx_err_int_en(struct platform_device *op)
+{
+ u32 *int_cell;
+ struct device_node *np;
+ void __iomem *mpic_base;
+ u32 reg_tmp;
+ u32 int_len;
+ struct resource r;
+ int res;
+
+ if (!op->dev.of_node)
+ return -EINVAL;
+
+ /*
+ * Unmask pcie error interrupt bit in EIMR0.
+ * Extend interrupt specifier has 4 cells.
+ * For the 3rd cell:
+ * 0 -- normal interrupt;
+ * 1 -- error interrupt.
+ */
+ int_cell = (u32 *)of_get_property(op->dev.of_node, "interrupts",
+ &int_len);
+ if ((int_len/sizeof(u32)) == 4) {
+ /* soc has error interrupt integration handling mechanism */
+ if (*(int_cell + 2) == 1) {
+ np = of_find_node_by_type(NULL, "open-pic");
+
+ if (of_address_to_resource(np, 0, &r)) {
+ pr_err("%s: Failed to map mpic regs\n",
+ __func__);
+ of_node_put(np);
+ res = -ENOMEM;
+ goto err;
+ }
+
+ if (!request_mem_region(r.start, r.end - r.start + 1,
+ "mpic")) {
+ pr_err("%s: Error when requesting mem region\n",
+ __func__);
+ res = -EBUSY;
+ goto err;
+ }
+
+ mpic_base = ioremap(r.start, r.end - r.start + 1);
+ if (!mpic_base) {
+ pr_err("%s: Unable to map mpic regs\n",
+ __func__);
+ res = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ reg_tmp = in_be32(mpic_base + MPC85XX_MPIC_EIMR0);
+ out_be32(mpic_base + MPC85XX_MPIC_EIMR0, reg_tmp &
+ ~(1 << (31 - *(int_cell + 3))));
+ iounmap(mpic_base);
+ release_mem_region(r.start, r.end - r.start + 1);
+ of_node_put(np);
+ }
+ }
+
+ return 0;
+
+err_ioremap:
+ release_mem_region(r.start, r.end - r.start + 1);
+err:
+ return res;
+}
+
+static int mpc85xx_pcie_find_capability(struct device_node *np)
+{
+ struct pci_controller *hose;
+
+ if (!np)
+ return -EINVAL;
+
+ hose = pci_find_hose_for_OF_device(np);
+
+ return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
+}
+
static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
{
struct edac_pci_ctl_info *pci = dev_id;
@@ -207,7 +322,10 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
if (!err_detect)
return IRQ_NONE;
- mpc85xx_pci_check(pci);
+ if (pdata->is_pcie)
+ mpc85xx_pcie_check(pci);
+ else
+ mpc85xx_pci_check(pci);
return IRQ_HANDLED;
}
@@ -239,14 +357,23 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata = pci->pvt_info;
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
+ if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
+ pdata->is_pcie = 1;
+ else
+ pdata->is_pcie = 0;
+
dev_set_drvdata(&op->dev, pci);
pci->dev = &op->dev;
pci->mod_name = EDAC_MOD_STR;
pci->ctl_name = pdata->name;
pci->dev_name = dev_name(&op->dev);
- if (edac_op_state == EDAC_OPSTATE_POLL)
- pci->edac_check = mpc85xx_pci_check;
+ if (edac_op_state == EDAC_OPSTATE_POLL) {
+ if (pdata->is_pcie)
+ pci->edac_check = mpc85xx_pcie_check;
+ else
+ pci->edac_check = mpc85xx_pci_check;
+ }
pdata->edac_idx = edac_pci_idx++;
@@ -275,16 +402,29 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
goto err;
}
- orig_pci_err_cap_dr =
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
+ if (pdata->is_pcie) {
+ if (mpc85xx_err_int_en(op) < 0)
+ goto err;
- /* PCI master abort is expected during config cycles */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
+ orig_pci_err_cap_dr =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);
+ orig_pci_err_en =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);
+ } else {
+ orig_pci_err_cap_dr =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
+
+ /* PCI master abort is expected during config cycles */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
- orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+ orig_pci_err_en =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
- /* disable master abort reporting */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+ /* disable master abort reporting */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+ }
/* clear error bits */
out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
@@ -297,7 +437,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
if (edac_op_state == EDAC_OPSTATE_INT) {
pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_pci_isr, IRQF_DISABLED,
+ mpc85xx_pci_isr,
+ IRQF_DISABLED | IRQF_SHARED,
"[EDAC] PCI err", pci);
if (res < 0) {
printk(KERN_ERR
@@ -312,6 +453,12 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata->irq);
}
+ if (pdata->is_pcie) {
+ /* enable all pcie error interrupt & error detect */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0);
+ }
+
devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
edac_dbg(3, "success\n");
printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 932016f..8ce091a 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -141,6 +141,12 @@
#define MPC85XX_PCI_ERR_DH 0x001c
#define MPC85XX_PCI_GAS_TIMR 0x0020
#define MPC85XX_PCI_PCIX_TIMR 0x0024
+#define MPC85XX_PCIE_ERR_CAP_R0 0x0028
+#define MPC85XX_PCIE_ERR_CAP_R1 0x002c
+#define MPC85XX_PCIE_ERR_CAP_R2 0x0030
+#define MPC85XX_PCIE_ERR_CAP_R3 0x0034
+
+#define MPC85XX_MPIC_EIMR0 0x3910
struct mpc85xx_mc_pdata {
char *name;
@@ -158,6 +164,7 @@ struct mpc85xx_l2_pdata {
struct mpc85xx_pci_pdata {
char *name;
+ char is_pcie;
int edac_idx;
void __iomem *pci_vbase;
int irq;
--
1.7.6.5
^ permalink raw reply related
* Re: 3.9-rc1 powerpc ptrace.c: 'brk.len' is used uninitialized
From: Philippe De Muyter @ 2013-03-08 10:24 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <11606.1362697414@ale.ozlabs.ibm.com>
On Fri, Mar 08, 2013 at 10:03:34AM +1100, Michael Neuling wrote:
> Michael Neuling <mikey@neuling.org> wrote:
>
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index 245c1b6..8564515 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -1428,6 +1428,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
>
> brk.address = bp_info->addr & ~7UL;
> brk.type = HW_BRK_TYPE_TRANSLATE;
> + brk.len = 0;
> if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
> brk.type |= HW_BRK_TYPE_READ;
> if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
That's ok. Thanks
Philippe
^ permalink raw reply
* RE: [PATCH] drivers/tty/hvc: fixup original commit: 9276dfd27897a0b29d8b5814f39a1f82f56b6b6b
From: David Laight @ 2013-03-08 11:11 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Chen Gang
Cc: Jiri Slaby, Greg KH, wfp5p, tklauser, linuxppc-dev, alan
In-Reply-To: <1362714364.6977.4.camel@pasglop>
> On Fri, 2013-03-08 at 11:38 +0800, Chen Gang wrote:
> > originally I did not notice src buf len and dest buf len are the =
same.
> > so origianlly, it is not a bug issue, it is only for beautify =
code.
> > and now, using strcpy is better.
>=20
> Being the same len doesn't mean it's safe to use strcpy ... the source
> might be missing the 0 terminator. In this specific case though, I
> believe the source string comes was itself populated with strlcpy
> (at least since your patch 6b6680c4ea3952af8ae76915cbca41245147741b) =
so
> strcpy is indeed safe but using strlcpy doesn't hurt does it ?
Using strlcpy() also stops someone else having to check it
again in a few years time.
David
^ permalink raw reply
* [PATCH] powerpc/kernel: Cleanup on rtas_pci.c
From: Gavin Shan @ 2013-03-08 11:47 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Gavin Shan
It's minor cleanup so that the function names comply with the
coding style.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
arch/powerpc/kernel/rtas_pci.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 81c1abb..8d26f92 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -202,7 +202,7 @@ static void python_countermeasures(struct device_node *dev)
iounmap(chip_regs);
}
-void __init init_pci_config_tokens (void)
+void __init init_pci_config_tokens(void)
{
read_pci_config = rtas_token("read-pci-config");
write_pci_config = rtas_token("write-pci-config");
@@ -210,7 +210,7 @@ void __init init_pci_config_tokens (void)
ibm_write_pci_config = rtas_token("ibm,write-pci-config");
}
-unsigned long get_phb_buid (struct device_node *phb)
+unsigned long get_phb_buid(struct device_node *phb)
{
struct resource r;
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 3/4] TDM Device Tree entries for various Freescale Platforms
From: Timur Tabi @ 2013-03-08 16:47 UTC (permalink / raw)
To: Sandeep Singh; +Cc: Poonam Aggrwal, linuxppc-dev
In-Reply-To: <1362655668-26721-3-git-send-email-Sandeep@freescale.com>
On Thu, Mar 7, 2013 at 5:27 AM, Sandeep Singh <Sandeep@freescale.com> wrote:
> arch/powerpc/boot/dts/p1022ds_36b.dts | 3 +++
You forgot to update p1022ds_3b.dts.
> - * Copyright 2011 Freescale Semiconductor Inc.
> + * Copyright 2011-2012 Freescale Semiconductor Inc.
Do not update the copyright year in patches.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH 3/4] TDM Device Tree entries for various Freescale Platforms
From: Timur Tabi @ 2013-03-08 16:47 UTC (permalink / raw)
To: Sandeep Singh, linuxppc-dev, Poonam Aggrwal
In-Reply-To: <CAOZdJXW7=3G8STRzaF04dmFZKFjp3=_2uy9F2pTZ-pe7L8nd7A@mail.gmail.com>
On Fri, Mar 8, 2013 at 10:47 AM, Timur Tabi <timur@tabi.org> wrote:
>
> You forgot to update p1022ds_3b.dts.
I meant p1022ds_32b.dts -- the 32-bit DTS for the P1022DS.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH] edac/85xx: Add PCIe error interrupt edac support
From: Gala Kumar-B11780 @ 2013-03-08 19:22 UTC (permalink / raw)
To: Lan Chunhe-B25806; +Cc: <linuxppc-dev@lists.ozlabs.org>
In-Reply-To: <1362731547-25165-1-git-send-email-Chunhe.Lan@freescale.com>
On Mar 8, 2013, at 2:32 AM, Chunhe Lan wrote:
> Adding pcie error interrupt edac support for mpc85xx, p3041, p4080,
> and p5020. The mpc85xx uses the legacy interrupt report mechanism -
> the error interrupts are reported directly to mpic. While, the p3041/
> p4080/p5020 attaches the most of error interrupts to interrupt zero.
> And report error interrupts to mpic via interrupt 0.
>=20
> This patch can handle both of them.
>=20
> Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
> ---
> drivers/edac/mpc85xx_edac.c | 169 ++++++++++++++++++++++++++++++++++++++=
++---
> drivers/edac/mpc85xx_edac.h | 7 ++
> 2 files changed, 165 insertions(+), 11 deletions(-)
Does this also work on T4 / PCIe controller rev3.0?
>=20
> diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
> index 42a840d..085b6b3 100644
> --- a/drivers/edac/mpc85xx_edac.c
> +++ b/drivers/edac/mpc85xx_edac.c
> @@ -1,5 +1,6 @@
> /*
> * Freescale MPC85xx Memory Controller kenel module
> + * Copyright (c) 2013 Freescale Semiconductor, Inc.
> *
> * Author: Dave Jiang <djiang@mvista.com>
> *
> @@ -196,6 +197,120 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_i=
nfo *pci)
> edac_pci_handle_npe(pci, pci->ctl_name);
> }
>=20
> +static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
> +{
> + struct mpc85xx_pci_pdata *pdata =3D pci->pvt_info;
> + u32 err_detect;
> +
> + err_detect =3D in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
> +
> + pr_err("PCIE error(s) detected\n");
> + pr_err("PCIE ERR_DR register: 0x%08x\n", err_detect);
> + pr_err("PCIE ERR_CAP_STAT register: 0x%08x\n",
> + in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR));
> + pr_err("PCIE ERR_CAP_R0 register: 0x%08x\n",
> + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
> + pr_err("PCIE ERR_CAP_R1 register: 0x%08x\n",
> + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
> + pr_err("PCIE ERR_CAP_R2 register: 0x%08x\n",
> + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
> + pr_err("PCIE ERR_CAP_R3 register: 0x%08x\n",
> + in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
> +
> + /* clear error bits */
> + out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
> +}
> +
> +/*
> + * This function is for error interrupt ORed mechanism.
> + * This mechanism attaches most functions' error interrupts to interrupt=
0.
> + * And report error interrupt to mpic via interrupt 0.
> + * EIMR0 - Error Interrupt Mask Register 0.
> + *
> + * This function check whether the device support error interrupt ORed
> + * mechanism via device tree. If supported, umask pcie error interrupt
> + * bit in EIMR0.
> + */
> +static int mpc85xx_err_int_en(struct platform_device *op)
> +{
> + u32 *int_cell;
> + struct device_node *np;
> + void __iomem *mpic_base;
> + u32 reg_tmp;
> + u32 int_len;
> + struct resource r;
> + int res;
> +
> + if (!op->dev.of_node)
> + return -EINVAL;
> +
> + /*
> + * Unmask pcie error interrupt bit in EIMR0.
> + * Extend interrupt specifier has 4 cells.
> + * For the 3rd cell:
> + * 0 -- normal interrupt;
> + * 1 -- error interrupt.
> + */
> + int_cell =3D (u32 *)of_get_property(op->dev.of_node, "interrupts",
> + &int_len);
> + if ((int_len/sizeof(u32)) =3D=3D 4) {
> + /* soc has error interrupt integration handling mechanism */
> + if (*(int_cell + 2) =3D=3D 1) {
> + np =3D of_find_node_by_type(NULL, "open-pic");
> +
> + if (of_address_to_resource(np, 0, &r)) {
> + pr_err("%s: Failed to map mpic regs\n",
> + __func__);
> + of_node_put(np);
> + res =3D -ENOMEM;
> + goto err;
> + }
> +
> + if (!request_mem_region(r.start, r.end - r.start + 1,
> + "mpic")) {
> + pr_err("%s: Error when requesting mem region\n",
> + __func__);
> + res =3D -EBUSY;
> + goto err;
> + }
> +
> + mpic_base =3D ioremap(r.start, r.end - r.start + 1);
> + if (!mpic_base) {
> + pr_err("%s: Unable to map mpic regs\n",
> + __func__);
> + res =3D -ENOMEM;
> + goto err_ioremap;
> + }
> +
> + reg_tmp =3D in_be32(mpic_base + MPC85XX_MPIC_EIMR0);
> + out_be32(mpic_base + MPC85XX_MPIC_EIMR0, reg_tmp &
> + ~(1 << (31 - *(int_cell + 3))));
> + iounmap(mpic_base);
> + release_mem_region(r.start, r.end - r.start + 1);
> + of_node_put(np);
> + }
> + }
> +
Why is this all needed, we have handling of error interrupts in the kernel =
already?
- k
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: Add platform_device declaration to fsl_pci.h
From: Kumar Gala @ 2013-03-08 20:38 UTC (permalink / raw)
To: Jia Hongtao; +Cc: B07421, linuxppc-dev
In-Reply-To: <1362386409-15907-1-git-send-email-B38951@freescale.com>
On Mar 4, 2013, at 2:40 AM, Jia Hongtao wrote:
> mpc85xx_pci_err_probe(struct platform_device *op) need platform_device
> declaration for definition. Otherwise, it will cause compile error if any
> files including fsl_pci.h without declaration of platform_device.
>
> Signed-off-by: Jia Hongtao <B38951@freescale.com>
> ---
> arch/powerpc/sysdev/fsl_pci.h | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
Where does the compile error show up?
- k
> diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
> index c495c00..df66721 100644
> --- a/arch/powerpc/sysdev/fsl_pci.h
> +++ b/arch/powerpc/sysdev/fsl_pci.h
> @@ -14,6 +14,8 @@
> #ifndef __POWERPC_FSL_PCI_H
> #define __POWERPC_FSL_PCI_H
>
> +#include <linux/platform_device.h>
> +
> #define PCIE_LTSSM 0x0404 /* PCIE Link Training and Status */
> #define PCIE_LTSSM_L0 0x16 /* L0 state */
> #define PCIE_IP_REV_2_2 0x02080202 /* PCIE IP block version Rev2.2 */
> --
> 1.7.5.1
>
^ permalink raw reply
* Re: [PATCH 1/1] book3e/corenet64: increase CPU numbers by default
From: Kumar Gala @ 2013-03-08 20:39 UTC (permalink / raw)
To: Tiejun Chen; +Cc: linuxppc-dev
In-Reply-To: <1361871198-942-1-git-send-email-tiejun.chen@windriver.com>
On Feb 26, 2013, at 3:33 AM, Tiejun Chen wrote:
> Currently we already support p5040ds which has 4 e5500 cores, but
> twelve dual-threaded e6500 cores are also built on T4240, we can
> change CONFIG_NR_CPUS with this value now.
>
> Signed-off-by: Tiejun Chen <tiejun.chen@windriver.com>
> ---
> arch/powerpc/configs/corenet64_smp_defconfig | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
I've handled this as part of the T4 baseline support patchset.
- k
^ permalink raw reply
* Re: [PATCH] mmc: sdhci-pltfm: Fix timeout on t4240's sdhci controller
From: Gala Kumar-B11780 @ 2013-03-08 20:43 UTC (permalink / raw)
To: Lan Chunhe-B25806
Cc: Gala Kumar-B11780, <linuxppc-dev@lists.ozlabs.org>
In-Reply-To: <513953B5.30707@freescale.com>
On Mar 7, 2013, at 8:57 PM, Chunhe Lan wrote:
> On 03/08/2013 12:30 AM, Gala Kumar-B11780 wrote:
>> On Mar 7, 2013, at 2:05 AM, Chunhe Lan wrote:
>>=20
>>> This patch fixes timeout problems on t4240's sdhci controller:
>>>=20
>>> mmc0: Too large timeout requested for CMD25!
>>> mmc0: Too large timeout requested for CMD25!
>>> mmc0: Too large timeout requested for CMD25!
>>>=20
>>> Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
>>> ---
>>> drivers/mmc/host/sdhci-pltfm.c | 1 +
>>> 1 files changed, 1 insertions(+), 0 deletions(-)
>>>=20
>>> diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pl=
tfm.c
>>> index 3145a78..9db7b12 100644
>>> --- a/drivers/mmc/host/sdhci-pltfm.c
>>> +++ b/drivers/mmc/host/sdhci-pltfm.c
>>> @@ -94,6 +94,7 @@ void sdhci_get_of_property(struct platform_device *pd=
ev)
>>>=20
>>> if (of_device_is_compatible(np, "fsl,p2020-esdhc") ||
>>> of_device_is_compatible(np, "fsl,p1010-esdhc") ||
>>> + of_device_is_compatible(np, "fsl,t4240-esdhc") ||
>>> of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
>>> host->quirks |=3D SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
>>>=20
>>> --=20
>>> 1.7.6.5
>>>=20
>>=20
>> Why does this occur? Is it a board issue? Is it a silicon issue? Is i=
t due to some erratum? Why T4 only?
> It would be the property of T4 hardware, and please see below the pat=
ch which locates
> the mail list of freescale:
>=20
> eSDHC: mmc:host host need long time to generate command complete interrup=
t
>=20
> According to Spec 2.0, command complete interrupt will generate within 15=
0 SD-CLK.
> But this was not enough on T4240 board. So give it sufficient time to det=
ect command
> timeout. 1000 * HZ will be enough, this value was test on all T4 board, a=
ll worked well.
>=20
> Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> Signed-off-by: Haijun Zhang <Haijun.Zhang@freescale.com>
I still don't understand the explanation of the issue on T4. Why doesn't P=
4080, P5020, etc suffer from the issue?
- k=
^ permalink raw reply
* Re: [PATCH V4] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Scott Wood @ 2013-03-09 0:49 UTC (permalink / raw)
To: Jia Hongtao-B38951
Cc: Wood Scott-B07421, David Laight, linuxppc-dev@lists.ozlabs.org,
Stuart Yoder
In-Reply-To: <412C8208B4A0464FA894C5F0C278CD5D01BFC620@039-SN1MPN1-002.039d.mgd.msft.net>
On 03/08/2013 02:01:46 AM, Jia Hongtao-B38951 wrote:
>=20
>=20
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Friday, March 08, 2013 12:38 AM
> > To: Jia Hongtao-B38951
> > Cc: David Laight; Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org;
> > Stuart Yoder
> > Subject: Re: [PATCH V4] powerpc/85xx: Add machine check handler to =20
> fix
> > PCIe erratum on mpc85xx
> >
> > On 03/07/2013 02:06:05 AM, Jia Hongtao-B38951 wrote:
> > > Here is the ideas from Scott:
> > > "
> > > > + if (is_in_pci_mem_space(addr)) {
> > > > + inst =3D *(unsigned int *)regs->nip;
> > >
> > > Be careful about taking a fault here. A simple TLB miss should be
> > > safe given that we shouldn't be accessing PCIe in the middle of
> > > exception code, but what if the mapping has gone away (e.g. a
> > > userspace driver had its code munmap()ed or swapped out)? What if
> > > permissions allow execute but not read (not sure if Linux will =20
> allow
> > > this, but the hardware does)?
> > >
> > > What if it happened in a KVM guest? You can't access guest =20
> addresses
> > > directly.
> > > "
> >
> > That means you need to be careful about how you read the =20
> instruction, not
> > that you shouldn't do it at all.
> >
> > -Scott
>=20
> I agree.
>=20
> Do you have a more secure way to get the instruction?
> Or what should be done to avoid permission break issue?
probe_kernel_address() should take care of userspace issues. As for =20
KVM, if you see MSR_GS set, bail out and don't apply the workaround. =20
Let KVM/QEMU deal with it as it wishes (e.g. reflect to the guest and =20
let its machine check handler do the skipping). On PR-mode KVM (e.g. =20
on e500v2-based chips) there is no MSR_GS and it just looks like =20
userspace code -- for now just pretend it is user mode.
-Scott=
^ permalink raw reply
* [PATCH] powerpc: Fix dynamic relocation
From: Alexander Graf @ 2013-03-09 1:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Anton Blanchard
Commit 5ac47f7a introduced dynamic relocation of code by manually
relocating TOC entries. However, we need to access the TOC using
the physical address that we have for it, not the virtual address
that we can't even access yet.
Drop the offset from the TOC accessing pointer.
This fixes Linux 3.9 booting on OpenBIOS for me.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
I've also encountered breakage on a G5 Mac, not sure if it's related.
I'll have to test whether this is the culprit on that one too.
Ben, please make sure that this gets into 3.9.
---
arch/powerpc/kernel/prom_init.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 7f7fb7f..2bf7cc3 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2851,7 +2851,7 @@ static void reloc_toc(void)
(__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
/* Need to add offset to get at __prom_init_toc_start */
- __reloc_toc(__prom_init_toc_start + offset, offset, nr_entries);
+ __reloc_toc(__prom_init_toc_start, offset, nr_entries);
mb();
}
--
1.6.0.2
^ 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