* [PATCH v5 3/3] powernv, cpufreq: Use cpufreq_frequency_table.driver_data to store pstate ids
From: Gautham R. Shenoy @ 2014-03-28 20:11 UTC (permalink / raw)
To: Viresh Kumar, rjw, Benjamin Herrenschmidt
Cc: Gautham R. Shenoy, Linux PM list, linux-kernel, cpufreq,
linuxppc-dev, Anton Blanchard, srivatsa.bhat
In-Reply-To: <1396037484-23907-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
The .driver_data field in the cpufreq_frequency_table was supposed to
be private to the drivers. However at some later point, it was being
used to indicate if the particular frequency in the table is the
BOOST_FREQUENCY. After patches [1] and [2], the .driver_data is once
again private to the driver. Thus we can safely use
cpufreq_frequency_table.driver_data to store pstate_ids instead of
having to maintain a separate array powernv_pstate_ids[] for this
purpose.
[1]:
Subject: cpufreq: don't print value of .driver_data from core
From : Viresh Kumar <viresh.kumar@ linaro.org>
url : http://marc.info/?l=linux-pm&m=139601421504709&w=2
[2]:
Subject: cpufreq: create another field .flags in cpufreq_frequency_table
From : Viresh Kumar <viresh.kumar@linaro.org>
url : http://marc.info/?l=linux-pm&m=139601416804702&w=2
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
drivers/cpufreq/powernv-cpufreq.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index e1e5197..9edccc6 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -33,7 +33,6 @@
#define POWERNV_MAX_PSTATES 256
static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
-static int powernv_pstate_ids[POWERNV_MAX_PSTATES+1];
/*
* Note: The set of pstates consists of contiguous integers, the
@@ -112,7 +111,7 @@ static int init_powernv_pstates(void)
pr_debug("PState id %d freq %d MHz\n", id, freq);
powernv_freqs[i].frequency = freq * 1000; /* kHz */
- powernv_pstate_ids[i] = id;
+ powernv_freqs[i].driver_data = id;
}
/* End of list marker entry */
powernv_freqs[i].frequency = CPUFREQ_TABLE_END;
@@ -283,7 +282,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
{
struct powernv_smp_call_data freq_data;
- freq_data.pstate_id = powernv_pstate_ids[new_index];
+ freq_data.pstate_id = powernv_freqs[new_index].driver_data;
/*
* Use smp_call_function to send IPI and execute the
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Benjamin Herrenschmidt @ 2014-03-28 21:25 UTC (permalink / raw)
To: Dongsheng Wang
Cc: James Hogan, Andrew Morton, David S. Miller, Peter Zijlstra,
fweisbec, Helge Deller, linuxppc-dev, Heiko Carstens,
linux-kernel, Paul Mackerras, James E.J. Bottomley,
Linus Torvalds, jason.jin, H. Peter Anvin, scottwood,
Thomas Gleixner, Ingo Molnar, Martin Schwidefsky
In-Reply-To: <1395992312-23035-1-git-send-email-dongsheng.wang@freescale.com>
On Fri, 2014-03-28 at 15:38 +0800, Dongsheng Wang wrote:
> From: Wang Dongsheng <dongsheng.wang@freescale.com>
>
> If softirq use hardirq stack, we will get kernel painc when a hard irq coming again
> during __do_softirq enable local irq to deal with softirq action. So we need to switch
> satck into softirq stack when invoke soft irq.
Yes, an interrupt can potentially nest but we should be near the top of
the stack at that point, as the comment says in softirq.c, it should
be fine. And your backtrace doesn't seem to indicate a major overflow.
The code in do_IRQ() will make sure we don't switch stack again if
we were already on either hard or softirq stack.
I need a better analysis of your problem. Is that really a stack
overflow ? Or is it a false positive due to a bug in the overflow
detection ?
I moved around the code that updates KSP_LIMIT in 32-bit to asm in
misc_32.S a while ago since we don't do that on 64-bit, maybe we are
getting it wrong...
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Benjamin Herrenschmidt @ 2014-03-28 21:27 UTC (permalink / raw)
To: Kevin Hao
Cc: Ingo Molnar, James Hogan, jason.jin, Peter Zijlstra, fweisbec,
Helge Deller, linuxppc-dev, Heiko Carstens, Dongsheng Wang,
Paul Mackerras, linux-kernel, Martin Schwidefsky, Thomas Gleixner,
James E.J. Bottomley, H. Peter Anvin, scottwood, Andrew Morton,
Linus Torvalds, David S. Miller
In-Reply-To: <20140328081827.GB2176@pek-khao-d1.corp.ad.wrs.com>
On Fri, 2014-03-28 at 16:18 +0800, Kevin Hao wrote:
> powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack
>
Kevin. It looks like it was applied to 3.14 and sent to 3.12 stable but
not 3.13 ... can you fix that up ?
Cheers,
Ben.
> Guenter Roeck has got the following call trace on a p2020 board:
> Kernel stack overflow in process eb3e5a00, r1=eb79df90
> CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4
> task: eb3e5a00 ti: c0616000 task.ti: ef440000
> NIP: c003a420 LR: c003a410 CTR: c0017518
> REGS: eb79dee0 TRAP: 0901 Not tainted (3.13.0-rc8-juniper-00146-g19eca00)
> MSR: 00029000 <CE,EE,ME> CR: 24008444 XER: 00000000
> GPR00: c003a410 eb79df90 eb3e5a00 00000000 eb05d900 00000001 65d87646 00000000
> GPR08: 00000000 020b8000 00000000 00000000 44008442
> NIP [c003a420] __do_softirq+0x94/0x1ec
> LR [c003a410] __do_softirq+0x84/0x1ec
> Call Trace:
> [eb79df90] [c003a410] __do_softirq+0x84/0x1ec (unreliable)
> [eb79dfe0] [c003a970] irq_exit+0xbc/0xc8
> [eb79dff0] [c000cc1c] call_do_irq+0x24/0x3c
> [ef441f20] [c00046a8] do_IRQ+0x8c/0xf8
> [ef441f40] [c000e7f4] ret_from_except+0x0/0x18
> --- Exception: 501 at 0xfcda524
> LR = 0x10024900
> Instruction dump:
> 7c781b78 3b40000a 3a73b040 543c0024 3a800000 3b3913a0 7ef5bb78 48201bf9
> 5463103a 7d3b182e 7e89b92e 7c008146 <3ba00000> 7e7e9b78 48000014 57fff87f
> Kernel panic - not syncing: kernel stack overflow
> CPU: 0 PID: 2838 Comm: ssh Not tainted 3.13.0-rc8-juniper-00146-g19eca00 #4
> Call Trace:
>
> The reason is that we have used the wrong register to calculate the
> ksp_limit in commit cbc9565ee826 (powerpc: Remove ksp_limit on ppc64).
> Just fix it.
>
> As suggested by Benjamin Herrenschmidt, also add the C prototype of the
> function in the comment in order to avoid such kind of errors in the
> future.
>
> Cc: stable@vger.kernel.org # 3.12
> Reported-by: Guenter Roeck <linux@roeck-us.net>
> Tested-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> Thanks,
> Kevin
^ permalink raw reply
* Re: [RESEND][PATCH 0/2] Cleanup asm/scatterlist.h
From: Andrew Morton @ 2014-03-28 22:14 UTC (permalink / raw)
To: Laura Abbott
Cc: linux-ia64, Heiko Carstens, David Howells, Paul Mackerras,
H. Peter Anvin, sparclinux, Lennox Wu, Chen Liqin, Jesper Nilsson,
linux-am33-list, Russell King, linux-scsi, Hirokazu Takata, x86,
Ingo Molnar, Fenghua Yu, linux-s390, microblaze-uclinux,
Mikael Starvik, linux-m32r, Thomas Gleixner, linux-arm-kernel,
Michal Simek, Tony Luck, linux-cris-kernel, linux-kernel,
James E.J. Bottomley, linux-alpha, Martin Schwidefsky, linux390,
Koichi Yasutake, linuxppc-dev, David S. Miller
In-Reply-To: <1395512032-20575-1-git-send-email-lauraa@codeaurora.org>
On Sat, 22 Mar 2014 11:13:50 -0700 Laura Abbott <lauraa@codeaurora.org> wrote:
> I haven't gotten many responses so I'm going to try sending again
> (this time with a cover letter which I probably should have done in
> the first place...)
>
> ARCH_HAS_SG_CHAIN is currently defined as needed in asm/scatterlist.h.
> It was suggested[1] that this should probably be a proper Kconfig.
> At the same time, we can clean up most of the asm/scatterlist.h files
> to reduce redundancy. This makes parisc the only architecture that still
> has an asm/scatterlist.h file due to the #define sg_virt_addr (which
> could probably be cleaned up further still)
>
> Andrew, once we get a few more Acked-bys can we take this through your tree
> as suggested by Will?
Grabbed. It's super late for 3.15-rc1 and I'm thinking of merging this
in 3.16-rc1. Or I can maybe squeeze it into 3.15-rc2 is there's an
immediatish need for it?
^ permalink raw reply
* Re: [PATCH] powerpc/irq: Remove HAVE_IRQ_EXIT_ON_IRQ_STACK feature at powerpc platform
From: Kevin Hao @ 2014-03-29 1:20 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Ingo Molnar, James Hogan, jason.jin, Peter Zijlstra, fweisbec,
Helge Deller, linuxppc-dev, Heiko Carstens, Dongsheng Wang,
Paul Mackerras, linux-kernel, Martin Schwidefsky, Thomas Gleixner,
James E.J. Bottomley, H. Peter Anvin, scottwood, Andrew Morton,
Linus Torvalds, David S. Miller
In-Reply-To: <1396042027.11529.24.camel@pasglop>
[-- Attachment #1: Type: text/plain, Size: 517 bytes --]
On Sat, Mar 29, 2014 at 08:27:07AM +1100, Benjamin Herrenschmidt wrote:
> On Fri, 2014-03-28 at 16:18 +0800, Kevin Hao wrote:
>
> > powerpc: Set the correct ksp_limit on ppc32 when switching to irq stack
> >
>
> Kevin. It looks like it was applied to 3.14 and sent to 3.12 stable but
> not 3.13 ... can you fix that up ?
It was already merged into 3.13 stable since 3.13.6:
https://lkml.org/lkml/2014/3/4/787
I guess that Dongsheng didn't use the latest 3.13 stable tree.
Thanks,
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply
* [PATCH v2] powerpc/book3s: Recover from MC in opal on SCOM read via MMIO.
From: Mahesh J Salgaonkar @ 2014-03-29 4:57 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt; +Cc: Paul Mackerras, Anton Blanchard
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Detect and recover from machine check when inside opal on a special
scom load instructions. On specific SCOM read via MMIO we may get a machine
check exception with SRR0 pointing inside opal. To recover from MC
in this scenario, get a recovery instruction address and return to it from
MC.
OPAL will export the machine check recoverable ranges through
device tree node mcheck-recoverable-ranges under ibm,opal:
# hexdump /proc/device-tree/ibm,opal/mcheck-recoverable-ranges
0000000 0000 0000 3000 2804 0000 000c 0000 0000
0000010 3000 2814 0000 0000 3000 27f0 0000 000c
0000020 0000 0000 3000 2814 xxxx xxxx xxxx xxxx
0000030 llll llll yyyy yyyy yyyy yyyy
...
...
#
where:
xxxx xxxx xxxx xxxx = Starting instruction address
llll llll = Length of the address range.
yyyy yyyy yyyy yyyy = recovery address
Each recoverable address range entry is (start address, len,
recovery address), 2 cells each for start and recovery address, 1 cell for
len, totalling 5 cells per entry. During kernel boot time, build up the
recovery table with the list of recovery ranges from device-tree node which
will be used during machine check exception to recover from MMIO SCOM UE.
Changes in V2:
- Allocate mc_recoverable_range buffer based on number of entries
of recoverable ranges instead of device property size. Without this
change we end up allocating less memory and run into buffer corruption
issue.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/machdep.h | 3 +
arch/powerpc/include/asm/mce.h | 3 +
arch/powerpc/include/asm/opal.h | 3 +
arch/powerpc/kernel/mce.c | 4 +
arch/powerpc/kernel/mce_power.c | 37 +++++++++--
arch/powerpc/kernel/prom.c | 5 +
arch/powerpc/platforms/powernv/opal.c | 112 +++++++++++++++++++++++++++++++-
arch/powerpc/platforms/powernv/setup.c | 1
8 files changed, 158 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index ad3025d..4da6574 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -170,6 +170,9 @@ struct machdep_calls {
int (*system_reset_exception)(struct pt_regs *regs);
int (*machine_check_exception)(struct pt_regs *regs);
+ /* Called during machine check exception to retrive fixup address. */
+ bool (*mce_check_early_recovery)(struct pt_regs *regs);
+
/* Motherboard/chipset features. This is a kind of general purpose
* hook used to control some machine specific features (like reset
* lines, chip power control, etc...).
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
index 8e99edf..f97d8cb 100644
--- a/arch/powerpc/include/asm/mce.h
+++ b/arch/powerpc/include/asm/mce.h
@@ -187,7 +187,8 @@ struct mce_error_info {
#define MCE_EVENT_DONTRELEASE false
extern void save_mce_event(struct pt_regs *regs, long handled,
- struct mce_error_info *mce_err, uint64_t addr);
+ struct mce_error_info *mce_err, uint64_t nip,
+ uint64_t addr);
extern int get_mce_event(struct machine_check_event *mce, bool release);
extern void release_mce_event(void);
extern void machine_check_queue_event(void);
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index ed82142..ad67c40 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -833,6 +833,8 @@ int64_t opal_sync_host_reboot(void);
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+extern int early_init_dt_scan_recoverable_ranges(unsigned long node,
+ const char *uname, int depth, void *data);
extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
@@ -863,6 +865,7 @@ extern void opal_nvram_init(void);
extern void opal_flash_init(void);
extern int opal_machine_check(struct pt_regs *regs);
+extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
extern void opal_shutdown(void);
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index cadef7e..a7fd4cb 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -70,7 +70,7 @@ static void mce_set_error_info(struct machine_check_event *mce,
*/
void save_mce_event(struct pt_regs *regs, long handled,
struct mce_error_info *mce_err,
- uint64_t addr)
+ uint64_t nip, uint64_t addr)
{
uint64_t srr1;
int index = __get_cpu_var(mce_nest_count)++;
@@ -86,7 +86,7 @@ void save_mce_event(struct pt_regs *regs, long handled,
/* Populate generic machine check info */
mce->version = MCE_V1;
- mce->srr0 = regs->nip;
+ mce->srr0 = nip;
mce->srr1 = regs->msr;
mce->gpr3 = regs->gpr[3];
mce->in_use = 1;
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index 27c93f4..aa9aff3 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -26,6 +26,7 @@
#include <linux/ptrace.h>
#include <asm/mmu.h>
#include <asm/mce.h>
+#include <asm/machdep.h>
/* flush SLBs and reload */
static void flush_and_reload_slb(void)
@@ -197,13 +198,32 @@ static void mce_get_derror_p7(struct mce_error_info *mce_err, uint64_t dsisr)
}
}
+static long mce_handle_ue_error(struct pt_regs *regs)
+{
+ long handled = 0;
+
+ /*
+ * On specific SCOM read via MMIO we may get a machine check
+ * exception with SRR0 pointing inside opal. If that is the
+ * case OPAL may have recovery address to re-read SCOM data in
+ * different way and hence we can recover from this MC.
+ */
+
+ if (ppc_md.mce_check_early_recovery) {
+ if (ppc_md.mce_check_early_recovery(regs))
+ handled = 1;
+ }
+ return handled;
+}
+
long __machine_check_early_realmode_p7(struct pt_regs *regs)
{
- uint64_t srr1, addr;
+ uint64_t srr1, nip, addr;
long handled = 1;
struct mce_error_info mce_error_info = { 0 };
srr1 = regs->msr;
+ nip = regs->nip;
/*
* Handle memory errors depending whether this was a load/store or
@@ -221,7 +241,11 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
addr = regs->nip;
}
- save_mce_event(regs, handled, &mce_error_info, addr);
+ /* Handle UE error. */
+ if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
+ handled = mce_handle_ue_error(regs);
+
+ save_mce_event(regs, handled, &mce_error_info, nip, addr);
return handled;
}
@@ -263,11 +287,12 @@ static long mce_handle_derror_p8(uint64_t dsisr)
long __machine_check_early_realmode_p8(struct pt_regs *regs)
{
- uint64_t srr1, addr;
+ uint64_t srr1, nip, addr;
long handled = 1;
struct mce_error_info mce_error_info = { 0 };
srr1 = regs->msr;
+ nip = regs->nip;
if (P7_SRR1_MC_LOADSTORE(srr1)) {
handled = mce_handle_derror_p8(regs->dsisr);
@@ -279,6 +304,10 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs)
addr = regs->nip;
}
- save_mce_event(regs, handled, &mce_error_info, addr);
+ /* Handle UE error. */
+ if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
+ handled = mce_handle_ue_error(regs);
+
+ save_mce_event(regs, handled, &mce_error_info, nip, addr);
return handled;
}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f58c0d3..d711b7e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -752,6 +752,11 @@ void __init early_init_devtree(void *params)
spinning_secondaries = boot_cpu_count - 1;
#endif
+#ifdef CONFIG_PPC_POWERNV
+ /* Scan and build the list of machine check recoverable ranges */
+ of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
+#endif
+
DBG(" <- early_init_devtree()\n");
}
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 65499ad..f52762b 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -21,6 +21,7 @@
#include <linux/sched.h>
#include <linux/kobject.h>
#include <linux/delay.h>
+#include <linux/memblock.h>
#include <asm/opal.h>
#include <asm/firmware.h>
#include <asm/mce.h>
@@ -33,8 +34,18 @@ struct kobject *opal_kobj;
struct opal {
u64 base;
u64 entry;
+ u64 size;
} opal;
+struct mcheck_recoverable_range {
+ u64 start_addr;
+ u64 end_addr;
+ u64 recover_addr;
+};
+
+static struct mcheck_recoverable_range *mc_recoverable_range;
+static int mc_recoverable_range_len;
+
static struct device_node *opal_node;
static DEFINE_SPINLOCK(opal_write_lock);
extern u64 opal_mc_secondary_handler[];
@@ -49,25 +60,29 @@ static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
- const void *basep, *entryp;
- unsigned long basesz, entrysz;
+ const void *basep, *entryp, *sizep;
+ unsigned long basesz, entrysz, runtimesz;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0;
basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
+ sizep = of_get_flat_dt_prop(node, "opal-runtime-size", &runtimesz);
- if (!basep || !entryp)
+ if (!basep || !entryp || !sizep)
return 1;
opal.base = of_read_number(basep, basesz/4);
opal.entry = of_read_number(entryp, entrysz/4);
+ opal.size = of_read_number(sizep, runtimesz/4);
pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n",
opal.base, basep, basesz);
pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
opal.entry, entryp, entrysz);
+ pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%ld)\n",
+ opal.size, sizep, runtimesz);
powerpc_firmware_features |= FW_FEATURE_OPAL;
if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
@@ -84,6 +99,65 @@ int __init early_init_dt_scan_opal(unsigned long node,
return 1;
}
+int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ unsigned long i, psize, size;
+ const __be32 *prop;
+
+ if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
+ return 0;
+
+ prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize);
+
+ if (!prop)
+ return 1;
+
+ pr_debug("Found machine check recoverable ranges.\n");
+
+ /*
+ * Calculate number of available entries.
+ *
+ * Each recoverable address range entry is (start address, len,
+ * recovery address), 2 cells each for start and recovery address,
+ * 1 cell for len, totalling 5 cells per entry.
+ */
+ mc_recoverable_range_len = psize / (sizeof(*prop) * 5);
+
+ /* Sanity check */
+ if (!mc_recoverable_range_len)
+ return 1;
+
+ /* Size required to hold all the entries. */
+ size = mc_recoverable_range_len *
+ sizeof(struct mcheck_recoverable_range);
+
+ /*
+ * Allocate a buffer to hold the MC recoverable ranges. We would be
+ * accessing them in real mode, hence it needs to be within
+ * RMO region.
+ */
+ mc_recoverable_range = __va(memblock_alloc_base(size, __alignof__(u64),
+ ppc64_rma_size));
+ memset(mc_recoverable_range, 0, size);
+
+ for (i = 0; i < mc_recoverable_range_len; i++) {
+ mc_recoverable_range[i].start_addr =
+ of_read_number(prop + (i * 5) + 0, 2);
+ mc_recoverable_range[i].end_addr =
+ mc_recoverable_range[i].start_addr +
+ of_read_number(prop + (i * 5) + 2, 1);
+ mc_recoverable_range[i].recover_addr =
+ of_read_number(prop + (i * 5) + 3, 2);
+
+ pr_debug("Machine check recoverable range: %llx..%llx: %llx\n",
+ mc_recoverable_range[i].start_addr,
+ mc_recoverable_range[i].end_addr,
+ mc_recoverable_range[i].recover_addr);
+ }
+ return 1;
+}
+
static int __init opal_register_exception_handlers(void)
{
#ifdef __BIG_ENDIAN__
@@ -401,6 +475,38 @@ int opal_machine_check(struct pt_regs *regs)
return 0;
}
+static uint64_t find_recovery_address(uint64_t nip)
+{
+ int i;
+
+ for (i = 0; i < mc_recoverable_range_len; i++)
+ if ((nip >= mc_recoverable_range[i].start_addr) &&
+ (nip < mc_recoverable_range[i].end_addr))
+ return mc_recoverable_range[i].recover_addr;
+ return 0;
+}
+
+bool opal_mce_check_early_recovery(struct pt_regs *regs)
+{
+ uint64_t recover_addr = 0;
+
+ if (!opal.base || !opal.size)
+ goto out;
+
+ if ((regs->nip >= opal.base) &&
+ (regs->nip <= (opal.base + opal.size)))
+ recover_addr = find_recovery_address(regs->nip);
+
+ /*
+ * Setup regs->nip to rfi into fixup address.
+ */
+ if (recover_addr)
+ regs->nip = recover_addr;
+
+out:
+ return !!recover_addr;
+}
+
static irqreturn_t opal_interrupt(int irq, void *data)
{
__be64 events;
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 110f4fb..2d80845 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -188,6 +188,7 @@ static void __init pnv_setup_machdep_opal(void)
ppc_md.power_off = pnv_power_off;
ppc_md.halt = pnv_halt;
ppc_md.machine_check_exception = opal_machine_check;
+ ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
}
#ifdef CONFIG_PPC_POWERNV_RTAS
^ permalink raw reply related
* Re: Bug in reclaim logic with exhausted nodes?
From: Christoph Lameter @ 2014-03-29 5:40 UTC (permalink / raw)
To: Nishanth Aravamudan; +Cc: linux-mm, mgorman, linuxppc-dev, anton, rientjes
In-Reply-To: <20140327203354.GA16651@linux.vnet.ibm.com>
On Thu, 27 Mar 2014, Nishanth Aravamudan wrote:
> > That looks to be the correct way to handle things. Maybe mark the node as
> > offline or somehow not present so that the kernel ignores it.
>
> This is a SLUB condition:
>
> mm/slub.c::early_kmem_cache_node_alloc():
> ...
> page = new_slab(kmem_cache_node, GFP_NOWAIT, node);
> ...
So the page allocation from the node failed. We have a strange boot
condition where the OS is aware of anode but allocations on that node
fail.
> if (page_to_nid(page) != node) {
> printk(KERN_ERR "SLUB: Unable to allocate memory from "
> "node %d\n", node);
> printk(KERN_ERR "SLUB: Allocating a useless per node structure "
> "in order to be able to continue\n");
> }
> ...
>
> Since this is quite early, and we have not set up the nodemasks yet,
> does it make sense to perhaps have a temporary init-time nodemask that
> we set bits in here, and "fix-up" those nodes when we setup the
> nodemasks?
Please take care of this earlier than this. The page allocator in general
should allow allocations from all nodes with memory during boot,
^ permalink raw reply
* Re: [PATCH v2] powerpc/book3s: Recover from MC in opal on SCOM read via MMIO.
From: Benjamin Herrenschmidt @ 2014-03-29 11:41 UTC (permalink / raw)
To: Mahesh J Salgaonkar; +Cc: linuxppc-dev, Paul Mackerras, Anton Blanchard
In-Reply-To: <20140329045724.5158.19322.stgit@mars>
On Sat, 2014-03-29 at 10:27 +0530, Mahesh J Salgaonkar wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>
> Detect and recover from machine check when inside opal on a special
> scom load instructions. On specific SCOM read via MMIO we may get a machine
> check exception with SRR0 pointing inside opal. To recover from MC
> in this scenario, get a recovery instruction address and return to it from
> MC.
V1 is already in -next, please send an incremental patch.
Cheers,
Ben.
> OPAL will export the machine check recoverable ranges through
> device tree node mcheck-recoverable-ranges under ibm,opal:
>
> # hexdump /proc/device-tree/ibm,opal/mcheck-recoverable-ranges
> 0000000 0000 0000 3000 2804 0000 000c 0000 0000
> 0000010 3000 2814 0000 0000 3000 27f0 0000 000c
> 0000020 0000 0000 3000 2814 xxxx xxxx xxxx xxxx
> 0000030 llll llll yyyy yyyy yyyy yyyy
> ...
> ...
> #
>
> where:
> xxxx xxxx xxxx xxxx = Starting instruction address
> llll llll = Length of the address range.
> yyyy yyyy yyyy yyyy = recovery address
>
> Each recoverable address range entry is (start address, len,
> recovery address), 2 cells each for start and recovery address, 1 cell for
> len, totalling 5 cells per entry. During kernel boot time, build up the
> recovery table with the list of recovery ranges from device-tree node which
> will be used during machine check exception to recover from MMIO SCOM UE.
>
> Changes in V2:
> - Allocate mc_recoverable_range buffer based on number of entries
> of recoverable ranges instead of device property size. Without this
> change we end up allocating less memory and run into buffer corruption
> issue.
>
> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> ---
> arch/powerpc/include/asm/machdep.h | 3 +
> arch/powerpc/include/asm/mce.h | 3 +
> arch/powerpc/include/asm/opal.h | 3 +
> arch/powerpc/kernel/mce.c | 4 +
> arch/powerpc/kernel/mce_power.c | 37 +++++++++--
> arch/powerpc/kernel/prom.c | 5 +
> arch/powerpc/platforms/powernv/opal.c | 112 +++++++++++++++++++++++++++++++-
> arch/powerpc/platforms/powernv/setup.c | 1
> 8 files changed, 158 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
> index ad3025d..4da6574 100644
> --- a/arch/powerpc/include/asm/machdep.h
> +++ b/arch/powerpc/include/asm/machdep.h
> @@ -170,6 +170,9 @@ struct machdep_calls {
> int (*system_reset_exception)(struct pt_regs *regs);
> int (*machine_check_exception)(struct pt_regs *regs);
>
> + /* Called during machine check exception to retrive fixup address. */
> + bool (*mce_check_early_recovery)(struct pt_regs *regs);
> +
> /* Motherboard/chipset features. This is a kind of general purpose
> * hook used to control some machine specific features (like reset
> * lines, chip power control, etc...).
> diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h
> index 8e99edf..f97d8cb 100644
> --- a/arch/powerpc/include/asm/mce.h
> +++ b/arch/powerpc/include/asm/mce.h
> @@ -187,7 +187,8 @@ struct mce_error_info {
> #define MCE_EVENT_DONTRELEASE false
>
> extern void save_mce_event(struct pt_regs *regs, long handled,
> - struct mce_error_info *mce_err, uint64_t addr);
> + struct mce_error_info *mce_err, uint64_t nip,
> + uint64_t addr);
> extern int get_mce_event(struct machine_check_event *mce, bool release);
> extern void release_mce_event(void);
> extern void machine_check_queue_event(void);
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index ed82142..ad67c40 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -833,6 +833,8 @@ int64_t opal_sync_host_reboot(void);
>
> /* Internal functions */
> extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
> +extern int early_init_dt_scan_recoverable_ranges(unsigned long node,
> + const char *uname, int depth, void *data);
>
> extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
> extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
> @@ -863,6 +865,7 @@ extern void opal_nvram_init(void);
> extern void opal_flash_init(void);
>
> extern int opal_machine_check(struct pt_regs *regs);
> +extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
>
> extern void opal_shutdown(void);
>
> diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
> index cadef7e..a7fd4cb 100644
> --- a/arch/powerpc/kernel/mce.c
> +++ b/arch/powerpc/kernel/mce.c
> @@ -70,7 +70,7 @@ static void mce_set_error_info(struct machine_check_event *mce,
> */
> void save_mce_event(struct pt_regs *regs, long handled,
> struct mce_error_info *mce_err,
> - uint64_t addr)
> + uint64_t nip, uint64_t addr)
> {
> uint64_t srr1;
> int index = __get_cpu_var(mce_nest_count)++;
> @@ -86,7 +86,7 @@ void save_mce_event(struct pt_regs *regs, long handled,
>
> /* Populate generic machine check info */
> mce->version = MCE_V1;
> - mce->srr0 = regs->nip;
> + mce->srr0 = nip;
> mce->srr1 = regs->msr;
> mce->gpr3 = regs->gpr[3];
> mce->in_use = 1;
> diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
> index 27c93f4..aa9aff3 100644
> --- a/arch/powerpc/kernel/mce_power.c
> +++ b/arch/powerpc/kernel/mce_power.c
> @@ -26,6 +26,7 @@
> #include <linux/ptrace.h>
> #include <asm/mmu.h>
> #include <asm/mce.h>
> +#include <asm/machdep.h>
>
> /* flush SLBs and reload */
> static void flush_and_reload_slb(void)
> @@ -197,13 +198,32 @@ static void mce_get_derror_p7(struct mce_error_info *mce_err, uint64_t dsisr)
> }
> }
>
> +static long mce_handle_ue_error(struct pt_regs *regs)
> +{
> + long handled = 0;
> +
> + /*
> + * On specific SCOM read via MMIO we may get a machine check
> + * exception with SRR0 pointing inside opal. If that is the
> + * case OPAL may have recovery address to re-read SCOM data in
> + * different way and hence we can recover from this MC.
> + */
> +
> + if (ppc_md.mce_check_early_recovery) {
> + if (ppc_md.mce_check_early_recovery(regs))
> + handled = 1;
> + }
> + return handled;
> +}
> +
> long __machine_check_early_realmode_p7(struct pt_regs *regs)
> {
> - uint64_t srr1, addr;
> + uint64_t srr1, nip, addr;
> long handled = 1;
> struct mce_error_info mce_error_info = { 0 };
>
> srr1 = regs->msr;
> + nip = regs->nip;
>
> /*
> * Handle memory errors depending whether this was a load/store or
> @@ -221,7 +241,11 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
> addr = regs->nip;
> }
>
> - save_mce_event(regs, handled, &mce_error_info, addr);
> + /* Handle UE error. */
> + if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
> + handled = mce_handle_ue_error(regs);
> +
> + save_mce_event(regs, handled, &mce_error_info, nip, addr);
> return handled;
> }
>
> @@ -263,11 +287,12 @@ static long mce_handle_derror_p8(uint64_t dsisr)
>
> long __machine_check_early_realmode_p8(struct pt_regs *regs)
> {
> - uint64_t srr1, addr;
> + uint64_t srr1, nip, addr;
> long handled = 1;
> struct mce_error_info mce_error_info = { 0 };
>
> srr1 = regs->msr;
> + nip = regs->nip;
>
> if (P7_SRR1_MC_LOADSTORE(srr1)) {
> handled = mce_handle_derror_p8(regs->dsisr);
> @@ -279,6 +304,10 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs)
> addr = regs->nip;
> }
>
> - save_mce_event(regs, handled, &mce_error_info, addr);
> + /* Handle UE error. */
> + if (mce_error_info.error_type == MCE_ERROR_TYPE_UE)
> + handled = mce_handle_ue_error(regs);
> +
> + save_mce_event(regs, handled, &mce_error_info, nip, addr);
> return handled;
> }
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index f58c0d3..d711b7e 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -752,6 +752,11 @@ void __init early_init_devtree(void *params)
> spinning_secondaries = boot_cpu_count - 1;
> #endif
>
> +#ifdef CONFIG_PPC_POWERNV
> + /* Scan and build the list of machine check recoverable ranges */
> + of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
> +#endif
> +
> DBG(" <- early_init_devtree()\n");
> }
>
> diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> index 65499ad..f52762b 100644
> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -21,6 +21,7 @@
> #include <linux/sched.h>
> #include <linux/kobject.h>
> #include <linux/delay.h>
> +#include <linux/memblock.h>
> #include <asm/opal.h>
> #include <asm/firmware.h>
> #include <asm/mce.h>
> @@ -33,8 +34,18 @@ struct kobject *opal_kobj;
> struct opal {
> u64 base;
> u64 entry;
> + u64 size;
> } opal;
>
> +struct mcheck_recoverable_range {
> + u64 start_addr;
> + u64 end_addr;
> + u64 recover_addr;
> +};
> +
> +static struct mcheck_recoverable_range *mc_recoverable_range;
> +static int mc_recoverable_range_len;
> +
> static struct device_node *opal_node;
> static DEFINE_SPINLOCK(opal_write_lock);
> extern u64 opal_mc_secondary_handler[];
> @@ -49,25 +60,29 @@ static atomic_t opal_notifier_hold = ATOMIC_INIT(0);
> int __init early_init_dt_scan_opal(unsigned long node,
> const char *uname, int depth, void *data)
> {
> - const void *basep, *entryp;
> - unsigned long basesz, entrysz;
> + const void *basep, *entryp, *sizep;
> + unsigned long basesz, entrysz, runtimesz;
>
> if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
> return 0;
>
> basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
> entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
> + sizep = of_get_flat_dt_prop(node, "opal-runtime-size", &runtimesz);
>
> - if (!basep || !entryp)
> + if (!basep || !entryp || !sizep)
> return 1;
>
> opal.base = of_read_number(basep, basesz/4);
> opal.entry = of_read_number(entryp, entrysz/4);
> + opal.size = of_read_number(sizep, runtimesz/4);
>
> pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n",
> opal.base, basep, basesz);
> pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
> opal.entry, entryp, entrysz);
> + pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%ld)\n",
> + opal.size, sizep, runtimesz);
>
> powerpc_firmware_features |= FW_FEATURE_OPAL;
> if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
> @@ -84,6 +99,65 @@ int __init early_init_dt_scan_opal(unsigned long node,
> return 1;
> }
>
> +int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
> + const char *uname, int depth, void *data)
> +{
> + unsigned long i, psize, size;
> + const __be32 *prop;
> +
> + if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
> + return 0;
> +
> + prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize);
> +
> + if (!prop)
> + return 1;
> +
> + pr_debug("Found machine check recoverable ranges.\n");
> +
> + /*
> + * Calculate number of available entries.
> + *
> + * Each recoverable address range entry is (start address, len,
> + * recovery address), 2 cells each for start and recovery address,
> + * 1 cell for len, totalling 5 cells per entry.
> + */
> + mc_recoverable_range_len = psize / (sizeof(*prop) * 5);
> +
> + /* Sanity check */
> + if (!mc_recoverable_range_len)
> + return 1;
> +
> + /* Size required to hold all the entries. */
> + size = mc_recoverable_range_len *
> + sizeof(struct mcheck_recoverable_range);
> +
> + /*
> + * Allocate a buffer to hold the MC recoverable ranges. We would be
> + * accessing them in real mode, hence it needs to be within
> + * RMO region.
> + */
> + mc_recoverable_range = __va(memblock_alloc_base(size, __alignof__(u64),
> + ppc64_rma_size));
> + memset(mc_recoverable_range, 0, size);
> +
> + for (i = 0; i < mc_recoverable_range_len; i++) {
> + mc_recoverable_range[i].start_addr =
> + of_read_number(prop + (i * 5) + 0, 2);
> + mc_recoverable_range[i].end_addr =
> + mc_recoverable_range[i].start_addr +
> + of_read_number(prop + (i * 5) + 2, 1);
> + mc_recoverable_range[i].recover_addr =
> + of_read_number(prop + (i * 5) + 3, 2);
> +
> + pr_debug("Machine check recoverable range: %llx..%llx: %llx\n",
> + mc_recoverable_range[i].start_addr,
> + mc_recoverable_range[i].end_addr,
> + mc_recoverable_range[i].recover_addr);
> + }
> + return 1;
> +}
> +
> static int __init opal_register_exception_handlers(void)
> {
> #ifdef __BIG_ENDIAN__
> @@ -401,6 +475,38 @@ int opal_machine_check(struct pt_regs *regs)
> return 0;
> }
>
> +static uint64_t find_recovery_address(uint64_t nip)
> +{
> + int i;
> +
> + for (i = 0; i < mc_recoverable_range_len; i++)
> + if ((nip >= mc_recoverable_range[i].start_addr) &&
> + (nip < mc_recoverable_range[i].end_addr))
> + return mc_recoverable_range[i].recover_addr;
> + return 0;
> +}
> +
> +bool opal_mce_check_early_recovery(struct pt_regs *regs)
> +{
> + uint64_t recover_addr = 0;
> +
> + if (!opal.base || !opal.size)
> + goto out;
> +
> + if ((regs->nip >= opal.base) &&
> + (regs->nip <= (opal.base + opal.size)))
> + recover_addr = find_recovery_address(regs->nip);
> +
> + /*
> + * Setup regs->nip to rfi into fixup address.
> + */
> + if (recover_addr)
> + regs->nip = recover_addr;
> +
> +out:
> + return !!recover_addr;
> +}
> +
> static irqreturn_t opal_interrupt(int irq, void *data)
> {
> __be64 events;
> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
> index 110f4fb..2d80845 100644
> --- a/arch/powerpc/platforms/powernv/setup.c
> +++ b/arch/powerpc/platforms/powernv/setup.c
> @@ -188,6 +188,7 @@ static void __init pnv_setup_machdep_opal(void)
> ppc_md.power_off = pnv_power_off;
> ppc_md.halt = pnv_halt;
> ppc_md.machine_check_exception = opal_machine_check;
> + ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
> }
>
> #ifdef CONFIG_PPC_POWERNV_RTAS
^ permalink raw reply
* Re: [PATCH 6/7] DMA: Freescale: use spin_lock_bh instead of spin_lock_irqsave
From: Vinod Koul @ 2014-03-29 13:45 UTC (permalink / raw)
To: Hongbo Zhang
Cc: Vinod Koul, linux-kernel, scottwood, dmaengine, dan.j.williams,
linuxppc-dev
In-Reply-To: <533517C1.8080208@freescale.com>
On Fri, Mar 28, 2014 at 02:33:37PM +0800, Hongbo Zhang wrote:
>
> On 03/26/2014 03:01 PM, Vinod Koul wrote:
> >On Thu, 2014-01-16 at 13:47 +0800, hongbo.zhang@freescale.com wrote:
> >>From: Hongbo Zhang <hongbo.zhang@freescale.com>
> >>
> >>The usage of spin_lock_irqsave() is a stronger locking mechanism than is
> >>required throughout the driver. The minimum locking required should be used
> >>instead. Interrupts will be turned off and context will be saved, it is
> >>unnecessary to use irqsave.
> >>
> >>This patch changes all instances of spin_lock_irqsave() to spin_lock_bh(). All
> >>manipulation of protected fields is done using tasklet context or weaker, which
> >>makes spin_lock_bh() the correct choice.
> >>
> >> /**
> >>@@ -1124,11 +1120,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
> >> static void dma_do_tasklet(unsigned long data)
> >> {
> >> struct fsldma_chan *chan = (struct fsldma_chan *)data;
> >>- unsigned long flags;
> >> chan_dbg(chan, "tasklet entry\n");
> >>- spin_lock_irqsave(&chan->desc_lock, flags);
> >>+ spin_lock_bh(&chan->desc_lock);
> >okay here is the problem :(
> >
> >You moved to _bh variant. So if you grab the lock in rest of the code
> >and irq gets triggered then here we will be spinning to grab the lock.
> >So effectively you made right locking solution into deadlock situation!
>
> If the rest code grabs lock by spin_lock_bh(), and if irq raised,
> the tasklet could not be executed because it has been disabled by
> the _bh variant function.
yes if you are accessing resources only in tasklet and rest of the code, then
_bh variant works well. The problem here is usage in irq handler
--
~Vinod
^ permalink raw reply
* Re: [PATCH v2] phy/at8031: enable at8031 to work on interrupt mode
From: David Miller @ 2014-03-29 22:20 UTC (permalink / raw)
To: B45475
Cc: mugunthanvnm, B07421, netdev, helmut.schaa, linux-kernel, zonque,
R63061, linuxppc-dev
In-Reply-To: <1395992381-23094-1-git-send-email-B45475@freescale.com>
From: Zhao Qiang <B45475@freescale.com>
Date: Fri, 28 Mar 2014 15:39:41 +0800
> The at8031 can work on polling mode and interrupt mode.
> Add ack_interrupt and config intr funcs to enable
> interrupt mode for it.
>
> Signed-off-by: Zhao Qiang <B45475@freescale.com>
> ---
> changes for v2:
> - when interrupt is not enabled, write 0 to interrupt enbale register
> - delete a inner parens not needed
Applied to net-next, thanks.
^ permalink raw reply
* [PATCH] gpio: ge: Convert to platform driver
From: Alexander Shiyan @ 2014-03-30 5:14 UTC (permalink / raw)
To: linux-gpio
Cc: Alexandre Courbot, Linus Walleij, linuxppc-dev, Alexander Shiyan
This patch converts GE I/O FPGA GPIO driver to platform driver.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
Only compile tested.
---
drivers/gpio/gpio-ge.c | 176 ++++++++++++++++---------------------------------
1 file changed, 58 insertions(+), 118 deletions(-)
diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
index 7b95a4a..93efb29 100644
--- a/drivers/gpio/gpio-ge.c
+++ b/drivers/gpio/gpio-ge.c
@@ -18,15 +18,9 @@
*/
#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/init.h>
#include <linux/io.h>
-#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_platform.h>
#include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
#include <linux/module.h>
#define GEF_GPIO_DIRECT 0x00
@@ -39,28 +33,28 @@
#define GEF_GPIO_OVERRUN 0x1C
#define GEF_GPIO_MODE 0x20
-static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
+static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
+ struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
unsigned int data;
- data = ioread32be(reg);
+ data = ioread32be(mmchip->regs + GEF_GPIO_OUT);
/* value: 0=low; 1=high */
- if (value & 0x1)
- data = data | (0x1 << offset);
+ if (value)
+ data = data | BIT(offset);
else
- data = data & ~(0x1 << offset);
+ data = data & ~BIT(offset);
- iowrite32be(data, reg);
+ iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);
}
-
static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
{
unsigned int data;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
- data = data | (0x1 << offset);
+ data = data | BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
return 0;
@@ -71,11 +65,11 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
unsigned int data;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
- /* Set direction before switching to input */
- _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+ /* Set value before switching to output */
+ gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
- data = data & ~(0x1 << offset);
+ data = data & ~BIT(offset);
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
return 0;
@@ -83,116 +77,62 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- unsigned int data;
- int state = 0;
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
- data = ioread32be(mmchip->regs + GEF_GPIO_IN);
- state = (int)((data >> offset) & 0x1);
-
- return state;
+ return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));
}
-static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static const struct of_device_id gef_gpio_ids[] = {
+ {
+ .compatible = "gef,sbc610-gpio",
+ .data = (void *)19,
+ }, {
+ .compatible = "gef,sbc310-gpio",
+ .data = (void *)6,
+ }, {
+ .compatible = "ge,imp3a-gpio",
+ .data = (void *)16,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gef_gpio_ids);
+
+static int gef_gpio_probe(struct platform_device *pdev)
{
- struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+ const struct of_device_id *of_id =
+ of_match_device(gef_gpio_ids, &pdev->dev);
+ struct of_mm_gpio_chip *mmchip;
- _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
-}
+ if (!of_id)
+ return -ENOSYS;
-static int __init gef_gpio_init(void)
-{
- struct device_node *np;
- int retval;
- struct of_mm_gpio_chip *gef_gpio_chip;
-
- for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
-
- pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
- /* Allocate chip structure */
- gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
- if (!gef_gpio_chip) {
- pr_err("%s: Unable to allocate structure\n",
- np->full_name);
- continue;
- }
-
- /* Setup pointers to chip functions */
- gef_gpio_chip->gc.of_gpio_n_cells = 2;
- gef_gpio_chip->gc.ngpio = 19;
- gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
- gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
- gef_gpio_chip->gc.get = gef_gpio_get;
- gef_gpio_chip->gc.set = gef_gpio_set;
-
- /* This function adds a memory mapped GPIO chip */
- retval = of_mm_gpiochip_add(np, gef_gpio_chip);
- if (retval) {
- kfree(gef_gpio_chip);
- pr_err("%s: Unable to add GPIO\n", np->full_name);
- }
- }
-
- for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
-
- pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
- /* Allocate chip structure */
- gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
- if (!gef_gpio_chip) {
- pr_err("%s: Unable to allocate structure\n",
- np->full_name);
- continue;
- }
-
- /* Setup pointers to chip functions */
- gef_gpio_chip->gc.of_gpio_n_cells = 2;
- gef_gpio_chip->gc.ngpio = 6;
- gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
- gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
- gef_gpio_chip->gc.get = gef_gpio_get;
- gef_gpio_chip->gc.set = gef_gpio_set;
-
- /* This function adds a memory mapped GPIO chip */
- retval = of_mm_gpiochip_add(np, gef_gpio_chip);
- if (retval) {
- kfree(gef_gpio_chip);
- pr_err("%s: Unable to add GPIO\n", np->full_name);
- }
- }
-
- for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
-
- pr_debug("%s: Initialising GE GPIO\n", np->full_name);
-
- /* Allocate chip structure */
- gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
- if (!gef_gpio_chip) {
- pr_err("%s: Unable to allocate structure\n",
- np->full_name);
- continue;
- }
-
- /* Setup pointers to chip functions */
- gef_gpio_chip->gc.of_gpio_n_cells = 2;
- gef_gpio_chip->gc.ngpio = 16;
- gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
- gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
- gef_gpio_chip->gc.get = gef_gpio_get;
- gef_gpio_chip->gc.set = gef_gpio_set;
-
- /* This function adds a memory mapped GPIO chip */
- retval = of_mm_gpiochip_add(np, gef_gpio_chip);
- if (retval) {
- kfree(gef_gpio_chip);
- pr_err("%s: Unable to add GPIO\n", np->full_name);
- }
- }
+ mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL);
+ if (!mmchip)
+ return -ENOMEM;
- return 0;
+ /* Setup pointers to chip functions */
+ mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data;
+ mmchip->gc.of_gpio_n_cells = 2;
+ mmchip->gc.direction_input = gef_gpio_dir_in;
+ mmchip->gc.direction_output = gef_gpio_dir_out;
+ mmchip->gc.get = gef_gpio_get;
+ mmchip->gc.set = gef_gpio_set;
+
+ platform_set_drvdata(pdev, mmchip);
+
+ /* This function adds a memory mapped GPIO chip */
+ return of_mm_gpiochip_add(pdev->dev.of_node, mmchip);
+};
+
+static struct platform_driver gef_gpio_driver = {
+ .driver = {
+ .name = "gef-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = gef_gpio_ids,
+ },
+ .probe = gef_gpio_probe,
};
-arch_initcall(gef_gpio_init);
+module_platform_driver(gef_gpio_driver);
MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
--
1.8.3.2
^ permalink raw reply related
* [PATCH] powerpc/book3s: Fix mc_recoverable_range buffer overrun issue.
From: Mahesh J Salgaonkar @ 2014-03-30 5:33 UTC (permalink / raw)
To: linuxppc-dev, Benjamin Herrenschmidt; +Cc: Paul Mackerras, Anton Blanchard
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Currently we wrongly allocate mc_recoverable_range buffer (to hold
recoverable ranges) based on size of the property "mcheck-recoverable-ranges".
This results in allocating less memory to hold available recoverable range
entries from /proc/device-tree/ibm,opal/mcheck-recoverable-ranges.
This patch fixes this issue by allocating mc_recoverable_range buffer based
on number of entries of recoverable ranges instead of device property size.
Without this change we end up allocating less memory and run into memory
corruption issue.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/platforms/powernv/opal.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index d5f11d6..f4c011f 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -102,13 +102,13 @@ int __init early_init_dt_scan_opal(unsigned long node,
int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
const char *uname, int depth, void *data)
{
- unsigned long i, size;
+ unsigned long i, psize, size;
const __be32 *prop;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0;
- prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &size);
+ prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize);
if (!prop)
return 1;
@@ -116,6 +116,23 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
pr_debug("Found machine check recoverable ranges.\n");
/*
+ * Calculate number of available entries.
+ *
+ * Each recoverable address range entry is (start address, len,
+ * recovery address), 2 cells each for start and recovery address,
+ * 1 cell for len, totalling 5 cells per entry.
+ */
+ mc_recoverable_range_len = psize / (sizeof(*prop) * 5);
+
+ /* Sanity check */
+ if (!mc_recoverable_range_len)
+ return 1;
+
+ /* Size required to hold all the entries. */
+ size = mc_recoverable_range_len *
+ sizeof(struct mcheck_recoverable_range);
+
+ /*
* Allocate a buffer to hold the MC recoverable ranges. We would be
* accessing them in real mode, hence it needs to be within
* RMO region.
@@ -124,11 +141,7 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
ppc64_rma_size));
memset(mc_recoverable_range, 0, size);
- /*
- * Each recoverable address entry is an (start address,len,
- * recover address) pair, * 2 cells each, totalling 4 cells per entry.
- */
- for (i = 0; i < size / (sizeof(*prop) * 5); i++) {
+ for (i = 0; i < mc_recoverable_range_len; i++) {
mc_recoverable_range[i].start_addr =
of_read_number(prop + (i * 5) + 0, 2);
mc_recoverable_range[i].end_addr =
@@ -142,7 +155,6 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
mc_recoverable_range[i].end_addr,
mc_recoverable_range[i].recover_addr);
}
- mc_recoverable_range_len = i;
return 1;
}
^ permalink raw reply related
* Re: [PATCH 1/2] powerpc/powernv: Add OPAL message log interface
From: Stewart Smith @ 2014-03-30 22:21 UTC (permalink / raw)
To: Joel Stanley, benh, paulus, anton, shangw, hegdevasant, michael
Cc: linuxppc-dev
In-Reply-To: <1395964240-8305-2-git-send-email-joel@jms.id.au>
Joel Stanley <joel@jms.id.au> writes:
> OPAL provides an in-memory circular buffer containing a message log
> populated with various runtime messages produced by the firmware.
>
> Provide a sysfs interface /sys/firmware/opal/messages for userspace to
> view the messages.
Acked-by: Stewart Smith <stewart@linux.vnet.ibm.com>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/powerpc/include/asm/opal.h | 4 ++
> arch/powerpc/platforms/powernv/Makefile | 1 +
> arch/powerpc/platforms/powernv/opal-messages.c | 97 ++++++++++++++++++++++++++
> arch/powerpc/platforms/powernv/opal.c | 4 +-
> 4 files changed, 105 insertions(+), 1 deletion(-)
> create mode 100644 arch/powerpc/platforms/powernv/opal-messages.c
>
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index ffafab0..6aa757e 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -729,6 +729,9 @@ typedef struct oppanel_line {
> /* /sys/firmware/opal */
> extern struct kobject *opal_kobj;
>
> +/* /ibm,opal */
> +extern struct device_node *opal_node;
> +
> /* API functions */
> int64_t opal_console_write(int64_t term_number, __be64 *length,
> const uint8_t *buffer);
> @@ -918,6 +921,7 @@ extern void opal_flash_init(void);
> extern int opal_elog_init(void);
> extern void opal_platform_dump_init(void);
> extern void opal_sys_param_init(void);
> +extern void opal_messages_init(void);
>
> extern int opal_machine_check(struct pt_regs *regs);
> extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
> diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
> index f324ea0..e2ba418 100644
> --- a/arch/powerpc/platforms/powernv/Makefile
> +++ b/arch/powerpc/platforms/powernv/Makefile
> @@ -1,6 +1,7 @@
> obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
> obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
> obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
> +obj-y += opal-messages.o
>
> obj-$(CONFIG_SMP) += smp.o
> obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
> diff --git a/arch/powerpc/platforms/powernv/opal-messages.c b/arch/powerpc/platforms/powernv/opal-messages.c
> new file mode 100644
> index 0000000..3a863e8
> --- /dev/null
> +++ b/arch/powerpc/platforms/powernv/opal-messages.c
> @@ -0,0 +1,97 @@
> +/*
> + * PowerNV OPAL in-memory console interface
> + *
> + * Copyright 2014 IBM Corp.
> + *
> + * 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 <asm/io.h>
> +#include <asm/opal.h>
> +#include <linux/debugfs.h>
> +#include <linux/of.h>
> +#include <linux/types.h>
> +
> +/* OPAL in-memory console. Defined in OPAL source at core/console.c */
> +struct memcons {
> + __be64 magic;
> +#define MEMCONS_MAGIC 0x6630696567726173L
> + __be64 obuf_phys;
> + __be64 ibuf_phys;
> + __be32 obuf_size;
> + __be32 ibuf_size;
> + __be32 out_pos;
> +#define MEMCONS_OUT_POS_WRAP 0x80000000u
> +#define MEMCONS_OUT_POS_MASK 0x00ffffffu
> + __be32 in_prod;
> + __be32 in_cons;
> +};
> +
> +static ssize_t opal_messages_read(struct file *file, struct kobject *kobj,
> + struct bin_attribute *bin_attr, char *to, loff_t pos, size_t count)
> +{
> + struct memcons *mc = bin_attr->private;
> + const char *conbuf;
> + bool wrapped;
> + size_t num_read;
> + int out_pos;
> +
> + if (!mc)
> + return -ENODEV;
> +
> + conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
> + wrapped = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_WRAP;
> + out_pos = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_MASK;
> +
> + if (!wrapped) {
> + num_read = memory_read_from_buffer(to, count, &pos, conbuf,
> + out_pos);
> + } else {
> + num_read = memory_read_from_buffer(to, count, &pos,
> + conbuf + out_pos,
> + be32_to_cpu(mc->obuf_size) - out_pos);
> +
> + if (num_read < 0)
> + goto out;
> +
> + num_read += memory_read_from_buffer(to + num_read,
> + count - num_read, &pos, conbuf, out_pos);
> + }
> +out:
> + return num_read;
> +}
> +
> +static struct bin_attribute messages_attr = {
> + .attr = {.name = "messages", .mode = 0444},
> + .read = opal_messages_read
> +};
> +
> +void __init opal_messages_init(void)
> +{
> + u64 mcaddr;
> + struct memcons *mc;
> +
> + if (of_property_read_u64(opal_node, "ibm,opal-memcons", &mcaddr)) {
> + pr_warn("OPAL: Property ibm,opal-memcons not found, no message log\n");
> + return;
> + }
> +
> + mc = phys_to_virt(mcaddr);
> + if (!mc) {
> + pr_warn("OPAL: memory console address is invalid\n");
> + return;
> + }
> +
> + if (be64_to_cpu(mc->magic) != MEMCONS_MAGIC) {
> + pr_warn("OPAL: memory console version is invalid\n");
> + return;
> + }
> +
> + messages_attr.private = mc;
> +
> + if (sysfs_create_bin_file(opal_kobj, &messages_attr) != 0)
> + pr_warn("OPAL: sysfs file creation failed\n");
> +}
> diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> index e92f2f6..2bc032a 100644
> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -46,7 +46,7 @@ struct mcheck_recoverable_range {
> static struct mcheck_recoverable_range *mc_recoverable_range;
> static int mc_recoverable_range_len;
>
> -static struct device_node *opal_node;
> +struct device_node *opal_node;
> static DEFINE_SPINLOCK(opal_write_lock);
> extern u64 opal_mc_secondary_handler[];
> static unsigned int *opal_irqs;
> @@ -574,6 +574,8 @@ static int __init opal_init(void)
> opal_platform_dump_init();
> /* Setup system parameters interface */
> opal_sys_param_init();
> + /* Setup message log interface. */
> + opal_messages_init();
> }
>
> return 0;
> --
> 1.9.1
^ permalink raw reply
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Stewart Smith @ 2014-03-30 22:27 UTC (permalink / raw)
To: Greg Kurz, benh; +Cc: nfont, linuxppc-dev, paulus, linux-kernel, anton
In-Reply-To: <20140328073344.26823.32931.stgit@bahia.local>
Greg Kurz <gkurz@linux.vnet.ibm.com> writes:
> struct rtas_error_log {
> +#ifdef __BIG_ENDIAN__
> + /* Byte 0 */
> unsigned long version:8; /* Architectural version */
> + /* Byte 1 */
I think it would be great if we got rid of the usage of bitfields. As
soon as the mood of the compiler changes, this code is going to break.
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/powernv: Add OPAL message log interface
From: Michael Neuling @ 2014-03-31 4:08 UTC (permalink / raw)
To: Joel Stanley
Cc: stewart, michael, shangw, hegdevasant, paulus, anton,
linuxppc-dev
In-Reply-To: <1395964240-8305-2-git-send-email-joel@jms.id.au>
Joel Stanley <joel@jms.id.au> wrote:
> OPAL provides an in-memory circular buffer containing a message log
> populated with various runtime messages produced by the firmware.
>
> Provide a sysfs interface /sys/firmware/opal/messages for userspace to
> view the messages.
>
> Signed-off-by: Joel Stanley <joel@jms.id.au>
> ---
> arch/powerpc/include/asm/opal.h | 4 ++
> arch/powerpc/platforms/powernv/Makefile | 1 +
> arch/powerpc/platforms/powernv/opal-messages.c | 97 ++++++++++++++++++++++++++
> arch/powerpc/platforms/powernv/opal.c | 4 +-
> 4 files changed, 105 insertions(+), 1 deletion(-)
> create mode 100644 arch/powerpc/platforms/powernv/opal-messages.c
>
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index ffafab0..6aa757e 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -729,6 +729,9 @@ typedef struct oppanel_line {
> /* /sys/firmware/opal */
> extern struct kobject *opal_kobj;
>
> +/* /ibm,opal */
> +extern struct device_node *opal_node;
> +
> /* API functions */
> int64_t opal_console_write(int64_t term_number, __be64 *length,
> const uint8_t *buffer);
> @@ -918,6 +921,7 @@ extern void opal_flash_init(void);
> extern int opal_elog_init(void);
> extern void opal_platform_dump_init(void);
> extern void opal_sys_param_init(void);
> +extern void opal_messages_init(void);
>
> extern int opal_machine_check(struct pt_regs *regs);
> extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
> diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
> index f324ea0..e2ba418 100644
> --- a/arch/powerpc/platforms/powernv/Makefile
> +++ b/arch/powerpc/platforms/powernv/Makefile
> @@ -1,6 +1,7 @@
> obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
> obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
> obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
> +obj-y += opal-messages.o
>
> obj-$(CONFIG_SMP) += smp.o
> obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
> diff --git a/arch/powerpc/platforms/powernv/opal-messages.c b/arch/powerpc/platforms/powernv/opal-messages.c
> new file mode 100644
> index 0000000..3a863e8
> --- /dev/null
> +++ b/arch/powerpc/platforms/powernv/opal-messages.c
> @@ -0,0 +1,97 @@
> +/*
> + * PowerNV OPAL in-memory console interface
> + *
> + * Copyright 2014 IBM Corp.
> + *
> + * 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 <asm/io.h>
> +#include <asm/opal.h>
> +#include <linux/debugfs.h>
> +#include <linux/of.h>
> +#include <linux/types.h>
> +
> +/* OPAL in-memory console. Defined in OPAL source at core/console.c */
> +struct memcons {
> + __be64 magic;
> +#define MEMCONS_MAGIC 0x6630696567726173L
0x6630696567726173 == f0iegras ... Ben!!! :-P
> + __be64 obuf_phys;
> + __be64 ibuf_phys;
> + __be32 obuf_size;
> + __be32 ibuf_size;
> + __be32 out_pos;
> +#define MEMCONS_OUT_POS_WRAP 0x80000000u
> +#define MEMCONS_OUT_POS_MASK 0x00ffffffu
> + __be32 in_prod;
> + __be32 in_cons;
> +};
> +
> +static ssize_t opal_messages_read(struct file *file, struct kobject *kobj,
> + struct bin_attribute *bin_attr, char *to, loff_t pos, size_t count)
> +{
> + struct memcons *mc = bin_attr->private;
> + const char *conbuf;
> + bool wrapped;
> + size_t num_read;
> + int out_pos;
> +
> + if (!mc)
> + return -ENODEV;
> +
> + conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
> + wrapped = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_WRAP;
> + out_pos = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_MASK;
> +
Are there ordering issues we need to think about here with reading
these? Can the messages be written on another CPU at the same time as
these are being read?
What happens if in between reading wrapped and out_pos the buffer wraps?
You'd end up getting only a few bytes of console? Maybe you need to
read wrapped before and after out_pos to make should it's not wrapped in
between.
> + if (!wrapped) {
Why the negative case first? Just make it:
if (wrapped) {
wrapped case
} else {
not wrapped case
}
Also, no curlies needed for single statement.
> + num_read = memory_read_from_buffer(to, count, &pos, conbuf,
> + out_pos);
This is probably not necessary, but do we need to sanity check out_pos <
obuf_size? I guess we don't generally sanity check numbers from OPAL as
it can screw us in many other ways anyway.
> + } else {
> + num_read = memory_read_from_buffer(to, count, &pos,
> + conbuf + out_pos,
> + be32_to_cpu(mc->obuf_size) - out_pos);
> +
> + if (num_read < 0)
> + goto out;
> +
> + num_read += memory_read_from_buffer(to + num_read,
> + count - num_read, &pos, conbuf,
> out_pos);
What if this second read returns an error? num_read += -ERRNO? I think
you need to check this return independently.
Mikey
> + }
> +out:
> + return num_read;
> +}
> +
> +static struct bin_attribute messages_attr = {
> + .attr = {.name = "messages", .mode = 0444},
> + .read = opal_messages_read
> +};
> +
> +void __init opal_messages_init(void)
> +{
> + u64 mcaddr;
> + struct memcons *mc;
> +
> + if (of_property_read_u64(opal_node, "ibm,opal-memcons", &mcaddr)) {
> + pr_warn("OPAL: Property ibm,opal-memcons not found, no message log\n");
> + return;
> + }
> +
> + mc = phys_to_virt(mcaddr);
> + if (!mc) {
> + pr_warn("OPAL: memory console address is invalid\n");
> + return;
> + }
> +
> + if (be64_to_cpu(mc->magic) != MEMCONS_MAGIC) {
> + pr_warn("OPAL: memory console version is invalid\n");
> + return;
> + }
> +
> + messages_attr.private = mc;
> +
> + if (sysfs_create_bin_file(opal_kobj, &messages_attr) != 0)
> + pr_warn("OPAL: sysfs file creation failed\n");
> +}
> diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> index e92f2f6..2bc032a 100644
> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -46,7 +46,7 @@ struct mcheck_recoverable_range {
> static struct mcheck_recoverable_range *mc_recoverable_range;
> static int mc_recoverable_range_len;
>
> -static struct device_node *opal_node;
> +struct device_node *opal_node;
> static DEFINE_SPINLOCK(opal_write_lock);
> extern u64 opal_mc_secondary_handler[];
> static unsigned int *opal_irqs;
> @@ -574,6 +574,8 @@ static int __init opal_init(void)
> opal_platform_dump_init();
> /* Setup system parameters interface */
> opal_sys_param_init();
> + /* Setup message log interface. */
> + opal_messages_init();
> }
>
> return 0;
> --
> 1.9.1
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 6/7] DMA: Freescale: use spin_lock_bh instead of spin_lock_irqsave
From: Hongbo Zhang @ 2014-03-31 4:08 UTC (permalink / raw)
To: Vinod Koul
Cc: Vinod Koul, linux-kernel, scottwood, dmaengine, dan.j.williams,
linuxppc-dev
In-Reply-To: <20140329134528.GQ1976@intel.com>
On 03/29/2014 09:45 PM, Vinod Koul wrote:
> On Fri, Mar 28, 2014 at 02:33:37PM +0800, Hongbo Zhang wrote:
>> On 03/26/2014 03:01 PM, Vinod Koul wrote:
>>> On Thu, 2014-01-16 at 13:47 +0800, hongbo.zhang@freescale.com wrote:
>>>> From: Hongbo Zhang <hongbo.zhang@freescale.com>
>>>>
>>>> The usage of spin_lock_irqsave() is a stronger locking mechanism than is
>>>> required throughout the driver. The minimum locking required should be used
>>>> instead. Interrupts will be turned off and context will be saved, it is
>>>> unnecessary to use irqsave.
>>>>
>>>> This patch changes all instances of spin_lock_irqsave() to spin_lock_bh(). All
>>>> manipulation of protected fields is done using tasklet context or weaker, which
>>>> makes spin_lock_bh() the correct choice.
>>>>
>
>>>> /**
>>>> @@ -1124,11 +1120,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
>>>> static void dma_do_tasklet(unsigned long data)
>>>> {
>>>> struct fsldma_chan *chan = (struct fsldma_chan *)data;
>>>> - unsigned long flags;
>>>> chan_dbg(chan, "tasklet entry\n");
>>>> - spin_lock_irqsave(&chan->desc_lock, flags);
>>>> + spin_lock_bh(&chan->desc_lock);
>>> okay here is the problem :(
>>>
>>> You moved to _bh variant. So if you grab the lock in rest of the code
>>> and irq gets triggered then here we will be spinning to grab the lock.
>>> So effectively you made right locking solution into deadlock situation!
>> If the rest code grabs lock by spin_lock_bh(), and if irq raised,
>> the tasklet could not be executed because it has been disabled by
>> the _bh variant function.
> yes if you are accessing resources only in tasklet and rest of the code, then
> _bh variant works well. The problem here is usage in irq handler
>
The name dma_do_tasklet may mislead, it is tasklet handler, not irq
handler, not a trigger to load tasklet.
the irq handler is fsldma_chan_irq, and I don't use lock in it.
If it is the problem, I would like to change dma_do_tasklet to
dma_tasklet to eliminate misleading.
^ permalink raw reply
* Re: [PATCH v5 1/3] powernv, cpufreq: Select CPUFreq related Kconfig options for powernv
From: Viresh Kumar @ 2014-03-31 4:21 UTC (permalink / raw)
To: Gautham R. Shenoy
Cc: Linux PM list, Rafael J. Wysocki, Linux Kernel Mailing List,
cpufreq@vger.kernel.org, linuxppc-dev@ozlabs.org, Anton Blanchard,
Srivatsa S. Bhat
In-Reply-To: <1396037484-23907-2-git-send-email-ego@linux.vnet.ibm.com>
On 29 March 2014 01:41, Gautham R. Shenoy <ego@linux.vnet.ibm.com> wrote:
> From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
>
> Enable CPUFreq for PowerNV. Select "performance", "powersave",
> "userspace" and "ondemand" governors. Choose "ondemand" to be the
> default governor.
>
> Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> ---
> arch/powerpc/configs/pseries_defconfig | 1 +
> arch/powerpc/configs/pseries_le_defconfig | 1 +
> arch/powerpc/platforms/powernv/Kconfig | 6 ++++++
> 3 files changed, 8 insertions(+)
Probably it doesn't make much sense to keep this as the first patch
as you still don't have the driver available yet.
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/powernv: Add OPAL message log interface
From: Michael Neuling @ 2014-03-31 4:21 UTC (permalink / raw)
Cc: stewart, michael, shangw, hegdevasant, paulus, Joel Stanley,
linuxppc-dev, anton
In-Reply-To: <21604.1396238935@ale.ozlabs.ibm.com>
Michael Neuling <mikey@neuling.org> wrote:
> Joel Stanley <joel@jms.id.au> wrote:
>
> > OPAL provides an in-memory circular buffer containing a message log
> > populated with various runtime messages produced by the firmware.
> >
> > Provide a sysfs interface /sys/firmware/opal/messages for userspace to
> > view the messages.
> >
> > Signed-off-by: Joel Stanley <joel@jms.id.au>
> > ---
> > arch/powerpc/include/asm/opal.h | 4 ++
> > arch/powerpc/platforms/powernv/Makefile | 1 +
> > arch/powerpc/platforms/powernv/opal-messages.c | 97 ++++++++++++++++++++++++++
> > arch/powerpc/platforms/powernv/opal.c | 4 +-
> > 4 files changed, 105 insertions(+), 1 deletion(-)
> > create mode 100644 arch/powerpc/platforms/powernv/opal-messages.c
> >
> > diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> > index ffafab0..6aa757e 100644
> > --- a/arch/powerpc/include/asm/opal.h
> > +++ b/arch/powerpc/include/asm/opal.h
> > @@ -729,6 +729,9 @@ typedef struct oppanel_line {
> > /* /sys/firmware/opal */
> > extern struct kobject *opal_kobj;
> >
> > +/* /ibm,opal */
> > +extern struct device_node *opal_node;
> > +
> > /* API functions */
> > int64_t opal_console_write(int64_t term_number, __be64 *length,
> > const uint8_t *buffer);
> > @@ -918,6 +921,7 @@ extern void opal_flash_init(void);
> > extern int opal_elog_init(void);
> > extern void opal_platform_dump_init(void);
> > extern void opal_sys_param_init(void);
> > +extern void opal_messages_init(void);
> >
> > extern int opal_machine_check(struct pt_regs *regs);
> > extern bool opal_mce_check_early_recovery(struct pt_regs *regs);
> > diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
> > index f324ea0..e2ba418 100644
> > --- a/arch/powerpc/platforms/powernv/Makefile
> > +++ b/arch/powerpc/platforms/powernv/Makefile
> > @@ -1,6 +1,7 @@
> > obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
> > obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
> > obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
> > +obj-y += opal-messages.o
> >
> > obj-$(CONFIG_SMP) += smp.o
> > obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
> > diff --git a/arch/powerpc/platforms/powernv/opal-messages.c b/arch/powerpc/platforms/powernv/opal-messages.c
> > new file mode 100644
> > index 0000000..3a863e8
> > --- /dev/null
> > +++ b/arch/powerpc/platforms/powernv/opal-messages.c
> > @@ -0,0 +1,97 @@
> > +/*
> > + * PowerNV OPAL in-memory console interface
> > + *
> > + * Copyright 2014 IBM Corp.
> > + *
> > + * 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 <asm/io.h>
> > +#include <asm/opal.h>
> > +#include <linux/debugfs.h>
> > +#include <linux/of.h>
> > +#include <linux/types.h>
> > +
> > +/* OPAL in-memory console. Defined in OPAL source at core/console.c */
> > +struct memcons {
> > + __be64 magic;
> > +#define MEMCONS_MAGIC 0x6630696567726173L
>
> 0x6630696567726173 == f0iegras ... Ben!!! :-P
>
> > + __be64 obuf_phys;
> > + __be64 ibuf_phys;
> > + __be32 obuf_size;
> > + __be32 ibuf_size;
> > + __be32 out_pos;
> > +#define MEMCONS_OUT_POS_WRAP 0x80000000u
> > +#define MEMCONS_OUT_POS_MASK 0x00ffffffu
> > + __be32 in_prod;
> > + __be32 in_cons;
> > +};
> > +
> > +static ssize_t opal_messages_read(struct file *file, struct kobject *kobj,
> > + struct bin_attribute *bin_attr, char *to, loff_t pos, size_t count)
> > +{
> > + struct memcons *mc = bin_attr->private;
> > + const char *conbuf;
> > + bool wrapped;
> > + size_t num_read;
> > + int out_pos;
> > +
> > + if (!mc)
> > + return -ENODEV;
> > +
> > + conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
> > + wrapped = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_WRAP;
> > + out_pos = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_MASK;
> > +
>
> Are there ordering issues we need to think about here with reading
> these? Can the messages be written on another CPU at the same time as
> these are being read?
>
> What happens if in between reading wrapped and out_pos the buffer wraps?
> You'd end up getting only a few bytes of console? Maybe you need to
> read wrapped before and after out_pos to make should it's not wrapped in
> between.
wrapped = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_WRAP;
out_pos = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_MASK;
OK, I just realised this is reading from the same location. So yeah,
don't do that. Read it once and calculate wrapped and out_pos from that
single read.
>
> > + if (!wrapped) {
>
> Why the negative case first? Just make it:
>
> if (wrapped) {
> wrapped case
> } else {
> not wrapped case
> }
>
> Also, no curlies needed for single statement.
>
>
> > + num_read = memory_read_from_buffer(to, count, &pos, conbuf,
> > + out_pos);
>
> This is probably not necessary, but do we need to sanity check out_pos <
> obuf_size? I guess we don't generally sanity check numbers from OPAL as
> it can screw us in many other ways anyway.
>
> > + } else {
> > + num_read = memory_read_from_buffer(to, count, &pos,
> > + conbuf + out_pos,
> > + be32_to_cpu(mc->obuf_size) - out_pos);
> > +
> > + if (num_read < 0)
> > + goto out;
> > +
> > + num_read += memory_read_from_buffer(to + num_read,
> > + count - num_read, &pos, conbuf,
> > out_pos);
>
> What if this second read returns an error? num_read += -ERRNO? I think
> you need to check this return independently.
>
> Mikey
>
> > + }
> > +out:
> > + return num_read;
> > +}
> > +
> > +static struct bin_attribute messages_attr = {
> > + .attr = {.name = "messages", .mode = 0444},
> > + .read = opal_messages_read
> > +};
> > +
> > +void __init opal_messages_init(void)
> > +{
> > + u64 mcaddr;
> > + struct memcons *mc;
> > +
> > + if (of_property_read_u64(opal_node, "ibm,opal-memcons", &mcaddr)) {
> > + pr_warn("OPAL: Property ibm,opal-memcons not found, no message log\n");
> > + return;
> > + }
> > +
> > + mc = phys_to_virt(mcaddr);
> > + if (!mc) {
> > + pr_warn("OPAL: memory console address is invalid\n");
> > + return;
> > + }
> > +
> > + if (be64_to_cpu(mc->magic) != MEMCONS_MAGIC) {
> > + pr_warn("OPAL: memory console version is invalid\n");
> > + return;
> > + }
> > +
> > + messages_attr.private = mc;
> > +
> > + if (sysfs_create_bin_file(opal_kobj, &messages_attr) != 0)
> > + pr_warn("OPAL: sysfs file creation failed\n");
> > +}
> > diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> > index e92f2f6..2bc032a 100644
> > --- a/arch/powerpc/platforms/powernv/opal.c
> > +++ b/arch/powerpc/platforms/powernv/opal.c
> > @@ -46,7 +46,7 @@ struct mcheck_recoverable_range {
> > static struct mcheck_recoverable_range *mc_recoverable_range;
> > static int mc_recoverable_range_len;
> >
> > -static struct device_node *opal_node;
> > +struct device_node *opal_node;
> > static DEFINE_SPINLOCK(opal_write_lock);
> > extern u64 opal_mc_secondary_handler[];
> > static unsigned int *opal_irqs;
> > @@ -574,6 +574,8 @@ static int __init opal_init(void)
> > opal_platform_dump_init();
> > /* Setup system parameters interface */
> > opal_sys_param_init();
> > + /* Setup message log interface. */
> > + opal_messages_init();
> > }
> >
> > return 0;
> > --
> > 1.9.1
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH v5 0/3] powernv, cpufreq: Dynamic Frequency Scaling support
From: Viresh Kumar @ 2014-03-31 4:25 UTC (permalink / raw)
To: Gautham R. Shenoy
Cc: Linux PM list, Rafael J. Wysocki, Linux Kernel Mailing List,
cpufreq@vger.kernel.org, linuxppc-dev@ozlabs.org, Anton Blanchard,
Srivatsa S. Bhat
In-Reply-To: <1396037484-23907-1-git-send-email-ego@linux.vnet.ibm.com>
On 29 March 2014 01:41, Gautham R. Shenoy <ego@linux.vnet.ibm.com> wrote:
> From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
>
> Hi,
>
> This is v5 of the patchset to enable dynamic frequency scaling on IBM
> PowerNV platforms. This patchset does address all the review comments
> obtained for v4 (which can be found at [1]).
>
> Changes from v4:
>
> * Created a separate patch to select the CPUFreq related Config
> options for PowerNV
>
> * Dropped the per-core locking hunks in
> drivers/cpufreq/powernv-cpufreq.c since the CPUFreq core takes
> care of the for us after the following commit which is present in
> linux-next:
>
> commit 12478cf0c55e5969f740bb38a24b1a0104ae18d8
> Author: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> Date: Mon Mar 24 13:35:44 2014 +0530
>
> cpufreq: Make sure frequency transitions are serialized
>
> * [PATCH v5 3/3] gets rid of the powernv_pstate_ids[] array that
> was being used to record the pstate ids. After the following
> patch it is safe to use cpufreq_frequency_table.driver_data
> since it is opaque to the cpufreq core:
>
> From: Viresh Kumar <viresh.kumar@linaro.org>
> Date: 2014-03-28 13:53:47
> url: http://marc.info/?l=linux-pm&m=139601416804702&w=2
>
> cpufreq: create another field .flags in cpufreq_frequency_table
>
> The patchset is based on the commit
> 201544be8c37dffbf069bb5fc9edb5674f8c1754 of the linux-next tree.
>
> While all the patches in the patchset apply cleanly on linux-next,
> [PATCH v5 3/3] requires the Viresh's patch that was mentioned
> above. Otherwise, the frequency corresponding to pstate id -3 will be
> omited while reporting the "scaling_available_frequencies" in sysfs.
>
> [1]: http://marc.info/?l=linux-pm&m=139585297620612&w=2
>
> Gautham R. Shenoy (2):
> powernv, cpufreq: Select CPUFreq related Kconfig options for powernv
Make this patch 3/3 (Probably Rafael can do this while applying)
> powernv,cpufreq: Use cpufreq_frequency_table.driver_data to store
> pstate ids
>
> Vaidyanathan Srinivasan (1):
> powernv, cpufreq: cpufreq driver for powernv platform
Otherwise,
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
^ permalink raw reply
* RE: [PATCH v2] fix wrong usage of dmaengine_unmap_put in async_xxx
From: Xuelin Shi @ 2014-03-31 6:54 UTC (permalink / raw)
To: vinod.koul@intel.com, dan.j.williams@intel.com
Cc: dmaengine@vger.kernel.org, Xuelin Shi,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1395303385-29461-1-git-send-email-xuelin.shi@freescale.com>
SGkgRGFuICYgdmlub2QsDQoNCkhhdmUgeW91IGdvdCBhIGNoYW5jZSB0byBzZWUgdGhpcyBwYXRj
aD8NCg0KQWxzbyB3aGF0J3MgeW91ciBjb21tZW50IGFib3V0IHRoZSAgUmFpZEVuZ2luZSBkcml2
ZXIgcGF0Y2g/DQoNClRoYW5rcywNClh1ZWxpbiBTaGkNCg0KLS0tLS1PcmlnaW5hbCBNZXNzYWdl
LS0tLS0NCkZyb206IHh1ZWxpbi5zaGlAZnJlZXNjYWxlLmNvbSBbbWFpbHRvOnh1ZWxpbi5zaGlA
ZnJlZXNjYWxlLmNvbV0gDQpTZW50OiAyMDE0xOoz1MIyMMjVIDE2OjE2DQpUbzogdmlub2Qua291
bEBpbnRlbC5jb207IGRhbi5qLndpbGxpYW1zQGludGVsLmNvbQ0KQ2M6IGRtYWVuZ2luZUB2Z2Vy
Lmtlcm5lbC5vcmc7IGxpbnV4cHBjLWRldkBsaXN0cy5vemxhYnMub3JnOyBTaGkgWHVlbGluLUIy
OTIzNw0KU3ViamVjdDogW1BBVENIIHYyXSBmaXggd3JvbmcgdXNhZ2Ugb2YgZG1hZW5naW5lX3Vu
bWFwX3B1dCBpbiBhc3luY194eHgNCg0KRnJvbTogWHVlbGluIFNoaSA8eHVlbGluLnNoaUBmcmVl
c2NhbGUuY29tPg0KDQpkbWFlbmdpbmVfdW5tYXBfcHV0IGRvZXMgYmVsb3cgdHdvIHRoaW5nczoN
CmEpIHVubWFwIHBhZ2VzIGZvciBzcmNzIGFuZCBkZXN0cw0KYikgZnJlZSB1bm1hcCBzdHJ1Y3QN
Cg0KVGhlIHVubWFwIHN0cnVjdCBkYXRhIGlzIGdlbmVyYXRlZCBidXQgb25seSBpbml0aWFsaXpl
ZCB3aGlsZSBvdGhlciBzb21lIGRtYSBjb250aW9ucyBhcmUgbWV0LCBsaWtlIGRtYSBhbGlnbm1l
bnQgZXRjLg0KSWYgdGhlIHVubWFwIGRhdGEgaXMgbm90IGluaXRpYWxpemVkLCBjYWxsIGRtYWVu
Z2luZV91bm1hcF9wdXQgd2lsbCB1bm1hcCBzb21lIHJhbmRvbSBkYXRhIGluIHVubWFwLT5hZGRy
Wy4uLl0NCg0KQWxzbyBjYWxsIGRtYWVuZ2luZV9nZXRfdW5tYXBfZGF0YSBpbW1lZGlhdGFsbHkg
YWZ0ZXIgZ2VuZXJhdGluZyB0eCBpcyBub3QgY29ycmVjdC4gTWF5YmUgdGhlIHR4IGhhcyBub3Qg
YmVlbiBmaW5pc2hlZCBieSBETUEgaGFyZHdhcmUgeWV0IGJ1dCB0aGUgc3JjcyBhbmQgZGVzdHMg
YXJlIGRtYSB1bm1hcHBlZC4NCg0KVGhpcyBwYXRjaCBmaXhlZCBhYm92ZSB0d28gaXNzdWVzIGJ5
Og0KYSkgb25seSBnZW5lcmF0ZXMgdW5tYXAgc3RydWN0IGRhdGEgd2hlbiBvdGhlciBkbWEgY29u
ZGl0aW9ucyBhcmUgbWV0Lg0KYikgZWxpbWluYXRlcyBkbWFlbmdpbmVfdW5tYXBfcHV0IHdoZW4g
dHggaXMgZ2VuZXJhdGVkIGJlY2F1c2UgdHgga25vd2VzIHRoZSBiZXN0IHRpbWUgdG8gdW5tYXAg
aXQgKGluIGludGVycnVwdCBwcm9jZXNzaW5nKS4NCg0KU2lnbmVkLW9mZi1ieTogWHVlbGluIFNo
aSA8eHVlbGluLnNoaUBmcmVlc2NhbGUuY29tPg0KLS0tDQpjaGFuZ2UgbG9nOg0KCXYxOiBpbmNs
dWRlIGNoYW5nZSBpbiBhc3luY19tZW1jcHksIGFzeW5jX3hvciwgYXN5bmNfcHENCiAJdjI6IGFk
ZCBjaGFuZ2UgaW4gYXN5bmNfcmFpZDZfcmVjb3YuYyBhbmQgZml4IHNvbWUgc3R5bGUgaXNzdWUN
Cg0KIGNyeXB0by9hc3luY190eC9hc3luY19tZW1jcHkuYyAgICAgIHwgIDgwICsrKysrKysrLS0t
LS0tLQ0KIGNyeXB0by9hc3luY190eC9hc3luY19wcS5jICAgICAgICAgIHwgMTg5ICsrKysrKysr
KysrKysrKysrKystLS0tLS0tLS0tLS0tLS0tLQ0KIGNyeXB0by9hc3luY190eC9hc3luY19yYWlk
Nl9yZWNvdi5jIHwgMTA4ICsrKysrKysrKysrLS0tLS0tLS0tLQ0KIGNyeXB0by9hc3luY190eC9h
c3luY194b3IuYyAgICAgICAgIHwgMTY0ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tLS0N
CiA0IGZpbGVzIGNoYW5nZWQsIDI4NiBpbnNlcnRpb25zKCspLCAyNTUgZGVsZXRpb25zKC0pDQoN
CmRpZmYgLS1naXQgYS9jcnlwdG8vYXN5bmNfdHgvYXN5bmNfbWVtY3B5LmMgYi9jcnlwdG8vYXN5
bmNfdHgvYXN5bmNfbWVtY3B5LmMgaW5kZXggZjhjMGI4ZC4uNjU0NmU4NyAxMDA2NDQNCi0tLSBh
L2NyeXB0by9hc3luY190eC9hc3luY19tZW1jcHkuYw0KKysrIGIvY3J5cHRvL2FzeW5jX3R4L2Fz
eW5jX21lbWNweS5jDQpAQCAtNTEsMTEgKzUxLDEwIEBAIGFzeW5jX21lbWNweShzdHJ1Y3QgcGFn
ZSAqZGVzdCwgc3RydWN0IHBhZ2UgKnNyYywgdW5zaWduZWQgaW50IGRlc3Rfb2Zmc2V0LA0KIAlz
dHJ1Y3QgZG1hX2RldmljZSAqZGV2aWNlID0gY2hhbiA/IGNoYW4tPmRldmljZSA6IE5VTEw7DQog
CXN0cnVjdCBkbWFfYXN5bmNfdHhfZGVzY3JpcHRvciAqdHggPSBOVUxMOw0KIAlzdHJ1Y3QgZG1h
ZW5naW5lX3VubWFwX2RhdGEgKnVubWFwID0gTlVMTDsNCisJdm9pZCAqZGVzdF9idWYsICpzcmNf
YnVmOw0KIA0KLQlpZiAoZGV2aWNlKQ0KLQkJdW5tYXAgPSBkbWFlbmdpbmVfZ2V0X3VubWFwX2Rh
dGEoZGV2aWNlLT5kZXYsIDIsIEdGUF9OT0lPKTsNCi0NCi0JaWYgKHVubWFwICYmIGlzX2RtYV9j
b3B5X2FsaWduZWQoZGV2aWNlLCBzcmNfb2Zmc2V0LCBkZXN0X29mZnNldCwgbGVuKSkgew0KKwlp
ZiAoZGV2aWNlICYmDQorCSAgICBpc19kbWFfY29weV9hbGlnbmVkKGRldmljZSwgc3JjX29mZnNl
dCwgZGVzdF9vZmZzZXQsIGxlbikpIHsNCiAJCXVuc2lnbmVkIGxvbmcgZG1hX3ByZXBfZmxhZ3Mg
PSAwOw0KIA0KIAkJaWYgKHN1Ym1pdC0+Y2JfZm4pDQpAQCAtNjMsNDUgKzYyLDU2IEBAIGFzeW5j
X21lbWNweShzdHJ1Y3QgcGFnZSAqZGVzdCwgc3RydWN0IHBhZ2UgKnNyYywgdW5zaWduZWQgaW50
IGRlc3Rfb2Zmc2V0LA0KIAkJaWYgKHN1Ym1pdC0+ZmxhZ3MgJiBBU1lOQ19UWF9GRU5DRSkNCiAJ
CQlkbWFfcHJlcF9mbGFncyB8PSBETUFfUFJFUF9GRU5DRTsNCiANCi0JCXVubWFwLT50b19jbnQg
PSAxOw0KLQkJdW5tYXAtPmFkZHJbMF0gPSBkbWFfbWFwX3BhZ2UoZGV2aWNlLT5kZXYsIHNyYywg
c3JjX29mZnNldCwgbGVuLA0KLQkJCQkJICAgICAgRE1BX1RPX0RFVklDRSk7DQotCQl1bm1hcC0+
ZnJvbV9jbnQgPSAxOw0KLQkJdW5tYXAtPmFkZHJbMV0gPSBkbWFfbWFwX3BhZ2UoZGV2aWNlLT5k
ZXYsIGRlc3QsIGRlc3Rfb2Zmc2V0LCBsZW4sDQotCQkJCQkgICAgICBETUFfRlJPTV9ERVZJQ0Up
Ow0KLQkJdW5tYXAtPmxlbiA9IGxlbjsNCi0NCi0JCXR4ID0gZGV2aWNlLT5kZXZpY2VfcHJlcF9k
bWFfbWVtY3B5KGNoYW4sIHVubWFwLT5hZGRyWzFdLA0KLQkJCQkJCSAgICB1bm1hcC0+YWRkclsw
XSwgbGVuLA0KLQkJCQkJCSAgICBkbWFfcHJlcF9mbGFncyk7DQorCQl1bm1hcCA9IGRtYWVuZ2lu
ZV9nZXRfdW5tYXBfZGF0YShkZXZpY2UtPmRldiwgMiwgR0ZQX05PSU8pOw0KKwkJaWYgKHVubWFw
KSB7DQorCQkJdW5tYXAtPnRvX2NudCA9IDE7DQorCQkJdW5tYXAtPmFkZHJbMF0gPSBkbWFfbWFw
X3BhZ2UoZGV2aWNlLT5kZXYsIHNyYywNCisJCQkJCQkgICAgICBzcmNfb2Zmc2V0LCBsZW4sDQor
CQkJCQkJICAgICAgRE1BX1RPX0RFVklDRSk7DQorCQkJdW5tYXAtPmZyb21fY250ID0gMTsNCisJ
CQl1bm1hcC0+YWRkclsxXSA9IGRtYV9tYXBfcGFnZShkZXZpY2UtPmRldiwgZGVzdCwNCisJCQkJ
CQkgICAgICBkZXN0X29mZnNldCwgbGVuLA0KKwkJCQkJCSAgICAgIERNQV9GUk9NX0RFVklDRSk7
DQorCQkJdW5tYXAtPmxlbiA9IGxlbjsNCisNCisJCQl0eCA9IGRldmljZS0+ZGV2aWNlX3ByZXBf
ZG1hX21lbWNweShjaGFuLA0KKwkJCQkJCQkgICAgdW5tYXAtPmFkZHJbMV0sDQorCQkJCQkJCSAg
ICB1bm1hcC0+YWRkclswXSwNCisJCQkJCQkJICAgIGxlbiwNCisJCQkJCQkJICAgIGRtYV9wcmVw
X2ZsYWdzKTsNCisJCQlpZiAodHgpIHsNCisJCQkJcHJfZGVidWcoIiVzOiAoYXN5bmMpIGxlbjog
JXp1XG4iLCBfX2Z1bmNfXywNCisJCQkJCSBsZW4pOw0KKw0KKwkJCQlkbWFfc2V0X3VubWFwKHR4
LCB1bm1hcCk7DQorCQkJCWFzeW5jX3R4X3N1Ym1pdChjaGFuLCB0eCwgc3VibWl0KTsNCisJCQkJ
cmV0dXJuIHR4Ow0KKwkJCX0NCisNCisJCQkvKiBjb3VsZCBub3QgZ2V0IGEgZGVzY3JpcHRvciwg
dW5tYXAgYW5kIGZhbGwgdGhyb3VnaCB0bw0KKwkJCSAqIHRoZSBzeW5jaHJvbm91cyBwYXRoDQor
CQkJICovDQorCQkJZG1hZW5naW5lX3VubWFwX3B1dCh1bm1hcCk7DQorCQl9DQogCX0NCiANCi0J
aWYgKHR4KSB7DQotCQlwcl9kZWJ1ZygiJXM6IChhc3luYykgbGVuOiAlenVcbiIsIF9fZnVuY19f
LCBsZW4pOw0KKwkvKiBydW4gdGhlIG9wZXJhdGlvbiBzeW5jaHJvbm91c2x5ICovDQorCXByX2Rl
YnVnKCIlczogKHN5bmMpIGxlbjogJXp1XG4iLCBfX2Z1bmNfXywgbGVuKTsNCiANCi0JCWRtYV9z
ZXRfdW5tYXAodHgsIHVubWFwKTsNCi0JCWFzeW5jX3R4X3N1Ym1pdChjaGFuLCB0eCwgc3VibWl0
KTsNCi0JfSBlbHNlIHsNCi0JCXZvaWQgKmRlc3RfYnVmLCAqc3JjX2J1ZjsNCi0JCXByX2RlYnVn
KCIlczogKHN5bmMpIGxlbjogJXp1XG4iLCBfX2Z1bmNfXywgbGVuKTsNCisJLyogd2FpdCBmb3Ig
YW55IHByZXJlcXVpc2l0ZSBvcGVyYXRpb25zICovDQorCWFzeW5jX3R4X3F1aWVzY2UoJnN1Ym1p
dC0+ZGVwZW5kX3R4KTsNCiANCi0JCS8qIHdhaXQgZm9yIGFueSBwcmVyZXF1aXNpdGUgb3BlcmF0
aW9ucyAqLw0KLQkJYXN5bmNfdHhfcXVpZXNjZSgmc3VibWl0LT5kZXBlbmRfdHgpOw0KKwlkZXN0
X2J1ZiA9IGttYXBfYXRvbWljKGRlc3QpICsgZGVzdF9vZmZzZXQ7DQorCXNyY19idWYgPSBrbWFw
X2F0b21pYyhzcmMpICsgc3JjX29mZnNldDsNCiANCi0JCWRlc3RfYnVmID0ga21hcF9hdG9taWMo
ZGVzdCkgKyBkZXN0X29mZnNldDsNCi0JCXNyY19idWYgPSBrbWFwX2F0b21pYyhzcmMpICsgc3Jj
X29mZnNldDsNCisJbWVtY3B5KGRlc3RfYnVmLCBzcmNfYnVmLCBsZW4pOw0KIA0KLQkJbWVtY3B5
KGRlc3RfYnVmLCBzcmNfYnVmLCBsZW4pOw0KLQ0KLQkJa3VubWFwX2F0b21pYyhzcmNfYnVmKTsN
Ci0JCWt1bm1hcF9hdG9taWMoZGVzdF9idWYpOw0KLQ0KLQkJYXN5bmNfdHhfc3luY19lcGlsb2co
c3VibWl0KTsNCi0JfQ0KKwlrdW5tYXBfYXRvbWljKHNyY19idWYpOw0KKwlrdW5tYXBfYXRvbWlj
KGRlc3RfYnVmKTsNCiANCi0JZG1hZW5naW5lX3VubWFwX3B1dCh1bm1hcCk7DQorCWFzeW5jX3R4
X3N5bmNfZXBpbG9nKHN1Ym1pdCk7DQogDQotCXJldHVybiB0eDsNCisJcmV0dXJuIE5VTEw7DQog
fQ0KIEVYUE9SVF9TWU1CT0xfR1BMKGFzeW5jX21lbWNweSk7DQogDQpkaWZmIC0tZ2l0IGEvY3J5
cHRvL2FzeW5jX3R4L2FzeW5jX3BxLmMgYi9jcnlwdG8vYXN5bmNfdHgvYXN5bmNfcHEuYyBpbmRl
eCBkMDUzMjdjLi5mNDQ2Y2RhIDEwMDY0NA0KLS0tIGEvY3J5cHRvL2FzeW5jX3R4L2FzeW5jX3Bx
LmMNCisrKyBiL2NyeXB0by9hc3luY190eC9hc3luY19wcS5jDQpAQCAtMTc1LDEwICsxNzUsNyBA
QCBhc3luY19nZW5fc3luZHJvbWUoc3RydWN0IHBhZ2UgKipibG9ja3MsIHVuc2lnbmVkIGludCBv
ZmZzZXQsIGludCBkaXNrcywNCiANCiAJQlVHX09OKGRpc2tzID4gMjU1IHx8ICEoUChibG9ja3Ms
IGRpc2tzKSB8fCBRKGJsb2NrcywgZGlza3MpKSk7DQogDQotCWlmIChkZXZpY2UpDQotCQl1bm1h
cCA9IGRtYWVuZ2luZV9nZXRfdW5tYXBfZGF0YShkZXZpY2UtPmRldiwgZGlza3MsIEdGUF9OT0lP
KTsNCi0NCi0JaWYgKHVubWFwICYmDQorCWlmIChkZXZpY2UgJiYNCiAJICAgIChzcmNfY250IDw9
IGRtYV9tYXhwcShkZXZpY2UsIDApIHx8DQogCSAgICAgZG1hX21heHBxKGRldmljZSwgRE1BX1BS
RVBfQ09OVElOVUUpID4gMCkgJiYNCiAJICAgIGlzX2RtYV9wcV9hbGlnbmVkKGRldmljZSwgb2Zm
c2V0LCAwLCBsZW4pKSB7IEBAIC0xOTQsNDYgKzE5MSw1NCBAQCBhc3luY19nZW5fc3luZHJvbWUo
c3RydWN0IHBhZ2UgKipibG9ja3MsIHVuc2lnbmVkIGludCBvZmZzZXQsIGludCBkaXNrcywNCiAJ
CS8qIGNvbnZlcnQgc291cmNlIGFkZHJlc3NlcyBiZWluZyBjYXJlZnVsIHRvIGNvbGxhcHNlICdl
bXB0eScNCiAJCSAqIHNvdXJjZXMgYW5kIHVwZGF0ZSB0aGUgY29lZmZpY2llbnRzIGFjY29yZGlu
Z2x5DQogCQkgKi8NCi0JCXVubWFwLT5sZW4gPSBsZW47DQotCQlmb3IgKGkgPSAwLCBqID0gMDsg
aSA8IHNyY19jbnQ7IGkrKykgew0KLQkJCWlmIChibG9ja3NbaV0gPT0gTlVMTCkNCi0JCQkJY29u
dGludWU7DQotCQkJdW5tYXAtPmFkZHJbal0gPSBkbWFfbWFwX3BhZ2UoZGV2aWNlLT5kZXYsIGJs
b2Nrc1tpXSwgb2Zmc2V0LA0KLQkJCQkJCSAgICAgIGxlbiwgRE1BX1RPX0RFVklDRSk7DQotCQkJ
Y29lZnNbal0gPSByYWlkNl9nZmV4cFtpXTsNCi0JCQl1bm1hcC0+dG9fY250Kys7DQotCQkJaisr
Ow0KLQkJfQ0KKwkJdW5tYXAgPSBkbWFlbmdpbmVfZ2V0X3VubWFwX2RhdGEoZGV2aWNlLT5kZXYs
IGRpc2tzLCBHRlBfTk9JTyk7DQorCQlpZiAodW5tYXApIHsNCisJCQl1bm1hcC0+bGVuID0gbGVu
Ow0KKwkJCWZvciAoaSA9IDAsIGogPSAwOyBpIDwgc3JjX2NudDsgaSsrKSB7DQorCQkJCWlmIChi
bG9ja3NbaV0gPT0gTlVMTCkNCisJCQkJCWNvbnRpbnVlOw0KKwkJCQl1bm1hcC0+YWRkcltqXSA9
IGRtYV9tYXBfcGFnZShkZXZpY2UtPmRldiwNCisJCQkJCQkJICAgICAgYmxvY2tzW2ldLA0KKwkJ
CQkJCQkgICAgICBvZmZzZXQsDQorCQkJCQkJCSAgICAgIGxlbiwNCisJCQkJCQkJICAgICAgRE1B
X1RPX0RFVklDRSk7DQorCQkJCWNvZWZzW2pdID0gcmFpZDZfZ2ZleHBbaV07DQorCQkJCXVubWFw
LT50b19jbnQrKzsNCisJCQkJaisrOw0KKwkJCX0NCiANCi0JCS8qDQotCQkgKiBETUFzIHVzZSBk
ZXN0aW5hdGlvbnMgYXMgc291cmNlcywNCi0JCSAqIHNvIHVzZSBCSURJUkVDVElPTkFMIG1hcHBp
bmcNCi0JCSAqLw0KLQkJdW5tYXAtPmJpZGlfY250Kys7DQotCQlpZiAoUChibG9ja3MsIGRpc2tz
KSkNCi0JCQl1bm1hcC0+YWRkcltqKytdID0gZG1hX21hcF9wYWdlKGRldmljZS0+ZGV2LCBQKGJs
b2NrcywgZGlza3MpLA0KLQkJCQkJCQlvZmZzZXQsIGxlbiwgRE1BX0JJRElSRUNUSU9OQUwpOw0K
LQkJZWxzZSB7DQotCQkJdW5tYXAtPmFkZHJbaisrXSA9IDA7DQotCQkJZG1hX2ZsYWdzIHw9IERN
QV9QUkVQX1BRX0RJU0FCTEVfUDsNCi0JCX0NCisJCQkvKg0KKwkJCSAqIERNQXMgdXNlIGRlc3Rp
bmF0aW9ucyBhcyBzb3VyY2VzLA0KKwkJCSAqIHNvIHVzZSBCSURJUkVDVElPTkFMIG1hcHBpbmcN
CisJCQkgKi8NCisJCQl1bm1hcC0+YmlkaV9jbnQrKzsNCisJCQlpZiAoUChibG9ja3MsIGRpc2tz
KSkNCisJCQkJdW5tYXAtPmFkZHJbaisrXSA9IGRtYV9tYXBfcGFnZShkZXZpY2UtPmRldiwNCisJ
CQkJCQkJUChibG9ja3MsIGRpc2tzKSwNCisJCQkJCQkJb2Zmc2V0LCBsZW4sDQorCQkJCQkJCURN
QV9CSURJUkVDVElPTkFMKTsNCisJCQllbHNlIHsNCisJCQkJdW5tYXAtPmFkZHJbaisrXSA9IDA7
DQorCQkJCWRtYV9mbGFncyB8PSBETUFfUFJFUF9QUV9ESVNBQkxFX1A7DQorCQkJfQ0KIA0KLQkJ
dW5tYXAtPmJpZGlfY250Kys7DQotCQlpZiAoUShibG9ja3MsIGRpc2tzKSkNCi0JCQl1bm1hcC0+
YWRkcltqKytdID0gZG1hX21hcF9wYWdlKGRldmljZS0+ZGV2LCBRKGJsb2NrcywgZGlza3MpLA0K
LQkJCQkJCSAgICAgICBvZmZzZXQsIGxlbiwgRE1BX0JJRElSRUNUSU9OQUwpOw0KLQkJZWxzZSB7
DQotCQkJdW5tYXAtPmFkZHJbaisrXSA9IDA7DQotCQkJZG1hX2ZsYWdzIHw9IERNQV9QUkVQX1BR
X0RJU0FCTEVfUTsNCi0JCX0NCisJCQl1bm1hcC0+YmlkaV9jbnQrKzsNCisJCQlpZiAoUShibG9j
a3MsIGRpc2tzKSkNCisJCQkJdW5tYXAtPmFkZHJbaisrXSA9IGRtYV9tYXBfcGFnZShkZXZpY2Ut
PmRldiwNCisJCQkJCQkJUShibG9ja3MsIGRpc2tzKSwNCisJCQkJCQkJb2Zmc2V0LCBsZW4sDQor
CQkJCQkJCURNQV9CSURJUkVDVElPTkFMKTsNCisJCQllbHNlIHsNCisJCQkJdW5tYXAtPmFkZHJb
aisrXSA9IDA7DQorCQkJCWRtYV9mbGFncyB8PSBETUFfUFJFUF9QUV9ESVNBQkxFX1E7DQorCQkJ
fQ0KIA0KLQkJdHggPSBkb19hc3luY19nZW5fc3luZHJvbWUoY2hhbiwgY29lZnMsIGosIHVubWFw
LCBkbWFfZmxhZ3MsIHN1Ym1pdCk7DQotCQlkbWFlbmdpbmVfdW5tYXBfcHV0KHVubWFwKTsNCi0J
CXJldHVybiB0eDsNCisJCQl0eCA9IGRvX2FzeW5jX2dlbl9zeW5kcm9tZShjaGFuLCBjb2Vmcywg
aiwgdW5tYXAsDQorCQkJCQkJICAgZG1hX2ZsYWdzLCBzdWJtaXQpOw0KKwkJCXJldHVybiB0eDsN
CisJCX0NCiAJfQ0KIA0KLQlkbWFlbmdpbmVfdW5tYXBfcHV0KHVubWFwKTsNCi0NCiAJLyogcnVu
IHRoZSBwcSBzeW5jaHJvbm91c2x5ICovDQogCXByX2RlYnVnKCIlczogKHN5bmMpIGRpc2tzOiAl
ZCBsZW46ICV6dVxuIiwgX19mdW5jX18sIGRpc2tzLCBsZW4pOw0KIA0KQEAgLTI5MywxMCArMjk4
LDcgQEAgYXN5bmNfc3luZHJvbWVfdmFsKHN0cnVjdCBwYWdlICoqYmxvY2tzLCB1bnNpZ25lZCBp
bnQgb2Zmc2V0LCBpbnQgZGlza3MsDQogDQogCUJVR19PTihkaXNrcyA8IDQpOw0KIA0KLQlpZiAo
ZGV2aWNlKQ0KLQkJdW5tYXAgPSBkbWFlbmdpbmVfZ2V0X3VubWFwX2RhdGEoZGV2aWNlLT5kZXYs
IGRpc2tzLCBHRlBfTk9JTyk7DQotDQotCWlmICh1bm1hcCAmJiBkaXNrcyA8PSBkbWFfbWF4cHEo
ZGV2aWNlLCAwKSAmJg0KKwlpZiAoZGV2aWNlICYmIGRpc2tzIDw9IGRtYV9tYXhwcShkZXZpY2Us
IDApICYmDQogCSAgICBpc19kbWFfcHFfYWxpZ25lZChkZXZpY2UsIG9mZnNldCwgMCwgbGVuKSkg
ew0KIAkJc3RydWN0IGRldmljZSAqZGV2ID0gZGV2aWNlLT5kZXY7DQogCQlkbWFfYWRkcl90IHBx
WzJdOw0KQEAgLTMwNSw1OCArMzA3LDYzIEBAIGFzeW5jX3N5bmRyb21lX3ZhbChzdHJ1Y3QgcGFn
ZSAqKmJsb2NrcywgdW5zaWduZWQgaW50IG9mZnNldCwgaW50IGRpc2tzLA0KIAkJcHJfZGVidWco
IiVzOiAoYXN5bmMpIGRpc2tzOiAlZCBsZW46ICV6dVxuIiwNCiAJCQkgX19mdW5jX18sIGRpc2tz
LCBsZW4pOw0KIA0KLQkJdW5tYXAtPmxlbiA9IGxlbjsNCi0JCWZvciAoaSA9IDA7IGkgPCBkaXNr
cy0yOyBpKyspDQotCQkJaWYgKGxpa2VseShibG9ja3NbaV0pKSB7DQotCQkJCXVubWFwLT5hZGRy
W2pdID0gZG1hX21hcF9wYWdlKGRldiwgYmxvY2tzW2ldLA0KLQkJCQkJCQkgICAgICBvZmZzZXQs
IGxlbiwNCisJCXVubWFwID0gZG1hZW5naW5lX2dldF91bm1hcF9kYXRhKGRldmljZS0+ZGV2LCBk
aXNrcywgR0ZQX05PSU8pOw0KKwkJaWYgKHVubWFwKSB7DQorCQkJdW5tYXAtPmxlbiA9IGxlbjsN
CisJCQlmb3IgKGkgPSAwOyBpIDwgZGlza3MtMjsgaSsrKQ0KKwkJCQlpZiAobGlrZWx5KGJsb2Nr
c1tpXSkpIHsNCisJCQkJCXVubWFwLT5hZGRyW2pdID0gZG1hX21hcF9wYWdlKGRldiwNCisJCQkJ
CQkJICAgICAgYmxvY2tzW2ldLA0KKwkJCQkJCQkgICAgICBvZmZzZXQsDQorCQkJCQkJCSAgICAg
IGxlbiwNCiAJCQkJCQkJICAgICAgRE1BX1RPX0RFVklDRSk7DQotCQkJCWNvZWZzW2pdID0gcmFp
ZDZfZ2ZleHBbaV07DQorCQkJCQljb2Vmc1tqXSA9IHJhaWQ2X2dmZXhwW2ldOw0KKwkJCQkJdW5t
YXAtPnRvX2NudCsrOw0KKwkJCQkJc3JjX2NudCsrOw0KKwkJCQkJaisrOw0KKwkJCQl9DQorDQor
CQkJaWYgKCFQKGJsb2NrcywgZGlza3MpKSB7DQorCQkJCXBxWzBdID0gMDsNCisJCQkJZG1hX2Zs
YWdzIHw9IERNQV9QUkVQX1BRX0RJU0FCTEVfUDsNCisJCQl9IGVsc2Ugew0KKwkJCQlwcVswXSA9
IGRtYV9tYXBfcGFnZShkZXYsIFAoYmxvY2tzLCBkaXNrcyksDQorCQkJCQkJICAgICBvZmZzZXQs
IGxlbiwNCisJCQkJCQkgICAgIERNQV9UT19ERVZJQ0UpOw0KKwkJCQl1bm1hcC0+YWRkcltqKytd
ID0gcHFbMF07DQorCQkJCXVubWFwLT50b19jbnQrKzsNCisJCQl9DQorCQkJaWYgKCFRKGJsb2Nr
cywgZGlza3MpKSB7DQorCQkJCXBxWzFdID0gMDsNCisJCQkJZG1hX2ZsYWdzIHw9IERNQV9QUkVQ
X1BRX0RJU0FCTEVfUTsNCisJCQl9IGVsc2Ugew0KKwkJCQlwcVsxXSA9IGRtYV9tYXBfcGFnZShk
ZXYsIFEoYmxvY2tzLCBkaXNrcyksDQorCQkJCQkJICAgICBvZmZzZXQsIGxlbiwNCisJCQkJCQkg
ICAgIERNQV9UT19ERVZJQ0UpOw0KKwkJCQl1bm1hcC0+YWRkcltqKytdID0gcHFbMV07DQogCQkJ
CXVubWFwLT50b19jbnQrKzsNCi0JCQkJc3JjX2NudCsrOw0KLQkJCQlqKys7DQogCQkJfQ0KIA0K
LQkJaWYgKCFQKGJsb2NrcywgZGlza3MpKSB7DQotCQkJcHFbMF0gPSAwOw0KLQkJCWRtYV9mbGFn
cyB8PSBETUFfUFJFUF9QUV9ESVNBQkxFX1A7DQotCQl9IGVsc2Ugew0KLQkJCXBxWzBdID0gZG1h
X21hcF9wYWdlKGRldiwgUChibG9ja3MsIGRpc2tzKSwNCi0JCQkJCSAgICAgb2Zmc2V0LCBsZW4s
DQotCQkJCQkgICAgIERNQV9UT19ERVZJQ0UpOw0KLQkJCXVubWFwLT5hZGRyW2orK10gPSBwcVsw
XTsNCi0JCQl1bm1hcC0+dG9fY250Kys7DQotCQl9DQotCQlpZiAoIVEoYmxvY2tzLCBkaXNrcykp
IHsNCi0JCQlwcVsxXSA9IDA7DQotCQkJZG1hX2ZsYWdzIHw9IERNQV9QUkVQX1BRX0RJU0FCTEVf
UTsNCi0JCX0gZWxzZSB7DQotCQkJcHFbMV0gPSBkbWFfbWFwX3BhZ2UoZGV2LCBRKGJsb2Nrcywg
ZGlza3MpLA0KLQkJCQkJICAgICBvZmZzZXQsIGxlbiwNCi0JCQkJCSAgICAgRE1BX1RPX0RFVklD
RSk7DQotCQkJdW5tYXAtPmFkZHJbaisrXSA9IHBxWzFdOw0KLQkJCXVubWFwLT50b19jbnQrKzsN
Ci0JCX0NCi0NCi0JCWlmIChzdWJtaXQtPmZsYWdzICYgQVNZTkNfVFhfRkVOQ0UpDQotCQkJZG1h
X2ZsYWdzIHw9IERNQV9QUkVQX0ZFTkNFOw0KLQkJZm9yICg7Oykgew0KLQkJCXR4ID0gZGV2aWNl
LT5kZXZpY2VfcHJlcF9kbWFfcHFfdmFsKGNoYW4sIHBxLA0KLQkJCQkJCQkgICAgdW5tYXAtPmFk
ZHIsDQotCQkJCQkJCSAgICBzcmNfY250LA0KLQkJCQkJCQkgICAgY29lZnMsDQotCQkJCQkJCSAg
ICBsZW4sIHBxcmVzLA0KLQkJCQkJCQkgICAgZG1hX2ZsYWdzKTsNCi0JCQlpZiAobGlrZWx5KHR4
KSkNCi0JCQkJYnJlYWs7DQotCQkJYXN5bmNfdHhfcXVpZXNjZSgmc3VibWl0LT5kZXBlbmRfdHgp
Ow0KLQkJCWRtYV9hc3luY19pc3N1ZV9wZW5kaW5nKGNoYW4pOw0KLQkJfQ0KKwkJCWlmIChzdWJt
aXQtPmZsYWdzICYgQVNZTkNfVFhfRkVOQ0UpDQorCQkJCWRtYV9mbGFncyB8PSBETUFfUFJFUF9G
RU5DRTsNCisJCQlmb3IgKDs7KSB7DQorCQkJCXR4ID0gZGV2aWNlLT5kZXZpY2VfcHJlcF9kbWFf
cHFfdmFsKGNoYW4sIHBxLA0KKwkJCQkJCQkJICAgIHVubWFwLT5hZGRyLA0KKwkJCQkJCQkJICAg
IHNyY19jbnQsDQorCQkJCQkJCQkgICAgY29lZnMsDQorCQkJCQkJCQkgICAgbGVuLCBwcXJlcywN
CisJCQkJCQkJCSAgICBkbWFfZmxhZ3MpOw0KKwkJCQlpZiAobGlrZWx5KHR4KSkNCisJCQkJCWJy
ZWFrOw0KKwkJCQlhc3luY190eF9xdWllc2NlKCZzdWJtaXQtPmRlcGVuZF90eCk7DQorCQkJCWRt
YV9hc3luY19pc3N1ZV9wZW5kaW5nKGNoYW4pOw0KKwkJCX0NCiANCi0JCWRtYV9zZXRfdW5tYXAo
dHgsIHVubWFwKTsNCi0JCWFzeW5jX3R4X3N1Ym1pdChjaGFuLCB0eCwgc3VibWl0KTsNCisJCQlk
bWFfc2V0X3VubWFwKHR4LCB1bm1hcCk7DQorCQkJYXN5bmNfdHhfc3VibWl0KGNoYW4sIHR4LCBz
dWJtaXQpOw0KIA0KLQkJcmV0dXJuIHR4Ow0KKwkJCXJldHVybiB0eDsNCisJCX0NCiAJfSBlbHNl
IHsNCiAJCXN0cnVjdCBwYWdlICpwX3NyYyA9IFAoYmxvY2tzLCBkaXNrcyk7DQogCQlzdHJ1Y3Qg
cGFnZSAqcV9zcmMgPSBRKGJsb2NrcywgZGlza3MpOyBAQCAtNDExLDkgKzQxOCw5IEBAIGFzeW5j
X3N5bmRyb21lX3ZhbChzdHJ1Y3QgcGFnZSAqKmJsb2NrcywgdW5zaWduZWQgaW50IG9mZnNldCwg
aW50IGRpc2tzLA0KIAkJc3VibWl0LT5jYl9wYXJhbSA9IGNiX3BhcmFtX29yaWc7DQogCQlzdWJt
aXQtPmZsYWdzID0gZmxhZ3Nfb3JpZzsNCiAJCWFzeW5jX3R4X3N5bmNfZXBpbG9nKHN1Ym1pdCk7
DQotDQotCQlyZXR1cm4gTlVMTDsNCiAJfQ0KKw0KKwlyZXR1cm4gTlVMTDsNCiB9DQogRVhQT1JU
X1NZTUJPTF9HUEwoYXN5bmNfc3luZHJvbWVfdmFsKTsNCiANCmRpZmYgLS1naXQgYS9jcnlwdG8v
YXN5bmNfdHgvYXN5bmNfcmFpZDZfcmVjb3YuYyBiL2NyeXB0by9hc3luY190eC9hc3luY19yYWlk
Nl9yZWNvdi5jDQppbmRleCA5MzRhODQ5Li5jNTVkOGYxIDEwMDY0NA0KLS0tIGEvY3J5cHRvL2Fz
eW5jX3R4L2FzeW5jX3JhaWQ2X3JlY292LmMNCisrKyBiL2NyeXB0by9hc3luY190eC9hc3luY19y
YWlkNl9yZWNvdi5jDQpAQCAtNDAsMTAgKzQwLDcgQEAgYXN5bmNfc3VtX3Byb2R1Y3Qoc3RydWN0
IHBhZ2UgKmRlc3QsIHN0cnVjdCBwYWdlICoqc3JjcywgdW5zaWduZWQgY2hhciAqY29lZiwNCiAJ
dTggYXgsIGJ4Ow0KIAl1OCAqYSwgKmIsICpjOw0KIA0KLQlpZiAoZG1hKQ0KLQkJdW5tYXAgPSBk
bWFlbmdpbmVfZ2V0X3VubWFwX2RhdGEoZG1hLT5kZXYsIDMsIEdGUF9OT0lPKTsNCi0NCi0JaWYg
KHVubWFwKSB7DQorCWlmIChkbWEpIHsNCiAJCXN0cnVjdCBkZXZpY2UgKmRldiA9IGRtYS0+ZGV2
Ow0KIAkJZG1hX2FkZHJfdCBwcVsyXTsNCiAJCXN0cnVjdCBkbWFfYXN5bmNfdHhfZGVzY3JpcHRv
ciAqdHg7DQpAQCAtNTEsMjkgKzQ4LDM1IEBAIGFzeW5jX3N1bV9wcm9kdWN0KHN0cnVjdCBwYWdl
ICpkZXN0LCBzdHJ1Y3QgcGFnZSAqKnNyY3MsIHVuc2lnbmVkIGNoYXIgKmNvZWYsDQogDQogCQlp
ZiAoc3VibWl0LT5mbGFncyAmIEFTWU5DX1RYX0ZFTkNFKQ0KIAkJCWRtYV9mbGFncyB8PSBETUFf
UFJFUF9GRU5DRTsNCi0JCXVubWFwLT5hZGRyWzBdID0gZG1hX21hcF9wYWdlKGRldiwgc3Jjc1sw
XSwgMCwgbGVuLCBETUFfVE9fREVWSUNFKTsNCi0JCXVubWFwLT5hZGRyWzFdID0gZG1hX21hcF9w
YWdlKGRldiwgc3Jjc1sxXSwgMCwgbGVuLCBETUFfVE9fREVWSUNFKTsNCi0JCXVubWFwLT50b19j
bnQgPSAyOw0KLQ0KLQkJdW5tYXAtPmFkZHJbMl0gPSBkbWFfbWFwX3BhZ2UoZGV2LCBkZXN0LCAw
LCBsZW4sIERNQV9CSURJUkVDVElPTkFMKTsNCi0JCXVubWFwLT5iaWRpX2NudCA9IDE7DQotCQkv
KiBlbmdpbmUgb25seSBsb29rcyBhdCBRLCBidXQgZXhwZWN0cyBpdCB0byBmb2xsb3cgUCAqLw0K
LQkJcHFbMV0gPSB1bm1hcC0+YWRkclsyXTsNCi0NCi0JCXVubWFwLT5sZW4gPSBsZW47DQotCQl0
eCA9IGRtYS0+ZGV2aWNlX3ByZXBfZG1hX3BxKGNoYW4sIHBxLCB1bm1hcC0+YWRkciwgMiwgY29l
ZiwNCi0JCQkJCSAgICAgbGVuLCBkbWFfZmxhZ3MpOw0KLQkJaWYgKHR4KSB7DQotCQkJZG1hX3Nl
dF91bm1hcCh0eCwgdW5tYXApOw0KLQkJCWFzeW5jX3R4X3N1Ym1pdChjaGFuLCB0eCwgc3VibWl0
KTsNCisNCisJCXVubWFwID0gZG1hZW5naW5lX2dldF91bm1hcF9kYXRhKGRtYS0+ZGV2LCAzLCBH
RlBfTk9JTyk7DQorCQlpZiAodW5tYXApIHsNCisJCQl1bm1hcC0+YWRkclswXSA9IGRtYV9tYXBf
cGFnZShkZXYsIHNyY3NbMF0sIDAsIGxlbiwNCisJCQkJCQkgICAgICBETUFfVE9fREVWSUNFKTsN
CisJCQl1bm1hcC0+YWRkclsxXSA9IGRtYV9tYXBfcGFnZShkZXYsIHNyY3NbMV0sIDAsIGxlbiwN
CisJCQkJCQkgICAgICBETUFfVE9fREVWSUNFKTsNCisJCQl1bm1hcC0+dG9fY250ID0gMjsNCisN
CisJCQl1bm1hcC0+YWRkclsyXSA9IGRtYV9tYXBfcGFnZShkZXYsIGRlc3QsIDAsIGxlbiwNCisJ
CQkJCQkgICAgICBETUFfQklESVJFQ1RJT05BTCk7DQorCQkJdW5tYXAtPmJpZGlfY250ID0gMTsN
CisJCQkvKiBlbmdpbmUgb25seSBsb29rcyBhdCBRLCBidXQgZXhwZWN0cyBpdCB0byBmb2xsb3cg
UCAqLw0KKwkJCXBxWzFdID0gdW5tYXAtPmFkZHJbMl07DQorDQorCQkJdW5tYXAtPmxlbiA9IGxl
bjsNCisJCQl0eCA9IGRtYS0+ZGV2aWNlX3ByZXBfZG1hX3BxKGNoYW4sIHBxLCB1bm1hcC0+YWRk
ciwgMiwNCisJCQkJCQkgICAgIGNvZWYsIGxlbiwgZG1hX2ZsYWdzKTsNCisJCQlpZiAodHgpIHsN
CisJCQkJZG1hX3NldF91bm1hcCh0eCwgdW5tYXApOw0KKwkJCQlhc3luY190eF9zdWJtaXQoY2hh
biwgdHgsIHN1Ym1pdCk7DQorCQkJCXJldHVybiB0eDsNCisJCQl9DQorDQorCQkJLyogY291bGQg
bm90IGdldCBhIGRlc2NyaXB0b3IsIHVubWFwIGFuZCBmYWxsIHRocm91Z2ggdG8NCisJCQkgKiB0
aGUgc3luY2hyb25vdXMgcGF0aA0KKwkJCSAqLw0KIAkJCWRtYWVuZ2luZV91bm1hcF9wdXQodW5t
YXApOw0KLQkJCXJldHVybiB0eDsNCiAJCX0NCi0NCi0JCS8qIGNvdWxkIG5vdCBnZXQgYSBkZXNj
cmlwdG9yLCB1bm1hcCBhbmQgZmFsbCB0aHJvdWdoIHRvDQotCQkgKiB0aGUgc3luY2hyb25vdXMg
cGF0aA0KLQkJICovDQotCQlkbWFlbmdpbmVfdW5tYXBfcHV0KHVubWFwKTsNCiAJfQ0KIA0KIAkv
KiBydW4gdGhlIG9wZXJhdGlvbiBzeW5jaHJvbm91c2x5ICovDQpAQCAtMTA0LDEwICsxMDcsNyBA
QCBhc3luY19tdWx0KHN0cnVjdCBwYWdlICpkZXN0LCBzdHJ1Y3QgcGFnZSAqc3JjLCB1OCBjb2Vm
LCBzaXplX3QgbGVuLA0KIAljb25zdCB1OCAqcW11bDsgLyogUSBtdWx0aXBsaWVyIHRhYmxlICov
DQogCXU4ICpkLCAqczsNCiANCi0JaWYgKGRtYSkNCi0JCXVubWFwID0gZG1hZW5naW5lX2dldF91
bm1hcF9kYXRhKGRtYS0+ZGV2LCAzLCBHRlBfTk9JTyk7DQotDQotCWlmICh1bm1hcCkgew0KKwlp
ZiAoZG1hKSB7DQogCQlkbWFfYWRkcl90IGRtYV9kZXN0WzJdOw0KIAkJc3RydWN0IGRldmljZSAq
ZGV2ID0gZG1hLT5kZXY7DQogCQlzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKnR4Ow0K
QEAgLTExNSwzMSArMTE1LDM3IEBAIGFzeW5jX211bHQoc3RydWN0IHBhZ2UgKmRlc3QsIHN0cnVj
dCBwYWdlICpzcmMsIHU4IGNvZWYsIHNpemVfdCBsZW4sDQogDQogCQlpZiAoc3VibWl0LT5mbGFn
cyAmIEFTWU5DX1RYX0ZFTkNFKQ0KIAkJCWRtYV9mbGFncyB8PSBETUFfUFJFUF9GRU5DRTsNCi0J
CXVubWFwLT5hZGRyWzBdID0gZG1hX21hcF9wYWdlKGRldiwgc3JjLCAwLCBsZW4sIERNQV9UT19E
RVZJQ0UpOw0KLQkJdW5tYXAtPnRvX2NudCsrOw0KLQkJdW5tYXAtPmFkZHJbMV0gPSBkbWFfbWFw
X3BhZ2UoZGV2LCBkZXN0LCAwLCBsZW4sIERNQV9CSURJUkVDVElPTkFMKTsNCi0JCWRtYV9kZXN0
WzFdID0gdW5tYXAtPmFkZHJbMV07DQotCQl1bm1hcC0+YmlkaV9jbnQrKzsNCi0JCXVubWFwLT5s
ZW4gPSBsZW47DQotDQotCQkvKiB0aGlzIGxvb2tzIGZ1bm55LCBidXQgdGhlIGVuZ2luZSBsb29r
cyBmb3IgUSBhdA0KLQkJICogZG1hX2Rlc3RbMV0gYW5kIGlnbm9yZXMgZG1hX2Rlc3RbMF0gYXMg
YSBkZXN0DQotCQkgKiBkdWUgdG8gRE1BX1BSRVBfUFFfRElTQUJMRV9QDQotCQkgKi8NCi0JCXR4
ID0gZG1hLT5kZXZpY2VfcHJlcF9kbWFfcHEoY2hhbiwgZG1hX2Rlc3QsIHVubWFwLT5hZGRyLA0K
LQkJCQkJICAgICAxLCAmY29lZiwgbGVuLCBkbWFfZmxhZ3MpOw0KIA0KLQkJaWYgKHR4KSB7DQot
CQkJZG1hX3NldF91bm1hcCh0eCwgdW5tYXApOw0KKwkJdW5tYXAgPSBkbWFlbmdpbmVfZ2V0X3Vu
bWFwX2RhdGEoZG1hLT5kZXYsIDMsIEdGUF9OT0lPKTsNCisJCWlmICh1bm1hcCkgew0KKwkJCXVu
bWFwLT5hZGRyWzBdID0gZG1hX21hcF9wYWdlKGRldiwgc3JjLCAwLCBsZW4sDQorCQkJCQkJICAg
ICAgRE1BX1RPX0RFVklDRSk7DQorCQkJdW5tYXAtPnRvX2NudCsrOw0KKwkJCXVubWFwLT5hZGRy
WzFdID0gZG1hX21hcF9wYWdlKGRldiwgZGVzdCwgMCwgbGVuLA0KKwkJCQkJCSAgICAgIERNQV9C
SURJUkVDVElPTkFMKTsNCisJCQlkbWFfZGVzdFsxXSA9IHVubWFwLT5hZGRyWzFdOw0KKwkJCXVu
bWFwLT5iaWRpX2NudCsrOw0KKwkJCXVubWFwLT5sZW4gPSBsZW47DQorDQorCQkJLyogdGhpcyBs
b29rcyBmdW5ueSwgYnV0IHRoZSBlbmdpbmUgbG9va3MgZm9yIFEgYXQNCisJCQkgKiBkbWFfZGVz
dFsxXSBhbmQgaWdub3JlcyBkbWFfZGVzdFswXSBhcyBhIGRlc3QNCisJCQkgKiBkdWUgdG8gRE1B
X1BSRVBfUFFfRElTQUJMRV9QDQorCQkJICovDQorCQkJdHggPSBkbWEtPmRldmljZV9wcmVwX2Rt
YV9wcShjaGFuLCBkbWFfZGVzdCwNCisJCQkJCQkgICAgIHVubWFwLT5hZGRyLCAxLCAmY29lZiwN
CisJCQkJCQkgICAgIGxlbiwgZG1hX2ZsYWdzKTsNCisNCisJCQlpZiAodHgpIHsNCisJCQkJZG1h
X3NldF91bm1hcCh0eCwgdW5tYXApOw0KKwkJCQlhc3luY190eF9zdWJtaXQoY2hhbiwgdHgsIHN1
Ym1pdCk7DQorCQkJCXJldHVybiB0eDsNCisJCQl9DQorDQorCQkJLyogY291bGQgbm90IGdldCBh
IGRlc2NyaXB0b3IsIHVubWFwIGFuZCBmYWxsIHRocm91Z2ggdG8NCisJCQkgKiB0aGUgc3luY2hy
b25vdXMgcGF0aA0KKwkJCSAqLw0KIAkJCWRtYWVuZ2luZV91bm1hcF9wdXQodW5tYXApOw0KLQkJ
CWFzeW5jX3R4X3N1Ym1pdChjaGFuLCB0eCwgc3VibWl0KTsNCi0JCQlyZXR1cm4gdHg7DQogCQl9
DQotDQotCQkvKiBjb3VsZCBub3QgZ2V0IGEgZGVzY3JpcHRvciwgdW5tYXAgYW5kIGZhbGwgdGhy
b3VnaCB0bw0KLQkJICogdGhlIHN5bmNocm9ub3VzIHBhdGgNCi0JCSAqLw0KLQkJZG1hZW5naW5l
X3VubWFwX3B1dCh1bm1hcCk7DQogCX0NCiANCiAJLyogbm8gY2hhbm5lbCBhdmFpbGFibGUsIG9y
IGZhaWxlZCB0byBhbGxvY2F0ZSBhIGRlc2NyaXB0b3IsIHNvIGRpZmYgLS1naXQgYS9jcnlwdG8v
YXN5bmNfdHgvYXN5bmNfeG9yLmMgYi9jcnlwdG8vYXN5bmNfdHgvYXN5bmNfeG9yLmMgaW5kZXgg
M2M1NjJmNS4uMDE5ZTQ2OSAxMDA2NDQNCi0tLSBhL2NyeXB0by9hc3luY190eC9hc3luY194b3Iu
Yw0KKysrIGIvY3J5cHRvL2FzeW5jX3R4L2FzeW5jX3hvci5jDQpAQCAtMTgyLDU1ICsxODIsNTcg
QEAgYXN5bmNfeG9yKHN0cnVjdCBwYWdlICpkZXN0LCBzdHJ1Y3QgcGFnZSAqKnNyY19saXN0LCB1
bnNpZ25lZCBpbnQgb2Zmc2V0LA0KIA0KIAlCVUdfT04oc3JjX2NudCA8PSAxKTsNCiANCi0JaWYg
KGRldmljZSkNCi0JCXVubWFwID0gZG1hZW5naW5lX2dldF91bm1hcF9kYXRhKGRldmljZS0+ZGV2
LCBzcmNfY250KzEsIEdGUF9OT0lPKTsNCi0NCi0JaWYgKHVubWFwICYmIGlzX2RtYV94b3JfYWxp
Z25lZChkZXZpY2UsIG9mZnNldCwgMCwgbGVuKSkgew0KKwlpZiAoZGV2aWNlICYmIGlzX2RtYV94
b3JfYWxpZ25lZChkZXZpY2UsIG9mZnNldCwgMCwgbGVuKSkgew0KIAkJc3RydWN0IGRtYV9hc3lu
Y190eF9kZXNjcmlwdG9yICp0eDsNCiAJCWludCBpLCBqOw0KIA0KIAkJLyogcnVuIHRoZSB4b3Ig
YXN5bmNocm9ub3VzbHkgKi8NCiAJCXByX2RlYnVnKCIlcyAoYXN5bmMpOiBsZW46ICV6dVxuIiwg
X19mdW5jX18sIGxlbik7DQogDQotCQl1bm1hcC0+bGVuID0gbGVuOw0KLQkJZm9yIChpID0gMCwg
aiA9IDA7IGkgPCBzcmNfY250OyBpKyspIHsNCi0JCQlpZiAoIXNyY19saXN0W2ldKQ0KLQkJCQlj
b250aW51ZTsNCi0JCQl1bm1hcC0+dG9fY250Kys7DQotCQkJdW5tYXAtPmFkZHJbaisrXSA9IGRt
YV9tYXBfcGFnZShkZXZpY2UtPmRldiwgc3JjX2xpc3RbaV0sDQotCQkJCQkJCW9mZnNldCwgbGVu
LCBETUFfVE9fREVWSUNFKTsNCi0JCX0NCisJCXVubWFwID0gZG1hZW5naW5lX2dldF91bm1hcF9k
YXRhKGRldmljZS0+ZGV2LCBzcmNfY250ICsgMSwNCisJCQkJCQkgR0ZQX05PSU8pOw0KKwkJaWYg
KHVubWFwKSB7DQorCQkJdW5tYXAtPmxlbiA9IGxlbjsNCisJCQlmb3IgKGkgPSAwLCBqID0gMDsg
aSA8IHNyY19jbnQ7IGkrKykgew0KKwkJCQlpZiAoIXNyY19saXN0W2ldKQ0KKwkJCQkJY29udGlu
dWU7DQorCQkJCXVubWFwLT50b19jbnQrKzsNCisJCQkJdW5tYXAtPmFkZHJbaisrXSA9IGRtYV9t
YXBfcGFnZShkZXZpY2UtPmRldiwNCisJCQkJCQkJCXNyY19saXN0W2ldLA0KKwkJCQkJCQkJb2Zm
c2V0LCBsZW4sDQorCQkJCQkJCQlETUFfVE9fREVWSUNFKTsNCisJCQl9DQogDQotCQkvKiBtYXAg
aXQgYmlkaXJlY3Rpb25hbCBhcyBpdCBtYXkgYmUgcmUtdXNlZCBhcyBhIHNvdXJjZSAqLw0KLQkJ
dW5tYXAtPmFkZHJbal0gPSBkbWFfbWFwX3BhZ2UoZGV2aWNlLT5kZXYsIGRlc3QsIG9mZnNldCwg
bGVuLA0KLQkJCQkJICAgICAgRE1BX0JJRElSRUNUSU9OQUwpOw0KLQkJdW5tYXAtPmJpZGlfY250
ID0gMTsNCi0NCi0JCXR4ID0gZG9fYXN5bmNfeG9yKGNoYW4sIHVubWFwLCBzdWJtaXQpOw0KLQkJ
ZG1hZW5naW5lX3VubWFwX3B1dCh1bm1hcCk7DQotCQlyZXR1cm4gdHg7DQotCX0gZWxzZSB7DQot
CQlkbWFlbmdpbmVfdW5tYXBfcHV0KHVubWFwKTsNCi0JCS8qIHJ1biB0aGUgeG9yIHN5bmNocm9u
b3VzbHkgKi8NCi0JCXByX2RlYnVnKCIlcyAoc3luYyk6IGxlbjogJXp1XG4iLCBfX2Z1bmNfXywg
bGVuKTsNCi0JCVdBUk5fT05DRShjaGFuLCAiJXM6IG5vIHNwYWNlIGZvciBkbWEgYWRkcmVzcyBj
b252ZXJzaW9uXG4iLA0KLQkJCSAgX19mdW5jX18pOw0KLQ0KLQkJLyogaW4gdGhlIHN5bmMgY2Fz
ZSB0aGUgZGVzdCBpcyBhbiBpbXBsaWVkIHNvdXJjZQ0KLQkJICogKGFzc3VtZXMgdGhlIGRlc3Qg
aXMgdGhlIGZpcnN0IHNvdXJjZSkNCi0JCSAqLw0KLQkJaWYgKHN1Ym1pdC0+ZmxhZ3MgJiBBU1lO
Q19UWF9YT1JfRFJPUF9EU1QpIHsNCi0JCQlzcmNfY250LS07DQotCQkJc3JjX2xpc3QrKzsNCisJ
CQkvKiBtYXAgaXQgYmlkaXJlY3Rpb25hbCBhcyBpdCBtYXkgYmUgcmUtdXNlZA0KKwkJCSAgIGFz
IGEgc291cmNlICovDQorCQkJdW5tYXAtPmFkZHJbal0gPSBkbWFfbWFwX3BhZ2UoZGV2aWNlLT5k
ZXYsIGRlc3QsIG9mZnNldCwNCisJCQkJCQkgICAgICBsZW4sIERNQV9CSURJUkVDVElPTkFMKTsN
CisJCQl1bm1hcC0+YmlkaV9jbnQgPSAxOw0KKw0KKwkJCXR4ID0gZG9fYXN5bmNfeG9yKGNoYW4s
IHVubWFwLCBzdWJtaXQpOw0KKwkJCXJldHVybiB0eDsNCiAJCX0NCisJfQ0KIA0KLQkJLyogd2Fp
dCBmb3IgYW55IHByZXJlcXVpc2l0ZSBvcGVyYXRpb25zICovDQotCQlhc3luY190eF9xdWllc2Nl
KCZzdWJtaXQtPmRlcGVuZF90eCk7DQorCS8qIHJ1biB0aGUgeG9yIHN5bmNocm9ub3VzbHkgKi8N
CisJcHJfZGVidWcoIiVzIChzeW5jKTogbGVuOiAlenVcbiIsIF9fZnVuY19fLCBsZW4pOw0KKwlX
QVJOX09OQ0UoY2hhbiwgIiVzOiBubyBzcGFjZSBmb3IgZG1hIGFkZHJlc3MgY29udmVyc2lvblxu
IiwNCisJCSAgX19mdW5jX18pOw0KKw0KKwkvKiBpbiB0aGUgc3luYyBjYXNlIHRoZSBkZXN0IGlz
IGFuIGltcGxpZWQgc291cmNlDQorCSAqIChhc3N1bWVzIHRoZSBkZXN0IGlzIHRoZSBmaXJzdCBz
b3VyY2UpDQorCSAqLw0KKwlpZiAoc3VibWl0LT5mbGFncyAmIEFTWU5DX1RYX1hPUl9EUk9QX0RT
VCkgew0KKwkJc3JjX2NudC0tOw0KKwkJc3JjX2xpc3QrKzsNCisJfQ0KIA0KLQkJZG9fc3luY194
b3IoZGVzdCwgc3JjX2xpc3QsIG9mZnNldCwgc3JjX2NudCwgbGVuLCBzdWJtaXQpOw0KKwkvKiB3
YWl0IGZvciBhbnkgcHJlcmVxdWlzaXRlIG9wZXJhdGlvbnMgKi8NCisJYXN5bmNfdHhfcXVpZXNj
ZSgmc3VibWl0LT5kZXBlbmRfdHgpOw0KIA0KLQkJcmV0dXJuIE5VTEw7DQotCX0NCisJZG9fc3lu
Y194b3IoZGVzdCwgc3JjX2xpc3QsIG9mZnNldCwgc3JjX2NudCwgbGVuLCBzdWJtaXQpOw0KKw0K
KwlyZXR1cm4gTlVMTDsNCiB9DQogRVhQT1JUX1NZTUJPTF9HUEwoYXN5bmNfeG9yKTsNCiANCkBA
IC0yNzUsMTMgKzI3NywxMSBAQCBhc3luY194b3JfdmFsKHN0cnVjdCBwYWdlICpkZXN0LCBzdHJ1
Y3QgcGFnZSAqKnNyY19saXN0LCB1bnNpZ25lZCBpbnQgb2Zmc2V0LA0KIAlzdHJ1Y3QgZG1hX2Rl
dmljZSAqZGV2aWNlID0gY2hhbiA/IGNoYW4tPmRldmljZSA6IE5VTEw7DQogCXN0cnVjdCBkbWFf
YXN5bmNfdHhfZGVzY3JpcHRvciAqdHggPSBOVUxMOw0KIAlzdHJ1Y3QgZG1hZW5naW5lX3VubWFw
X2RhdGEgKnVubWFwID0gTlVMTDsNCisJZW51bSBhc3luY190eF9mbGFncyBmbGFnc19vcmlnID0g
c3VibWl0LT5mbGFnczsNCiANCiAJQlVHX09OKHNyY19jbnQgPD0gMSk7DQogDQotCWlmIChkZXZp
Y2UpDQotCQl1bm1hcCA9IGRtYWVuZ2luZV9nZXRfdW5tYXBfZGF0YShkZXZpY2UtPmRldiwgc3Jj
X2NudCwgR0ZQX05PSU8pOw0KLQ0KLQlpZiAodW5tYXAgJiYgc3JjX2NudCA8PSBkZXZpY2UtPm1h
eF94b3IgJiYNCisJaWYgKGRldmljZSAmJiBzcmNfY250IDw9IGRldmljZS0+bWF4X3hvciAmJg0K
IAkgICAgaXNfZG1hX3hvcl9hbGlnbmVkKGRldmljZSwgb2Zmc2V0LCAwLCBsZW4pKSB7DQogCQl1
bnNpZ25lZCBsb25nIGRtYV9wcmVwX2ZsYWdzID0gMDsNCiAJCWludCBpOw0KQEAgLTI5Myw1MSAr
MjkzLDU5IEBAIGFzeW5jX3hvcl92YWwoc3RydWN0IHBhZ2UgKmRlc3QsIHN0cnVjdCBwYWdlICoq
c3JjX2xpc3QsIHVuc2lnbmVkIGludCBvZmZzZXQsDQogCQlpZiAoc3VibWl0LT5mbGFncyAmIEFT
WU5DX1RYX0ZFTkNFKQ0KIAkJCWRtYV9wcmVwX2ZsYWdzIHw9IERNQV9QUkVQX0ZFTkNFOw0KIA0K
LQkJZm9yIChpID0gMDsgaSA8IHNyY19jbnQ7IGkrKykgew0KLQkJCXVubWFwLT5hZGRyW2ldID0g
ZG1hX21hcF9wYWdlKGRldmljZS0+ZGV2LCBzcmNfbGlzdFtpXSwNCi0JCQkJCQkgICAgICBvZmZz
ZXQsIGxlbiwgRE1BX1RPX0RFVklDRSk7DQotCQkJdW5tYXAtPnRvX2NudCsrOw0KLQkJfQ0KLQkJ
dW5tYXAtPmxlbiA9IGxlbjsNCi0NCi0JCXR4ID0gZGV2aWNlLT5kZXZpY2VfcHJlcF9kbWFfeG9y
X3ZhbChjaGFuLCB1bm1hcC0+YWRkciwgc3JjX2NudCwNCi0JCQkJCQkgICAgIGxlbiwgcmVzdWx0
LA0KLQkJCQkJCSAgICAgZG1hX3ByZXBfZmxhZ3MpOw0KLQkJaWYgKHVubGlrZWx5KCF0eCkpIHsN
Ci0JCQlhc3luY190eF9xdWllc2NlKCZzdWJtaXQtPmRlcGVuZF90eCk7DQotDQotCQkJd2hpbGUg
KCF0eCkgew0KLQkJCQlkbWFfYXN5bmNfaXNzdWVfcGVuZGluZyhjaGFuKTsNCi0JCQkJdHggPSBk
ZXZpY2UtPmRldmljZV9wcmVwX2RtYV94b3JfdmFsKGNoYW4sDQotCQkJCQl1bm1hcC0+YWRkciwg
c3JjX2NudCwgbGVuLCByZXN1bHQsDQotCQkJCQlkbWFfcHJlcF9mbGFncyk7DQorCQl1bm1hcCA9
IGRtYWVuZ2luZV9nZXRfdW5tYXBfZGF0YShkZXZpY2UtPmRldiwgc3JjX2NudCwNCisJCQkJCQkg
R0ZQX05PSU8pOw0KKwkJaWYgKHVubWFwKSB7DQorCQkJZm9yIChpID0gMDsgaSA8IHNyY19jbnQ7
IGkrKykgew0KKwkJCQl1bm1hcC0+YWRkcltpXSA9IGRtYV9tYXBfcGFnZShkZXZpY2UtPmRldiwN
CisJCQkJCQkJICAgICAgc3JjX2xpc3RbaV0sDQorCQkJCQkJCSAgICAgIG9mZnNldCwgbGVuLA0K
KwkJCQkJCQkgICAgICBETUFfVE9fREVWSUNFKTsNCisJCQkJdW5tYXAtPnRvX2NudCsrOw0KKwkJ
CX0NCisJCQl1bm1hcC0+bGVuID0gbGVuOw0KKw0KKwkJCXR4ID0gZGV2aWNlLT5kZXZpY2VfcHJl
cF9kbWFfeG9yX3ZhbChjaGFuLCB1bm1hcC0+YWRkciwNCisJCQkJCQkJICAgICBzcmNfY250LA0K
KwkJCQkJCQkgICAgIGxlbiwgcmVzdWx0LA0KKwkJCQkJCQkgICAgIGRtYV9wcmVwX2ZsYWdzKTsN
CisJCQlpZiAodW5saWtlbHkoIXR4KSkgew0KKwkJCQlhc3luY190eF9xdWllc2NlKCZzdWJtaXQt
PmRlcGVuZF90eCk7DQorDQorCQkJCXdoaWxlICghdHgpIHsNCisJCQkJCWRtYV9hc3luY19pc3N1
ZV9wZW5kaW5nKGNoYW4pOw0KKwkJCQkJdHggPSBkZXZpY2UtPmRldmljZV9wcmVwX2RtYV94b3Jf
dmFsKA0KKwkJCQkJCQljaGFuLCB1bm1hcC0+YWRkciwNCisJCQkJCQkJc3JjX2NudCwgbGVuLA0K
KwkJCQkJCQlyZXN1bHQsIGRtYV9wcmVwX2ZsYWdzKTsNCisJCQkJfQ0KIAkJCX0NCisJCQlkbWFf
c2V0X3VubWFwKHR4LCB1bm1hcCk7DQorCQkJYXN5bmNfdHhfc3VibWl0KGNoYW4sIHR4LCBzdWJt
aXQpOw0KKw0KKwkJCXJldHVybiB0eDsNCiAJCX0NCi0JCWRtYV9zZXRfdW5tYXAodHgsIHVubWFw
KTsNCi0JCWFzeW5jX3R4X3N1Ym1pdChjaGFuLCB0eCwgc3VibWl0KTsNCi0JfSBlbHNlIHsNCi0J
CWVudW0gYXN5bmNfdHhfZmxhZ3MgZmxhZ3Nfb3JpZyA9IHN1Ym1pdC0+ZmxhZ3M7DQorCX0NCiAN
Ci0JCXByX2RlYnVnKCIlczogKHN5bmMpIGxlbjogJXp1XG4iLCBfX2Z1bmNfXywgbGVuKTsNCi0J
CVdBUk5fT05DRShkZXZpY2UgJiYgc3JjX2NudCA8PSBkZXZpY2UtPm1heF94b3IsDQotCQkJICAi
JXM6IG5vIHNwYWNlIGZvciBkbWEgYWRkcmVzcyBjb252ZXJzaW9uXG4iLA0KLQkJCSAgX19mdW5j
X18pOw0KKwkvKiBydW4gdGhlIHhvcl92YWwgc3luY2hyb25vdXNseSAqLw0KKwlwcl9kZWJ1Zygi
JXM6IChzeW5jKSBsZW46ICV6dVxuIiwgX19mdW5jX18sIGxlbik7DQorCVdBUk5fT05DRShkZXZp
Y2UgJiYgc3JjX2NudCA8PSBkZXZpY2UtPm1heF94b3IsDQorCQkgICIlczogbm8gc3BhY2UgZm9y
IGRtYSBhZGRyZXNzIGNvbnZlcnNpb25cbiIsDQorCQkgIF9fZnVuY19fKTsNCiANCi0JCXN1Ym1p
dC0+ZmxhZ3MgfD0gQVNZTkNfVFhfWE9SX0RST1BfRFNUOw0KLQkJc3VibWl0LT5mbGFncyAmPSB+
QVNZTkNfVFhfQUNLOw0KKwlzdWJtaXQtPmZsYWdzIHw9IEFTWU5DX1RYX1hPUl9EUk9QX0RTVDsN
CisJc3VibWl0LT5mbGFncyAmPSB+QVNZTkNfVFhfQUNLOw0KIA0KLQkJdHggPSBhc3luY194b3Io
ZGVzdCwgc3JjX2xpc3QsIG9mZnNldCwgc3JjX2NudCwgbGVuLCBzdWJtaXQpOw0KKwl0eCA9IGFz
eW5jX3hvcihkZXN0LCBzcmNfbGlzdCwgb2Zmc2V0LCBzcmNfY250LCBsZW4sIHN1Ym1pdCk7DQog
DQotCQlhc3luY190eF9xdWllc2NlKCZ0eCk7DQorCWFzeW5jX3R4X3F1aWVzY2UoJnR4KTsNCiAN
Ci0JCSpyZXN1bHQgPSAhcGFnZV9pc196ZXJvKGRlc3QsIG9mZnNldCwgbGVuKSA8PCBTVU1fQ0hF
Q0tfUDsNCisJKnJlc3VsdCA9ICFwYWdlX2lzX3plcm8oZGVzdCwgb2Zmc2V0LCBsZW4pIDw8IFNV
TV9DSEVDS19QOw0KIA0KLQkJYXN5bmNfdHhfc3luY19lcGlsb2coc3VibWl0KTsNCi0JCXN1Ym1p
dC0+ZmxhZ3MgPSBmbGFnc19vcmlnOw0KLQl9DQotCWRtYWVuZ2luZV91bm1hcF9wdXQodW5tYXAp
Ow0KKwlhc3luY190eF9zeW5jX2VwaWxvZyhzdWJtaXQpOw0KKwlzdWJtaXQtPmZsYWdzID0gZmxh
Z3Nfb3JpZzsNCiANCi0JcmV0dXJuIHR4Ow0KKwlyZXR1cm4gTlVMTDsNCiB9DQogRVhQT1JUX1NZ
TUJPTF9HUEwoYXN5bmNfeG9yX3ZhbCk7DQogDQotLQ0KMS44LjMuMg0KDQoNCg==
^ permalink raw reply
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Greg Kurz @ 2014-03-31 8:47 UTC (permalink / raw)
To: Stewart Smith; +Cc: linux-kernel, paulus, anton, nfont, linuxppc-dev
In-Reply-To: <87vbuv9vaz.fsf@river.i-did-not-set--mail-host-address--so-tickle-me>
On Mon, 31 Mar 2014 09:27:16 +1100
Stewart Smith <stewart@linux.vnet.ibm.com> wrote:
> Greg Kurz <gkurz@linux.vnet.ibm.com> writes:
> > struct rtas_error_log {
> > +#ifdef __BIG_ENDIAN__
> > + /* Byte 0 */
> > unsigned long version:8; /* Architectural version */
> > + /* Byte 1 */
>
> I think it would be great if we got rid of the usage of bitfields. As
> soon as the mood of the compiler changes, this code is going to break.
True... even though I am not so sure the compiler is likely to break
things in this specific case where no bitfield crosses the byte boundary.
Anyway, Nathan has done some work in the direction you suggest.
Nathan,
Could you send your patch to the list ?
Thanks.
--
Gregory Kurz kurzgreg@fr.ibm.com
gkurz@linux.vnet.ibm.com
Software Engineer @ IBM/Meiosys http://www.ibm.com
Tel +33 (0)562 165 496
"Anarchy is about taking complete responsibility for yourself."
Alan Moore.
^ permalink raw reply
* [PATCH] ASoC: fsl_sai: Fix buggy configurations in trigger()
From: Nicolin Chen @ 2014-03-31 11:39 UTC (permalink / raw)
To: broonie; +Cc: alsa-devel, Li.Xiubo, linuxppc-dev, linux-kernel, timur
The current trigger() has two crucial problems:
1) The DMA request enabling operations (FSL_SAI_CSR_FRDE) for Tx and Rx are
now totally exclusive: It would fail to run simultaneous Tx-Rx cases.
2) The TERE disabling operation depends on an incorrect condition -- active
reference count that only gets increased in snd_pcm_open() and decreased
in snd_pcm_close(): The TERE would never get cleared.
So this patch overwrites the trigger function by following these rules:
A) We continue to support tx-async-while-rx-sync-to-tx case alone, which's
originally limited by this fsl_sai driver, but we make the code easy to
modify for the further support of the opposite case.
B) We enable both TE and RE for PLAYBACK stream or CAPTURE stream but only
enabling the DMA request bit (FSL_SAI_CSR_FRDE) of the current direction
due to the requirement of SAI -- For tx-async-while-rx-sync-to-tx case,
the receiver is enabled only when both the transmitter and receiver are
enabled.
C) We only enable one side interrupt for each stream since over/underrun
on the opposite stream would be resulted from what we've done in rule B:
enabling TERE but remaining FRDE disabled, even though the xrun on the
opposite direction will not break the current stream.
Tested cases:
a) aplay test.wav -d5
b) arecord -r44100 -c2 -fS16_LE test.wav -d5
c) arecord -r44100 -c2 -fS16_LE -d5 | aplay
d) (aplay test2.wav &); sleep 1; arecord -r44100 -c2 -fS16_LE test.wav -d1
e) (arecord -r44100 -c2 -fS16_LE test.wav -d5 &); sleep 1; aplay test.wav -d1
Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
---
sound/soc/fsl/fsl_sai.c | 43 +++++++++++++++++++++++--------------------
sound/soc/fsl/fsl_sai.h | 11 +++++++++++
2 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index f088545..d64c33f 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -365,6 +365,7 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u32 tcsr, rcsr;
/*
@@ -379,14 +380,6 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- tcsr |= FSL_SAI_CSR_FRDE;
- rcsr &= ~FSL_SAI_CSR_FRDE;
- } else {
- rcsr |= FSL_SAI_CSR_FRDE;
- tcsr &= ~FSL_SAI_CSR_FRDE;
- }
-
/*
* It is recommended that the transmitter is the last enabled
* and the first disabled.
@@ -395,22 +388,32 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- tcsr |= FSL_SAI_CSR_TERE;
- rcsr |= FSL_SAI_CSR_TERE;
+ if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE);
+ }
- regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
- regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (!(cpu_dai->playback_active || cpu_dai->capture_active)) {
- tcsr &= ~FSL_SAI_CSR_TERE;
- rcsr &= ~FSL_SAI_CSR_TERE;
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ FSL_SAI_CSR_FRDE, 0);
+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
+ FSL_SAI_CSR_xIE_MASK, 0);
+
+ if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
+ FSL_SAI_CSR_TERE, 0);
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
+ FSL_SAI_CSR_TERE, 0);
}
-
- regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
- regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
break;
default:
return -EINVAL;
@@ -464,8 +467,8 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
- regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, FSL_SAI_FLAGS);
- regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, FSL_SAI_FLAGS);
+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0);
+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0);
regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
FSL_SAI_MAXBURST_TX * 2);
regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index a264185..be26d46 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -35,6 +35,16 @@
#define FSL_SAI_RFR 0xc0 /* SAI Receive FIFO */
#define FSL_SAI_RMR 0xe0 /* SAI Receive Mask */
+#define FSL_SAI_xCSR(tx) (tx ? FSL_SAI_TCSR : FSL_SAI_RCSR)
+#define FSL_SAI_xCR1(tx) (tx ? FSL_SAI_TCR1 : FSL_SAI_RCR1)
+#define FSL_SAI_xCR2(tx) (tx ? FSL_SAI_TCR2 : FSL_SAI_RCR2)
+#define FSL_SAI_xCR3(tx) (tx ? FSL_SAI_TCR3 : FSL_SAI_RCR3)
+#define FSL_SAI_xCR4(tx) (tx ? FSL_SAI_TCR4 : FSL_SAI_RCR4)
+#define FSL_SAI_xCR5(tx) (tx ? FSL_SAI_TCR5 : FSL_SAI_RCR5)
+#define FSL_SAI_xDR(tx) (tx ? FSL_SAI_TDR : FSL_SAI_RDR)
+#define FSL_SAI_xFR(tx) (tx ? FSL_SAI_TFR : FSL_SAI_RFR)
+#define FSL_SAI_xMR(tx) (tx ? FSL_SAI_TMR : FSL_SAI_RMR)
+
/* SAI Transmit/Recieve Control Register */
#define FSL_SAI_CSR_TERE BIT(31)
#define FSL_SAI_CSR_FR BIT(25)
@@ -48,6 +58,7 @@
#define FSL_SAI_CSR_FWF BIT(17)
#define FSL_SAI_CSR_FRF BIT(16)
#define FSL_SAI_CSR_xIE_SHIFT 8
+#define FSL_SAI_CSR_xIE_MASK (0x1f << FSL_SAI_CSR_xIE_SHIFT)
#define FSL_SAI_CSR_WSIE BIT(12)
#define FSL_SAI_CSR_SEIE BIT(11)
#define FSL_SAI_CSR_FEIE BIT(10)
--
1.8.4
^ permalink raw reply related
* Re: [PATCH] powerpc/le: enable RTAS events support
From: Benjamin Herrenschmidt @ 2014-03-31 11:56 UTC (permalink / raw)
To: Stewart Smith; +Cc: linux-kernel, paulus, anton, nfont, linuxppc-dev, Greg Kurz
In-Reply-To: <87vbuv9vaz.fsf@river.i-did-not-set--mail-host-address--so-tickle-me>
On Mon, 2014-03-31 at 09:27 +1100, Stewart Smith wrote:
> Greg Kurz <gkurz@linux.vnet.ibm.com> writes:
> > struct rtas_error_log {
> > +#ifdef __BIG_ENDIAN__
> > + /* Byte 0 */
> > unsigned long version:8; /* Architectural version */
> > + /* Byte 1 */
>
> I think it would be great if we got rid of the usage of bitfields. As
> soon as the mood of the compiler changes, this code is going to break.
... as would a whole pile of kernel code including filesystems :)
Now, don't get me wrong, I hate bitfields as much as you do for the same
reasons. However (unfortunately ?) we've somewhat painted ourselves into
a corner here in kernel-land and I suspect gcc would have a very hard
time changing the format considering how many people did just the same
we did.
Now if we were a userspace program, I would still insist on fixing it on
the ground on not depending on gcc but this is the kernel ... we have
more gcc'isms than spots on the face of a 14 yrs old..
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 1/2] powerpc/powernv: Add OPAL message log interface
From: Benjamin Herrenschmidt @ 2014-03-31 11:59 UTC (permalink / raw)
To: Michael Neuling
Cc: stewart, michael, shangw, hegdevasant, paulus, Joel Stanley,
linuxppc-dev, anton
In-Reply-To: <21604.1396238935@ale.ozlabs.ibm.com>
On Mon, 2014-03-31 at 15:08 +1100, Michael Neuling wrote:
> > +/* OPAL in-memory console. Defined in OPAL source at core/console.c */
> > +struct memcons {
> > + __be64 magic;
> > +#define MEMCONS_MAGIC 0x6630696567726173L
>
> 0x6630696567726173 == f0iegras ... Ben!!! :-P
Yummy ! :-)
> > + __be64 obuf_phys;
> > + __be64 ibuf_phys;
> > + __be32 obuf_size;
> > + __be32 ibuf_size;
> > + __be32 out_pos;
> > +#define MEMCONS_OUT_POS_WRAP 0x80000000u
> > +#define MEMCONS_OUT_POS_MASK 0x00ffffffu
> > + __be32 in_prod;
> > + __be32 in_cons;
> > +};
> > +
> > +static ssize_t opal_messages_read(struct file *file, struct kobject *kobj,
> > + struct bin_attribute *bin_attr, char *to, loff_t pos, size_t count)
> > +{
> > + struct memcons *mc = bin_attr->private;
> > + const char *conbuf;
> > + bool wrapped;
> > + size_t num_read;
> > + int out_pos;
> > +
> > + if (!mc)
> > + return -ENODEV;
> > +
> > + conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
> > + wrapped = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_WRAP;
> > + out_pos = be32_to_cpu(mc->out_pos) & MEMCONS_OUT_POS_MASK;
> > +
>
> Are there ordering issues we need to think about here with reading
> these? Can the messages be written on another CPU at the same time as
> these are being read?
Good point. out_pos should probably be read only once into a local
variable using the ACCESS_ONCE macro, and then only be broken up.
> What happens if in between reading wrapped and out_pos the buffer wraps?
> You'd end up getting only a few bytes of console? Maybe you need to
> read wrapped before and after out_pos to make should it's not wrapped in
> between.
Unlikely but yes, it can happen.
> > + if (!wrapped) {
>
> Why the negative case first? Just make it:
>
> if (wrapped) {
> wrapped case
> } else {
> not wrapped case
> }
>
> Also, no curlies needed for single statement.
>
>
> > + num_read = memory_read_from_buffer(to, count, &pos, conbuf,
> > + out_pos);
>
> This is probably not necessary, but do we need to sanity check out_pos <
> obuf_size? I guess we don't generally sanity check numbers from OPAL as
> it can screw us in many other ways anyway.
On the other hand it doesn't cost much and if the FW goes bonkers it
will give us a better handle to debug from.
> > + } else {
> > + num_read = memory_read_from_buffer(to, count, &pos,
> > + conbuf + out_pos,
> > + be32_to_cpu(mc->obuf_size) - out_pos);
> > +
> > + if (num_read < 0)
> > + goto out;
> > +
> > + num_read += memory_read_from_buffer(to + num_read,
> > + count - num_read, &pos, conbuf,
> > out_pos);
>
> What if this second read returns an error? num_read += -ERRNO? I think
> you need to check this return independently.
Cheers,
Ben.
> Mikey
>
> > + }
> > +out:
> > + return num_read;
> > +}
> > +
> > +static struct bin_attribute messages_attr = {
> > + .attr = {.name = "messages", .mode = 0444},
> > + .read = opal_messages_read
> > +};
> > +
> > +void __init opal_messages_init(void)
> > +{
> > + u64 mcaddr;
> > + struct memcons *mc;
> > +
> > + if (of_property_read_u64(opal_node, "ibm,opal-memcons", &mcaddr)) {
> > + pr_warn("OPAL: Property ibm,opal-memcons not found, no message log\n");
> > + return;
> > + }
> > +
> > + mc = phys_to_virt(mcaddr);
> > + if (!mc) {
> > + pr_warn("OPAL: memory console address is invalid\n");
> > + return;
> > + }
> > +
> > + if (be64_to_cpu(mc->magic) != MEMCONS_MAGIC) {
> > + pr_warn("OPAL: memory console version is invalid\n");
> > + return;
> > + }
> > +
> > + messages_attr.private = mc;
> > +
> > + if (sysfs_create_bin_file(opal_kobj, &messages_attr) != 0)
> > + pr_warn("OPAL: sysfs file creation failed\n");
> > +}
> > diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> > index e92f2f6..2bc032a 100644
> > --- a/arch/powerpc/platforms/powernv/opal.c
> > +++ b/arch/powerpc/platforms/powernv/opal.c
> > @@ -46,7 +46,7 @@ struct mcheck_recoverable_range {
> > static struct mcheck_recoverable_range *mc_recoverable_range;
> > static int mc_recoverable_range_len;
> >
> > -static struct device_node *opal_node;
> > +struct device_node *opal_node;
> > static DEFINE_SPINLOCK(opal_write_lock);
> > extern u64 opal_mc_secondary_handler[];
> > static unsigned int *opal_irqs;
> > @@ -574,6 +574,8 @@ static int __init opal_init(void)
> > opal_platform_dump_init();
> > /* Setup system parameters interface */
> > opal_sys_param_init();
> > + /* Setup message log interface. */
> > + opal_messages_init();
> > }
> >
> > return 0;
> > --
> > 1.9.1
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 3/4] KVM: PPC: Alow kvmppc_get_last_inst() to fail
From: Alexander Graf @ 2014-03-31 13:32 UTC (permalink / raw)
To: Scott Wood; +Cc: Mihai Caraman, linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1395867121.12738.56.camel@snotra.buserror.net>
On 03/26/2014 09:52 PM, Scott Wood wrote:
> On Thu, 2014-02-20 at 18:30 +0200, Mihai Caraman wrote:
>> diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
>> index a59a25a..80c533e 100644
>> --- a/arch/powerpc/kvm/book3s_paired_singles.c
>> +++ b/arch/powerpc/kvm/book3s_paired_singles.c
>> @@ -640,19 +640,24 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc,
>>
>> int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
>> {
>> - u32 inst = kvmppc_get_last_inst(vcpu);
>> + u32 inst;
>> enum emulation_result emulated = EMULATE_DONE;
>> -
>> - int ax_rd = inst_get_field(inst, 6, 10);
>> - int ax_ra = inst_get_field(inst, 11, 15);
>> - int ax_rb = inst_get_field(inst, 16, 20);
>> - int ax_rc = inst_get_field(inst, 21, 25);
>> - short full_d = inst_get_field(inst, 16, 31);
>> -
>> - u64 *fpr_d = &vcpu->arch.fpr[ax_rd];
>> - u64 *fpr_a = &vcpu->arch.fpr[ax_ra];
>> - u64 *fpr_b = &vcpu->arch.fpr[ax_rb];
>> - u64 *fpr_c = &vcpu->arch.fpr[ax_rc];
>> + int ax_rd, ax_ra, ax_rb, ax_rc;
>> + short full_d;
>> + u64 *fpr_d, *fpr_a, *fpr_b, *fpr_c;
>> +
>> + kvmppc_get_last_inst(vcpu, &inst);
> Should probably check for failure here and elsewhere -- even though it
> can't currently fail on book3s, the interface now allows it.
>
>> diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
>> index 5b9e906..b0d884d 100644
>> --- a/arch/powerpc/kvm/book3s_pr.c
>> +++ b/arch/powerpc/kvm/book3s_pr.c
>> @@ -624,9 +624,10 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
>> static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
>> {
>> ulong srr0 = kvmppc_get_pc(vcpu);
>> - u32 last_inst = kvmppc_get_last_inst(vcpu);
>> + u32 last_inst;
>> int ret;
>>
>> + kvmppc_get_last_inst(vcpu, &last_inst);
>> ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
> This isn't new, but this function looks odd to me -- calling
> kvmppc_get_last_inst() but ignoring last_inst, then calling kvmppc_ld()
> and ignoring anything but failure. last_inst itself is never read. And
> no comments to explain the weirdness. :-)
>
> I get that kvmppc_get_last_inst() is probably being used for the side
> effect of filling in vcpu->arch.last_inst, but why store the return
> value without using it? Why pass the address of it to kvmppc_ld(),
> which seems to be used only as an indirect way of determining whether
> kvmppc_get_last_inst() failed? And that whole mechanism becomes
> stranger once it becomes possible for kvmppc_get_last_inst() to directly
> return failure.
If you're interested in the history of this, here's the patch :)
https://github.com/mirrors/linux-2.6/commit/c7f38f46f2a98d232147e47284cb4e7363296a3e
The idea is that we need 2 things to be good after this function:
1) vcpu->arch.last_inst is valid
2) if the last instruction is not readable, return failure
Hence this weird construct. I don't think it's really necessary though -
just remove the kvmppc_ld() call and only fail read_inst() when the
caching didn't work and we can't translate the address.
Alex
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox