* Re: [PATCH 4/4] powerpc/eeh: Avoid event on passed PE
From: Alexander Graf @ 2014-05-21 6:20 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: aik@ozlabs.ru, Gavin Shan, kvm-ppc@vger.kernel.org,
alex.williamson@redhat.com, qiudayu@linux.vnet.ibm.com,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1400631544.3986.151.camel@pasglop>
> Am 21.05.2014 um 02:19 schrieb Benjamin Herrenschmidt <benh@kernel.crashin=
g.org>:
>=20
>> On Tue, 2014-05-20 at 15:49 +0200, Alexander Graf wrote:
>> So how about we just implement this whole thing properly as irqfd?=20
>> Whether QEMU can actually do anything with the interrupt is a different=20=
>> question - we can leave it be for now. But we could model all the code=20=
>> with the assumption that it should either handle the error itself or=20
>> trigger and irqfd write.
>=20
> I don't object to the idea... however this smells of Deja Vu...
>=20
> You often tend to want to turn something submitted that fills a specific
> gap and implements a specific spec/function into some kind of idealized
> grand design :-) And that means nothing gets upstream for weeks or monthes=
> as we churn and churn...
>=20
> Sometimes it's probably worth it. Here I would argue against it and would
> advocate for doing the basic functionality first, as it is used by guests,=
> and later add the irqfd option. I don't see any emergency here and adding
> the irqfd will not cause fundamental design changes:
>=20
> The "passed" flag (though I'm not fan of the name) is really something
> we want in the low level handlers to avoid triggering host side EEH in
> various places, regardless of whether we use irqfd or not.
>=20
> This is totally orthogonal from the mechanism used for notifications.
>=20
> Even in host, the detection path doesn't always involve interrupts, and
> we can detect some things as a result of a host side config space access
> for example etc...
>=20
> So let's keep things nice and separate here. The interrupt notification
> is just an "optimization" which will speed up discovery of the error in
> *some* cases later on (but adds its own complexity since we have multiple
> discovery path in host, so we need to keep track whether we have notified
> yet or not etc...) so let's keep it for later.
EEH handling is your call, but I only see reduced complexity here. I won't n=
ak the current approach though.
Alex
^ permalink raw reply
* Re: [PATCH 3/4] drivers/vfio: New IOCTL command VFIO_EEH_INFO
From: Alexander Graf @ 2014-05-21 6:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: aik@ozlabs.ru, Gavin Shan, kvm-ppc@vger.kernel.org,
alex.williamson@redhat.com, qiudayu@linux.vnet.ibm.com,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1400631832.3986.154.camel@pasglop>
> Am 21.05.2014 um 02:23 schrieb Benjamin Herrenschmidt <benh@kernel.crashin=
g.org>:
>=20
> On Tue, 2014-05-20 at 22:39 +1000, Gavin Shan wrote:
>>>> Yeah. How about this? :-)
>>>>=20
>>>> - Move eeh-vfio.c to drivers/vfio/pci/
>>>> - =46rom eeh-vfio.c, dereference arch/powerpc/kernel/eeh.c::eeh_ops, wh=
ich
>>>> is arch/powerpc/plaforms/powernv/eeh-powernv.c::powernv_eeh_ops. Call
>>>=20
>>> Hrm, I think it'd be nicer to just export individual functions that
>>> do thing you want to do from eeh.c.
>>=20
>> Ok. Got it. Thanks for your comments :)
>=20
> The interesting thing with this approach is that VFIO per-se can work
> with EEH RTAS backend too in the host.
>=20
> IE, with PR KVM for example or with non-KVM uses of VFIO, it would be
> possible to use a device in a user process and exploit EEH even when
> running under a PAPR hypervisor.
>=20
> That is, vfio-eeh uses "generic" exported EEH APIs from the EEH core
> that will work on both powernv and RTAS backends.
>=20
> Note to Alex: This definitely kills the notifier idea for now though,
> at least as a first class citizen of the design. We can add it as an
> optional optimization on top later.
I don't think it does. The notifier would just get triggered on config space=
read failures for example :). It's really just an aid for the vfio user to h=
ave a common code path for error handling.
Alex
^ permalink raw reply
* [PATCH 3/3] powerpc: Document sysfs DSCR interface
From: Sam Bobroff @ 2014-05-21 6:32 UTC (permalink / raw)
To: benh; +Cc: aik, mikey, linuxppc-dev
In-Reply-To: <cover.1400652868.git.sam.bobroff@au1.ibm.com>
Add some documentation about ...
/sys/devices/system/cpu/dscr_default
/sys/devices/system/cpu/cpuN/dscr
... to Documentation/ABI/stable.
Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
---
Documentation/ABI/stable/sysfs-devices-system-cpu | 25 +++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/ABI/stable/sysfs-devices-system-cpu
diff --git a/Documentation/ABI/stable/sysfs-devices-system-cpu b/Documentation/ABI/stable/sysfs-devices-system-cpu
new file mode 100644
index 0000000..33c133e
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-system-cpu
@@ -0,0 +1,25 @@
+What: /sys/devices/system/cpu/dscr_default
+Date: 13-May-2014
+KernelVersion: v3.15.0
+Contact:
+Description: Writes are equivalent to writing to
+ /sys/devices/system/cpu/cpuN/dscr on all CPUs.
+ Reads return the last written value or 0.
+ This value is not a global default: it is a way to set
+ all per-CPU defaults at the same time.
+Values: 64 bit unsigned integer (bit field)
+
+What: /sys/devices/system/cpu/cpu[0-9]+/dscr
+Date: 13-May-2014
+KernelVersion: v3.15.0
+Contact:
+Description: Default value for the Data Stream Control Register (DSCR) on
+ a CPU.
+ This default value is used when the kernel is executing and
+ for any process that has not set the DSCR itself.
+ If a process ever sets the DSCR (via direct access to the
+ SPR) that value will be persisted for that process and used
+ on any CPU where it executes (overriding the value described
+ here).
+ If set by a process it will be inherited by child processes.
+Values: 64 bit unsigned integer (bit field)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 2/3] powerpc: fix regression of per-CPU DSCR setting
From: Sam Bobroff @ 2014-05-21 6:32 UTC (permalink / raw)
To: benh; +Cc: aik, mikey, linuxppc-dev
In-Reply-To: <cover.1400652868.git.sam.bobroff@au1.ibm.com>
Since commit "efcac65 powerpc: Per process DSCR + some fixes (try#4)"
it is no longer possible to set the DSCR on a per-CPU basis.
The old behaviour was to minipulate the DSCR SPR directly but this is no
longer sufficient: the value is quickly overwritten by context switching.
This patch stores the per-CPU DSCR value in a kernel variable rather than
directly in the SPR and it is used whenever a process has not set the DSCR
itself. The sysfs interface (/sys/devices/system/cpu/cpuN/dscr) is unchanged.
Writes to the old global default (/sys/devices/system/cpu/dscr_default)
now set all of the per-CPU values and reads return the last written value.
The new per-CPU default is added to the paca_struct and is used everywhere
outside of sysfs.c instead of the old global default.
Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
---
arch/powerpc/include/asm/paca.h | 3 +++
arch/powerpc/kernel/asm-offsets.c | 1 +
arch/powerpc/kernel/entry_64.S | 9 +--------
arch/powerpc/kernel/sysfs.c | 32 ++++++++++++++++++-------------
arch/powerpc/kernel/tm.S | 16 ++++------------
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 3 +--
6 files changed, 29 insertions(+), 35 deletions(-)
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 8e956a0..bb0bd25 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -92,7 +92,10 @@ struct paca_struct {
struct slb_shadow *slb_shadow_ptr;
struct dtl_entry *dispatch_log;
struct dtl_entry *dispatch_log_end;
+#endif /* CONFIG_PPC_STD_MMU_64 */
+ u64 dscr_default; /* per-CPU default DSCR */
+#ifdef CONFIG_PPC_STD_MMU_64
/*
* Now, starting in cacheline 2, the exception save areas
*/
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index dba8140..cba2697 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -247,6 +247,7 @@ int main(void)
#endif
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state));
+ DEFINE(PACA_DSCR, offsetof(struct paca_struct, dscr_default));
DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime));
DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user));
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 9fde8a1..911d453 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -387,12 +387,6 @@ _GLOBAL(ret_from_kernel_thread)
li r3,0
b syscall_exit
- .section ".toc","aw"
-DSCR_DEFAULT:
- .tc dscr_default[TC],dscr_default
-
- .section ".text"
-
/*
* This routine switches between two different tasks. The process
* state of one is saved on its kernel stack. Then the state
@@ -577,11 +571,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#ifdef CONFIG_PPC64
BEGIN_FTR_SECTION
lwz r6,THREAD_DSCR_INHERIT(r4)
- ld r7,DSCR_DEFAULT@toc(2)
ld r0,THREAD_DSCR(r4)
cmpwi r6,0
bne 1f
- ld r0,0(r7)
+ ld r0,PACA_DSCR(r13)
1:
BEGIN_FTR_SECTION_NESTED(70)
mfspr r8, SPRN_FSCR
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index e2a1d6f..67fd2fd 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -484,7 +484,6 @@ SYSFS_PMCSETUP(pmc8, SPRN_PMC8);
SYSFS_PMCSETUP(mmcra, SPRN_MMCRA);
SYSFS_SPRSETUP(purr, SPRN_PURR);
SYSFS_SPRSETUP(spurr, SPRN_SPURR);
-SYSFS_SPRSETUP(dscr, SPRN_DSCR);
SYSFS_SPRSETUP(pir, SPRN_PIR);
/*
@@ -494,12 +493,27 @@ SYSFS_SPRSETUP(pir, SPRN_PIR);
*/
static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
static DEVICE_ATTR(spurr, 0400, show_spurr, NULL);
-static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
static DEVICE_ATTR(purr, 0400, show_purr, store_purr);
static DEVICE_ATTR(pir, 0400, show_pir, NULL);
-unsigned long dscr_default = 0;
-EXPORT_SYMBOL(dscr_default);
+static unsigned long dscr_default;
+
+static void read_dscr(void *val)
+{
+ *(unsigned long *)val = get_paca()->dscr_default;
+}
+
+static void write_dscr(void *val)
+{
+ get_paca()->dscr_default = *(unsigned long *)val;
+ if (!current->thread.dscr_inherit) {
+ current->thread.dscr = *(unsigned long *)val;
+ mtspr(SPRN_DSCR, *(unsigned long *)val);
+ }
+}
+
+SYSFS_SPRSETUP_SHOW_STORE(dscr);
+static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
static void add_write_permission_dev_attr(struct device_attribute *attr)
{
@@ -512,14 +526,6 @@ static ssize_t show_dscr_default(struct device *dev,
return sprintf(buf, "%lx\n", dscr_default);
}
-static void update_dscr(void *dummy)
-{
- if (!current->thread.dscr_inherit) {
- current->thread.dscr = dscr_default;
- mtspr(SPRN_DSCR, dscr_default);
- }
-}
-
static ssize_t __used store_dscr_default(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -532,7 +538,7 @@ static ssize_t __used store_dscr_default(struct device *dev,
return -EINVAL;
dscr_default = val;
- on_each_cpu(update_dscr, NULL, 1);
+ on_each_cpu(write_dscr, &val, 1);
return count;
}
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index ee061c3..2a324f4 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -78,12 +78,6 @@ _GLOBAL(tm_abort)
TABORT(R3)
blr
- .section ".toc","aw"
-DSCR_DEFAULT:
- .tc dscr_default[TC],dscr_default
-
- .section ".text"
-
/* void tm_reclaim(struct thread_struct *thread,
* unsigned long orig_msr,
* uint8_t cause)
@@ -298,9 +292,8 @@ dont_backup_fp:
mtlr r0
ld r2, STK_GOT(r1)
- /* Load system default DSCR */
- ld r4, DSCR_DEFAULT@toc(r2)
- ld r0, 0(r4)
+ /* Load CPU's default DSCR */
+ ld r0, PACA_DSCR(r13)
mtspr SPRN_DSCR, r0
blr
@@ -479,9 +472,8 @@ restore_gprs:
mtlr r0
ld r2, STK_GOT(r1)
- /* Load system default DSCR */
- ld r4, DSCR_DEFAULT@toc(r2)
- ld r0, 0(r4)
+ /* Load CPU's default DSCR */
+ ld r0, PACA_DSCR(r13)
mtspr SPRN_DSCR, r0
blr
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 9f0ad71..12f4ce5 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -286,8 +286,7 @@ kvm_start_guest:
beq kvm_no_guest
/* Set HSTATE_DSCR(r13) to something sensible */
- LOAD_REG_ADDR(r6, dscr_default)
- ld r6, 0(r6)
+ ld r6, PACA_DSCR(r13)
std r6, HSTATE_DSCR(r13)
bl kvmppc_hv_entry
--
1.7.10.4
^ permalink raw reply related
* [PATCH 0/3] powerpc: fix regression of per-CPU DSCR setting
From: Sam Bobroff @ 2014-05-21 6:32 UTC (permalink / raw)
To: benh; +Cc: aik, mikey, linuxppc-dev
Hello,
This patch corrects a regression on PowerPC CPUs that causes their
per-CPU DSCR SPR value (exposed via /sys/devices/system/cpuN/dscr) to
be quickly lost during context switching, effectively meaning that the
DSCR can no longer be set on a per-CPU basis.
My intent is to restore the functionality of the per-CPU value in a
way that is compatible with the newer global default and task-specific
DSCR setting system. Users of either the old or new systems should
now get pretty much what they expect.
A couple of notes:
I've split an existing "ifdef CONFIG_PPC_STD_MMU_64" block in
paca_struct into two parts because it allows dscr_default to be placed
into a cache line hole. (This seems be the case even without
CONFIG_PPC_STD_MMU_64 being defined.) Comments or ideas on alternative
placements are welcome.
PowerPC context switching is touched but there should not be any
performance cost; if anything it should get slightly faster due to the
per-CPU value being easier to access than the old global default.
Sam Bobroff (3):
powerpc: Split __SYSFS_SPRSETUP macro
powerpc: fix regression of per-CPU DSCR setting
powerpc: Document sysfs DSCR interface
Documentation/ABI/stable/sysfs-devices-system-cpu | 25 ++++++++++
arch/powerpc/include/asm/paca.h | 3 ++
arch/powerpc/kernel/asm-offsets.c | 1 +
arch/powerpc/kernel/entry_64.S | 9 +---
arch/powerpc/kernel/sysfs.c | 51 +++++++++++++--------
arch/powerpc/kernel/tm.S | 16 ++-----
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 3 +-
7 files changed, 67 insertions(+), 41 deletions(-)
create mode 100644 Documentation/ABI/stable/sysfs-devices-system-cpu
--
1.7.10.4
^ permalink raw reply
* [PATCH 1/3] powerpc: Split __SYSFS_SPRSETUP macro
From: Sam Bobroff @ 2014-05-21 6:32 UTC (permalink / raw)
To: benh; +Cc: aik, mikey, linuxppc-dev
In-Reply-To: <cover.1400652868.git.sam.bobroff@au1.ibm.com>
Split the __SYSFS_SPRSETUP macro into two parts so that registers requiring
custom read and write functions can use common code for their show and store
functions.
Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
---
arch/powerpc/kernel/sysfs.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index d90d4b7..e2a1d6f 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -404,7 +404,7 @@ void ppc_enable_pmcs(void)
}
EXPORT_SYMBOL(ppc_enable_pmcs);
-#define __SYSFS_SPRSETUP(NAME, ADDRESS, EXTRA) \
+#define __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, EXTRA) \
static void read_##NAME(void *val) \
{ \
*(unsigned long *)val = mfspr(ADDRESS); \
@@ -413,7 +413,9 @@ static void write_##NAME(void *val) \
{ \
EXTRA; \
mtspr(ADDRESS, *(unsigned long *)val); \
-} \
+}
+
+#define __SYSFS_SPRSETUP_SHOW_STORE(NAME) \
static ssize_t show_##NAME(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
@@ -436,10 +438,15 @@ static ssize_t __used \
return count; \
}
-#define SYSFS_PMCSETUP(NAME, ADDRESS) \
- __SYSFS_SPRSETUP(NAME, ADDRESS, ppc_enable_pmcs())
-#define SYSFS_SPRSETUP(NAME, ADDRESS) \
- __SYSFS_SPRSETUP(NAME, ADDRESS, )
+#define SYSFS_PMCSETUP(NAME, ADDRESS) \
+ __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ppc_enable_pmcs()) \
+ __SYSFS_SPRSETUP_SHOW_STORE(NAME)
+#define SYSFS_SPRSETUP(NAME, ADDRESS) \
+ __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ) \
+ __SYSFS_SPRSETUP_SHOW_STORE(NAME)
+
+#define SYSFS_SPRSETUP_SHOW_STORE(NAME) \
+ __SYSFS_SPRSETUP_SHOW_STORE(NAME)
/* Let's define all possible registers, we'll only hook up the ones
* that are implemented on the current processor
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH v4 8/8] DMA: Freescale: add suspend resume functions for DMA driver
From: Hongbo Zhang @ 2014-05-21 6:42 UTC (permalink / raw)
To: Vinod Koul
Cc: Shevchenko, Andriy, leo.li@freescale.com, vkoul@infradead.org,
linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
scottwood@freescale.com, Williams, Dan J,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20140521034513.GF21128@intel.com>
On 05/21/2014 11:45 AM, Vinod Koul wrote:
> On Thu, May 08, 2014 at 05:52:37PM +0800, Hongbo Zhang wrote:
>> On 05/07/2014 04:31 PM, Shevchenko, Andriy wrote:
>>> On Sun, 2014-05-04 at 18:22 +0800, Hongbo Zhang wrote:
>>>> On 05/03/2014 12:46 AM, Vinod Koul wrote:
>>>>> On Fri, Apr 18, 2014 at 04:17:51PM +0800, hongbo.zhang@freescale.com wrote:
>>>>>> From: Hongbo Zhang <hongbo.zhang@freescale.com>
>>>>>>
>>>>>> This patch adds suspend resume functions for Freescale DMA driver.
>>>>>> .prepare callback is used to stop further descriptors from being added into the
>>>>>> pending queue, and also issue pending queues into execution if there is any.
>>>>>> .suspend callback makes sure all the pending jobs are cleaned up and all the
>>>>>> channels are idle, and save the mode registers.
>>>>>> .resume callback re-initializes the channels by restore the mode registers.
>>>>>>
>>>>>> +
>>>>>> +static const struct dev_pm_ops fsldma_pm_ops = {
>>>>>> + .prepare = fsldma_prepare,
>>>>>> + .suspend = fsldma_suspend,
>>>>>> + .resume = fsldma_resume,
>>>>>> +};
>>>>> I think this is not correct. We discussed this sometime back on list. The
>>>>> DMAengine drivers should use late resume and early suspend to ensure they get
>>>>> suspended after clients (who should use normal ones) and resume before them
>>>>>
>>>> OK, will update it like this:
>>>> use .suspend to take place of current .prepare
>>> Could you remove this at all?
>>>
>>> Answering to your previous statements I could say that.
>>> Device drivers (DMAc users) that don't implement .suspend callback are
>>> on their own with troubles, you have not to care about them in the DMA
>>> driver.
>> Thanks for pointing out this issue.
>> Then how to handle the descriptors in the pending list if there is any?
>> a. let them finished.
>> but if the DMA user has already suspended prior DMA controller,
>> it is meaningless somehow and may even ask for trouble.
>> b. don't touch them.
>> after resume these pending descriptors could be executed, it is
>> also meaningless because the resumed DMA user may in different state
>> from before being suspended.
>> c. delete them.
>> should we do this? is is a bit crude?
>> d. return a non-success value
>> then the whole suspend process is reversed, e.g. suspend fails.
>> I've looked through some dma drivers, most of them is in case b.
> Yes and that makese sense.
>
> In calssic suspend case we maybe in middle so graceful behaviour would be to for
> client to PAUSE or terminate and then suspend followed by DMA suspend.
> You need to rely on client doing the right thing here
>
OK, will resend this 6/8, 7/8 and 8/8 for another iteration, and will
let the current 6/8 to be the last one for being reviewed and merged easier.
^ permalink raw reply
* Re: [PATCH 3/4] drivers/vfio: New IOCTL command VFIO_EEH_INFO
From: Benjamin Herrenschmidt @ 2014-05-21 7:24 UTC (permalink / raw)
To: Alexander Graf
Cc: aik@ozlabs.ru, Gavin Shan, kvm-ppc@vger.kernel.org,
alex.williamson@redhat.com, qiudayu@linux.vnet.ibm.com,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <17FB3514-B4F0-437F-826F-C473AD4F139E@suse.de>
On Wed, 2014-05-21 at 08:23 +0200, Alexander Graf wrote:
> > Note to Alex: This definitely kills the notifier idea for now
> though,
> > at least as a first class citizen of the design. We can add it as an
> > optional optimization on top later.
>
> I don't think it does. The notifier would just get triggered on config
> space read failures for example :). It's really just an aid for the
> vfio user to have a common code path for error handling.
I'll let Gavin make the final call on that one, if he thinks we can
reliably trigger it and there isn't too much code churn as a
consequence.
Cheers,
Ben.
^ permalink raw reply
* [PATCH v5 1/3] DMA: Freescale: use spin_lock_bh instead of spin_lock_irqsave
From: hongbo.zhang @ 2014-05-21 8:03 UTC (permalink / raw)
To: vkoul, dan.j.williams, dmaengine
Cc: scottwood, Hongbo Zhang, linuxppc-dev, linux-kernel, leo.li
In-Reply-To: <1400659383-6555-1-git-send-email-hongbo.zhang@freescale.com>
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.
Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
Signed-off-by: Qiang Liu <qiang.liu@freescale.com>
---
drivers/dma/fsldma.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index e0fec68..b291e6c 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -396,10 +396,9 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
struct fsldma_chan *chan = to_fsl_chan(tx->chan);
struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
struct fsl_desc_sw *child;
- unsigned long flags;
dma_cookie_t cookie = -EINVAL;
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
/*
* assign cookies to all of the software descriptors
@@ -412,7 +411,7 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
/* put this transaction onto the tail of the pending queue */
append_ld_queue(chan, desc);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
return cookie;
}
@@ -617,13 +616,12 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- unsigned long flags;
chan_dbg(chan, "free all channel resources\n");
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
dma_pool_destroy(chan->desc_pool);
chan->desc_pool = NULL;
@@ -842,7 +840,6 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
{
struct dma_slave_config *config;
struct fsldma_chan *chan;
- unsigned long flags;
int size;
if (!dchan)
@@ -852,7 +849,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
switch (cmd) {
case DMA_TERMINATE_ALL:
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
/* Halt the DMA engine */
dma_halt(chan);
@@ -862,7 +859,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
fsldma_free_desc_list(chan, &chan->ld_running);
chan->idle = true;
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
return 0;
case DMA_SLAVE_CONFIG:
@@ -904,11 +901,10 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- unsigned long flags;
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
fsl_chan_xfer_ld_queue(chan);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
}
/**
@@ -998,11 +994,10 @@ static void dma_do_tasklet(unsigned long data)
struct fsldma_chan *chan = (struct fsldma_chan *)data;
struct fsl_desc_sw *desc, *_desc;
LIST_HEAD(ld_cleanup);
- unsigned long flags;
chan_dbg(chan, "tasklet entry\n");
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
/* update the cookie if we have some descriptors to cleanup */
if (!list_empty(&chan->ld_running)) {
@@ -1031,7 +1026,7 @@ static void dma_do_tasklet(unsigned long data)
* ahead and free the descriptors below.
*/
fsl_chan_xfer_ld_queue(chan);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
/* Run the callback for each descriptor, in order */
list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH v5 2/3] DMA: Freescale: add suspend resume functions for DMA driver
From: hongbo.zhang @ 2014-05-21 8:03 UTC (permalink / raw)
To: vkoul, dan.j.williams, dmaengine
Cc: scottwood, Hongbo Zhang, linuxppc-dev, linux-kernel, leo.li
In-Reply-To: <1400659383-6555-1-git-send-email-hongbo.zhang@freescale.com>
From: Hongbo Zhang <hongbo.zhang@freescale.com>
This patch adds suspend and resume functions for Freescale DMA driver.
Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
---
drivers/dma/fsldma.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/dma/fsldma.h | 15 ++++++++++
2 files changed, 92 insertions(+)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index b291e6c..465f16d 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -400,6 +400,14 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
spin_lock_bh(&chan->desc_lock);
+#ifdef CONFIG_PM
+ if (unlikely(chan->pm_state != RUNNING)) {
+ chan_dbg(chan, "cannot submit due to suspend\n");
+ spin_unlock_bh(&chan->desc_lock);
+ return -1;
+ }
+#endif
+
/*
* assign cookies to all of the software descriptors
* that make up this transaction
@@ -1221,6 +1229,9 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
INIT_LIST_HEAD(&chan->ld_pending);
INIT_LIST_HEAD(&chan->ld_running);
chan->idle = true;
+#ifdef CONFIG_PM
+ chan->pm_state = RUNNING;
+#endif
chan->common.device = &fdev->common;
dma_cookie_init(&chan->common);
@@ -1360,6 +1371,69 @@ static int fsldma_of_remove(struct platform_device *op)
return 0;
}
+#ifdef CONFIG_PM
+static int fsldma_suspend_late(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fsldma_device *fdev = platform_get_drvdata(pdev);
+ struct fsldma_chan *chan;
+ int i;
+
+ for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ chan = fdev->chan[i];
+ if (!chan)
+ continue;
+
+ spin_lock_bh(&chan->desc_lock);
+ if (unlikely(!chan->idle))
+ goto out;
+ chan->regs_save.mr = get_mr(chan);
+ chan->pm_state = SUSPENDED;
+ spin_unlock_bh(&chan->desc_lock);
+ }
+ return 0;
+
+out:
+ for (; i >= 0; i--) {
+ chan = fdev->chan[i];
+ if (!chan)
+ continue;
+ chan->pm_state = RUNNING;
+ spin_unlock_bh(&chan->desc_lock);
+ }
+ return -EBUSY;
+}
+
+static int fsldma_resume_early(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fsldma_device *fdev = platform_get_drvdata(pdev);
+ struct fsldma_chan *chan;
+ u32 mode;
+ int i;
+
+ for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+ chan = fdev->chan[i];
+ if (!chan)
+ continue;
+
+ spin_lock_bh(&chan->desc_lock);
+ mode = chan->regs_save.mr
+ & ~FSL_DMA_MR_CS & ~FSL_DMA_MR_CC & ~FSL_DMA_MR_CA;
+ set_mr(chan, mode);
+ chan->pm_state = RUNNING;
+ spin_unlock_bh(&chan->desc_lock);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops fsldma_pm_ops = {
+ .suspend_late = fsldma_suspend_late,
+ .resume_early = fsldma_resume_early,
+};
+#endif
+
static const struct of_device_id fsldma_of_ids[] = {
{ .compatible = "fsl,elo3-dma", },
{ .compatible = "fsl,eloplus-dma", },
@@ -1372,6 +1446,9 @@ static struct platform_driver fsldma_of_driver = {
.name = "fsl-elo-dma",
.owner = THIS_MODULE,
.of_match_table = fsldma_of_ids,
+#ifdef CONFIG_PM
+ .pm = &fsldma_pm_ops,
+#endif
},
.probe = fsldma_of_probe,
.remove = fsldma_of_remove,
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index d56e835..f2e0c4d 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -134,6 +134,17 @@ struct fsldma_device {
#define FSL_DMA_CHAN_PAUSE_EXT 0x00001000
#define FSL_DMA_CHAN_START_EXT 0x00002000
+#ifdef CONFIG_PM
+struct fsldma_chan_regs_save {
+ u32 mr;
+};
+
+enum fsldma_pm_state {
+ RUNNING = 0,
+ SUSPENDED,
+};
+#endif
+
struct fsldma_chan {
char name[8]; /* Channel name */
struct fsldma_chan_regs __iomem *regs;
@@ -148,6 +159,10 @@ struct fsldma_chan {
struct tasklet_struct tasklet;
u32 feature;
bool idle; /* DMA controller is idle */
+#ifdef CONFIG_PM
+ struct fsldma_chan_regs_save regs_save;
+ enum fsldma_pm_state pm_state;
+#endif
void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v5 3/3] DMA: Freescale: change descriptor release process for supporting async_tx
From: hongbo.zhang @ 2014-05-21 8:03 UTC (permalink / raw)
To: vkoul, dan.j.williams, dmaengine
Cc: scottwood, Hongbo Zhang, linuxppc-dev, linux-kernel, leo.li
In-Reply-To: <1400659383-6555-1-git-send-email-hongbo.zhang@freescale.com>
From: Hongbo Zhang <hongbo.zhang@freescale.com>
Fix the potential risk when enable config NET_DMA and ASYNC_TX. Async_tx is
lack of support in current release process of dma descriptor, all descriptors
will be released whatever is acked or no-acked by async_tx, so there is a
potential race condition when dma engine is uesd by others clients (e.g. when
enable NET_DMA to offload TCP).
In our case, a race condition which is raised when use both of talitos and
dmaengine to offload xor is because napi scheduler will sync all pending
requests in dma channels, it affects the process of raid operations due to
ack_tx is not checked in fsl dma. The no-acked descriptor is freed which is
submitted just now, as a dependent tx, this freed descriptor trigger
BUG_ON(async_tx_test_ack(depend_tx)) in async_tx_submit().
TASK = ee1a94a0[1390] 'md0_raid5' THREAD: ecf40000 CPU: 0
GPR00: 00000001 ecf41ca0 ee44/921a94a0 0000003f 00000001 c00593e4 00000000 00000001
GPR08: 00000000 a7a7a7a7 00000001 045/920000002 42028042 100a38d4 ed576d98 00000000
GPR16: ed5a11b0 00000000 2b162000 00000200 046/920000000 2d555000 ed3015e8 c15a7aa0
GPR24: 00000000 c155fc40 00000000 ecb63220 ecf41d28 e47/92f640bb0 ef640c30 ecf41ca0
NIP [c02b048c] async_tx_submit+0x6c/0x2b4
LR [c02b068c] async_tx_submit+0x26c/0x2b4
Call Trace:
[ecf41ca0] [c02b068c] async_tx_submit+0x26c/0x2b448/92 (unreliable)
[ecf41cd0] [c02b0a4c] async_memcpy+0x240/0x25c
[ecf41d20] [c0421064] async_copy_data+0xa0/0x17c
[ecf41d70] [c0421cf4] __raid_run_ops+0x874/0xe10
[ecf41df0] [c0426ee4] handle_stripe+0x820/0x25e8
[ecf41e90] [c0429080] raid5d+0x3d4/0x5b4
[ecf41f40] [c04329b8] md_thread+0x138/0x16c
[ecf41f90] [c008277c] kthread+0x8c/0x90
[ecf41ff0] [c0011630] kernel_thread+0x4c/0x68
Another modification in this patch is the change of completed descriptors,
there is a potential risk which caused by exception interrupt, all descriptors
in ld_running list are seemed completed when an interrupt raised, it works fine
under normal condition, but if there is an exception occured, it cannot work as
our excepted. Hardware should not be depend on s/w list, the right way is to
read current descriptor address register to find the last completed descriptor.
If an interrupt is raised by an error, all descriptors in ld_running should not
be seemed finished, or these unfinished descriptors in ld_running will be
released wrongly.
A simple way to reproduce:
Enable dmatest first, then insert some bad descriptors which can trigger
Programming Error interrupts before the good descriptors. Last, the good
descriptors will be freed before they are processsed because of the exception
intrerrupt.
Note: the bad descriptors are only for simulating an exception interrupt. This
case can illustrate the potential risk in current fsl-dma very well.
Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
Signed-off-by: Qiang Liu <qiang.liu@freescale.com>
Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
---
drivers/dma/fsldma.c | 197 ++++++++++++++++++++++++++++++++++++--------------
drivers/dma/fsldma.h | 17 ++++-
2 files changed, 159 insertions(+), 55 deletions(-)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 465f16d..d5d6885 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -466,6 +466,88 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
}
/**
+ * fsldma_clean_completed_descriptor - free all descriptors which
+ * has been completed and acked
+ * @chan: Freescale DMA channel
+ *
+ * This function is used on all completed and acked descriptors.
+ * All descriptors should only be freed in this function.
+ */
+static void fsldma_clean_completed_descriptor(struct fsldma_chan *chan)
+{
+ struct fsl_desc_sw *desc, *_desc;
+
+ /* Run the callback for each descriptor, in order */
+ list_for_each_entry_safe(desc, _desc, &chan->ld_completed, node)
+ if (async_tx_test_ack(&desc->async_tx))
+ fsl_dma_free_descriptor(chan, desc);
+}
+
+/**
+ * fsldma_run_tx_complete_actions - cleanup a single link descriptor
+ * @chan: Freescale DMA channel
+ * @desc: descriptor to cleanup and free
+ * @cookie: Freescale DMA transaction identifier
+ *
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies.
+ */
+static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc, dma_cookie_t cookie)
+{
+ struct dma_async_tx_descriptor *txd = &desc->async_tx;
+ dma_cookie_t ret = cookie;
+
+ BUG_ON(txd->cookie < 0);
+
+ if (txd->cookie > 0) {
+ ret = txd->cookie;
+
+ /* Run the link descriptor callback function */
+ if (txd->callback) {
+ chan_dbg(chan, "LD %p callback\n", desc);
+ txd->callback(txd->callback_param);
+ }
+ }
+
+ /* Run any dependencies */
+ dma_run_dependencies(txd);
+
+ return ret;
+}
+
+/**
+ * fsldma_clean_running_descriptor - move the completed descriptor from
+ * ld_running to ld_completed
+ * @chan: Freescale DMA channel
+ * @desc: the descriptor which is completed
+ *
+ * Free the descriptor directly if acked by async_tx api, or move it to
+ * queue ld_completed.
+ */
+static void fsldma_clean_running_descriptor(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc)
+{
+ /* Remove from the list of transactions */
+ list_del(&desc->node);
+
+ /*
+ * the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+ if (!async_tx_test_ack(&desc->async_tx)) {
+ /*
+ * Move this descriptor to the list of descriptors which is
+ * completed, but still awaiting the 'ack' bit to be set.
+ */
+ list_add_tail(&desc->node, &chan->ld_completed);
+ return;
+ }
+
+ dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+}
+
+/**
* fsl_chan_xfer_ld_queue - transfer any pending transactions
* @chan : Freescale DMA channel
*
@@ -533,31 +615,58 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
}
/**
- * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
+ * fsldma_cleanup_descriptors - cleanup link descriptors which are completed
+ * and move them to ld_completed to free until flag 'ack' is set
* @chan: Freescale DMA channel
- * @desc: descriptor to cleanup and free
*
- * This function is used on a descriptor which has been executed by the DMA
- * controller. It will run any callbacks, submit any dependencies, and then
- * free the descriptor.
+ * This function is used on descriptors which have been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, then
+ * free these descriptors if flag 'ack' is set.
*/
-static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
- struct fsl_desc_sw *desc)
+static void fsldma_cleanup_descriptors(struct fsldma_chan *chan)
{
- struct dma_async_tx_descriptor *txd = &desc->async_tx;
+ struct fsl_desc_sw *desc, *_desc;
+ dma_cookie_t cookie = 0;
+ dma_addr_t curr_phys = get_cdar(chan);
+ int seen_current = 0;
- /* Run the link descriptor callback function */
- if (txd->callback) {
- chan_dbg(chan, "LD %p callback\n", desc);
- txd->callback(txd->callback_param);
+ fsldma_clean_completed_descriptor(chan);
+
+ /* Run the callback for each descriptor, in order */
+ list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+ /*
+ * do not advance past the current descriptor loaded into the
+ * hardware channel, subsequent descriptors are either in
+ * process or have not been submitted
+ */
+ if (seen_current)
+ break;
+
+ /*
+ * stop the search if we reach the current descriptor and the
+ * channel is busy
+ */
+ if (desc->async_tx.phys == curr_phys) {
+ seen_current = 1;
+ if (!dma_is_idle(chan))
+ break;
+ }
+
+ cookie = fsldma_run_tx_complete_actions(chan, desc, cookie);
+
+ fsldma_clean_running_descriptor(chan, desc);
}
- /* Run any dependencies */
- dma_run_dependencies(txd);
+ /*
+ * Start any pending transactions automatically
+ *
+ * In the ideal case, we keep the DMA controller busy while we go
+ * ahead and free the descriptors below.
+ */
+ fsl_chan_xfer_ld_queue(chan);
- dma_descriptor_unmap(txd);
- chan_dbg(chan, "LD %p free\n", desc);
- dma_pool_free(chan->desc_pool, desc, txd->phys);
+ if (cookie > 0)
+ chan->common.completed_cookie = cookie;
}
/**
@@ -627,8 +736,10 @@ static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
chan_dbg(chan, "free all channel resources\n");
spin_lock_bh(&chan->desc_lock);
+ fsldma_cleanup_descriptors(chan);
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
+ fsldma_free_desc_list(chan, &chan->ld_completed);
spin_unlock_bh(&chan->desc_lock);
dma_pool_destroy(chan->desc_pool);
@@ -865,6 +976,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
/* Remove and free all of the descriptors in the LD queue */
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
+ fsldma_free_desc_list(chan, &chan->ld_completed);
chan->idle = true;
spin_unlock_bh(&chan->desc_lock);
@@ -923,6 +1035,17 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
+ struct fsldma_chan *chan = to_fsl_chan(dchan);
+ enum dma_status ret;
+
+ ret = dma_cookie_status(dchan, cookie, txstate);
+ if (ret == DMA_COMPLETE)
+ return ret;
+
+ spin_lock_bh(&chan->desc_lock);
+ fsldma_cleanup_descriptors(chan);
+ spin_unlock_bh(&chan->desc_lock);
+
return dma_cookie_status(dchan, cookie, txstate);
}
@@ -1000,51 +1123,18 @@ 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;
- struct fsl_desc_sw *desc, *_desc;
- LIST_HEAD(ld_cleanup);
chan_dbg(chan, "tasklet entry\n");
spin_lock_bh(&chan->desc_lock);
- /* update the cookie if we have some descriptors to cleanup */
- if (!list_empty(&chan->ld_running)) {
- dma_cookie_t cookie;
-
- desc = to_fsl_desc(chan->ld_running.prev);
- cookie = desc->async_tx.cookie;
- dma_cookie_complete(&desc->async_tx);
-
- chan_dbg(chan, "completed_cookie=%d\n", cookie);
- }
-
- /*
- * move the descriptors to a temporary list so we can drop the lock
- * during the entire cleanup operation
- */
- list_splice_tail_init(&chan->ld_running, &ld_cleanup);
-
/* the hardware is now idle and ready for more */
chan->idle = true;
- /*
- * Start any pending transactions automatically
- *
- * In the ideal case, we keep the DMA controller busy while we go
- * ahead and free the descriptors below.
- */
- fsl_chan_xfer_ld_queue(chan);
- spin_unlock_bh(&chan->desc_lock);
-
- /* Run the callback for each descriptor, in order */
- list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
-
- /* Remove from the list of transactions */
- list_del(&desc->node);
+ /* Run all cleanup for descriptors which have been completed */
+ fsldma_cleanup_descriptors(chan);
- /* Run all cleanup for this descriptor */
- fsldma_cleanup_descriptor(chan, desc);
- }
+ spin_unlock_bh(&chan->desc_lock);
chan_dbg(chan, "tasklet exit\n");
}
@@ -1228,6 +1318,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
spin_lock_init(&chan->desc_lock);
INIT_LIST_HEAD(&chan->ld_pending);
INIT_LIST_HEAD(&chan->ld_running);
+ INIT_LIST_HEAD(&chan->ld_completed);
chan->idle = true;
#ifdef CONFIG_PM
chan->pm_state = RUNNING;
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index f2e0c4d..239c20c 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -149,8 +149,21 @@ struct fsldma_chan {
char name[8]; /* Channel name */
struct fsldma_chan_regs __iomem *regs;
spinlock_t desc_lock; /* Descriptor operation lock */
- struct list_head ld_pending; /* Link descriptors queue */
- struct list_head ld_running; /* Link descriptors queue */
+ /*
+ * Descriptors which are queued to run, but have not yet been
+ * submitted to the hardware for execution
+ */
+ struct list_head ld_pending;
+ /*
+ * Descriptors which are currently being executed by the hardware
+ */
+ struct list_head ld_running;
+ /*
+ * Descriptors which have finished execution by the hardware. These
+ * descriptors have already had their cleanup actions run. They are
+ * waiting for the ACK bit to be set by the async_tx API.
+ */
+ struct list_head ld_completed; /* Link descriptors queue */
struct dma_chan common; /* DMA common channel */
struct dma_pool *desc_pool; /* Descriptors pool */
struct device *dev; /* Channel device */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v5 0/3] DMA: Freescale: driver cleanups and enhancements
From: hongbo.zhang @ 2014-05-21 8:03 UTC (permalink / raw)
To: vkoul, dan.j.williams, dmaengine
Cc: scottwood, Hongbo Zhang, linuxppc-dev, linux-kernel, leo.li
From: Hongbo Zhang <hongbo.zhang@freescale.com>
Hi Dan,
Please have a look at this 3/3 as Vinod mentioned.
Hi Vinod Koul,
Please have a look at the v5 patch set.
v4 -> v5 changes:
- since previous 5 of 8 patches have been merged by Vinod, this iteration oly
inludes the last 3 patches of v4.
- patches order is changed for being reviewed and merged easier.
- remove the .prepare functions, and use the suspend_late and resume_early in
the suspend-and-resume patch.
v3 -> v4 changes:
- Fixed a typo in [2/8] commit message.
- There was a potential double call of list_del() when apply [4/8] only,
although this defect is removed again in later [6/8]. This version
eliminates this problem by updating [4/8] and [6/8] slightly.
- Updated [8/8] to use register access method introduced by [2/8]
v2 -> v3 change:
Only add "chan->pm_state = RUNNING" for patch[8/8].
v1 -> v2 change:
The only one change is introducing a new patch[1/7] to remove the unnecessary
macro FSL_DMA_LD_DEBUG, thus the total patches number is 8 now (was 7)
v1 notes:
Note that patch 2~6 had beed sent out for upstream before, but were together
with other storage patches at that time, that was not easy for being reviewed
and merged, so I send them separately this time.
Hongbo Zhang (3):
DMA: Freescale: use spin_lock_bh instead of spin_lock_irqsave
DMA: Freescale: add suspend resume functions for DMA driver
DMA: Freescale: change descriptor release process for supporting
async_tx
drivers/dma/fsldma.c | 297 ++++++++++++++++++++++++++++++++++++++------------
drivers/dma/fsldma.h | 32 +++++-
2 files changed, 260 insertions(+), 69 deletions(-)
--
1.7.9.5
^ permalink raw reply
* Re: [PATCH 3/4] drivers/vfio: New IOCTL command VFIO_EEH_INFO
From: Gavin Shan @ 2014-05-21 10:48 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: aik@ozlabs.ru, Alexander Graf, kvm-ppc@vger.kernel.org,
Gavin Shan, alex.williamson@redhat.com,
qiudayu@linux.vnet.ibm.com, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1400657062.18653.2.camel@pasglop>
On Wed, May 21, 2014 at 05:24:22PM +1000, Benjamin Herrenschmidt wrote:
>On Wed, 2014-05-21 at 08:23 +0200, Alexander Graf wrote:
>> > Note to Alex: This definitely kills the notifier idea for now
>> though,
>> > at least as a first class citizen of the design. We can add it as an
>> > optional optimization on top later.
>>
>> I don't think it does. The notifier would just get triggered on config
>> space read failures for example :). It's really just an aid for the
>> vfio user to have a common code path for error handling.
>
>I'll let Gavin make the final call on that one, if he thinks we can
>reliably trigger it and there isn't too much code churn as a
>consequence.
>
Lets postpone it as future improvement. It's not hard to send the
event (EEH errors) out, but I need think about how to extend the
existing guest's infrastructure to accept event. As Ben mentioned,
event-scan might be potential mechanism for that. We can discuss
for more later :-)
Thanks,
Gavin
^ permalink raw reply
* [PATCH 2/2] powerpc/corenet64_smp_defconfig: enable RTC support
From: Shengzhou Liu @ 2014-05-21 10:05 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: Shengzhou Liu
In-Reply-To: <1400666751-11459-1-git-send-email-Shengzhou.Liu@freescale.com>
Enable RTC support for DS1307, DS1374, DS3232, which is
needed on some corenet boards.
Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
---
arch/powerpc/configs/corenet64_smp_defconfig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 63508dd..e9c9f86 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -125,6 +125,11 @@ CONFIG_USB_EHCI_FSL=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS3232=y
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_DMADEVICES=y
--
1.8.0
^ permalink raw reply related
* [PATCH 1/2] mtd/spi: support en25s64 device
From: Shengzhou Liu @ 2014-05-21 10:05 UTC (permalink / raw)
To: linuxppc-dev, scottwood; +Cc: Shengzhou Liu
Add support for EON en25s64 spi device.
Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
---
drivers/mtd/devices/m25p80.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 7eda71d..6989311 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -745,6 +745,7 @@ static const struct spi_device_id m25p_ids[] = {
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, 0) },
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
/* ESMT */
--
1.8.0
^ permalink raw reply related
* Re: [PATCH v5 3/4] drivers/vfio: EEH support for VFIO PCI device
From: Alexander Graf @ 2014-05-21 13:07 UTC (permalink / raw)
To: Gavin Shan, kvm-ppc; +Cc: aik, alex.williamson, qiudayu, linuxppc-dev
In-Reply-To: <1400648623-9127-4-git-send-email-gwshan@linux.vnet.ibm.com>
On 21.05.14 07:03, Gavin Shan wrote:
> The patch adds new IOCTL command VFIO_EEH_OP to VFIO PCI device
> to support EEH functionality for PCI devices, which have been
> passed from host to guest via VFIO.
>
> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
> ---
> Documentation/vfio.txt | 6 +-
> arch/powerpc/include/asm/eeh.h | 10 ++
> arch/powerpc/kernel/eeh.c | 323 +++++++++++++++++++++++++++++++++++++++++
> drivers/vfio/pci/vfio_pci.c | 99 ++++++++++++-
> include/uapi/linux/vfio.h | 43 ++++++
> 5 files changed, 474 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt
> index b9ca023..bb17ec7 100644
> --- a/Documentation/vfio.txt
> +++ b/Documentation/vfio.txt
> @@ -305,7 +305,10 @@ faster, the map/unmap handling has been implemented in real mode which provides
> an excellent performance which has limitations such as inability to do
> locked pages accounting in real time.
>
> -So 3 additional ioctls have been added:
> +4) PPC64 guests detect PCI errors and recover from them via EEH RTAS services,
> +which works on the basis of additional ioctl command VFIO_EEH_OP.
> +
> +So 4 additional ioctls have been added:
>
> VFIO_IOMMU_SPAPR_TCE_GET_INFO - returns the size and the start
> of the DMA window on the PCI bus.
> @@ -316,6 +319,7 @@ So 3 additional ioctls have been added:
>
> VFIO_IOMMU_DISABLE - disables the container.
>
> + VFIO_EEH_OP - EEH dependent operations
Please document exactly what the ioctl does. In an ideal world, a VFIO
user will just look at the documentation and be able to write a program
against the API with it.
>
> The code flow from the example above should be slightly changed:
>
> diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
> index 34a2d83..93922ef 100644
> --- a/arch/powerpc/include/asm/eeh.h
> +++ b/arch/powerpc/include/asm/eeh.h
> @@ -305,6 +305,16 @@ void eeh_add_device_late(struct pci_dev *);
> void eeh_add_device_tree_late(struct pci_bus *);
> void eeh_add_sysfs_files(struct pci_bus *);
> void eeh_remove_device(struct pci_dev *);
> +#ifdef CONFIG_VFIO_PCI_EEH
> +int eeh_vfio_open(struct pci_dev *pdev);
> +void eeh_vfio_release(struct pci_dev *pdev);
> +int eeh_vfio_set_pe_option(struct pci_dev *pdev, int option, int *retval);
> +int eeh_vfio_get_pe_addr(struct pci_dev *pdev, int option,
> + int *retval, int *info);
> +int eeh_vfio_get_pe_state(struct pci_dev *pdev, int *retval, int *state);
> +int eeh_vfio_reset_pe(struct pci_dev *pdev, int option, int *retval);
> +int eeh_vfio_configure_pe(struct pci_dev *pdev, int *retval);
> +#endif
>
> /**
> * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
> diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
> index 9c6b899..2aaf90e 100644
> --- a/arch/powerpc/kernel/eeh.c
> +++ b/arch/powerpc/kernel/eeh.c
> @@ -1098,6 +1098,329 @@ void eeh_remove_device(struct pci_dev *dev)
> edev->mode &= ~EEH_DEV_SYSFS;
> }
>
> +#ifdef CONFIG_VFIO_PCI_EEH
> +int eeh_vfio_open(struct pci_dev *pdev)
Why vfio? Also that config option will not be set if vfio is compiled as
a module.
> +{
> + struct eeh_dev *edev;
> +
> + /* No PCI device ? */
> + if (!pdev)
> + return -ENODEV;
> +
> + /* No EEH device ? */
> + edev = pci_dev_to_eeh_dev(pdev);
> + if (!edev || !edev->pe)
> + return -ENODEV;
> +
> + eeh_dev_set_passed(edev, true);
> + eeh_pe_set_passed(edev->pe, true);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(eeh_vfio_open);
> +
> +void eeh_vfio_release(struct pci_dev *pdev)
> +{
> + bool release_pe = true;
> + struct eeh_pe *pe = NULL;
> + struct eeh_dev *tmp, *edev;
> +
> + /* No PCI device ? */
> + if (!pdev)
> + return;
> +
> + /* No EEH device ? */
> + edev = pci_dev_to_eeh_dev(pdev);
> + if (!edev || !eeh_dev_passed(edev) ||
> + !edev->pe || !eeh_pe_passed(pe))
> + return;
> +
> + /* Release device */
> + pe = edev->pe;
> + eeh_dev_set_passed(edev, false);
> +
> + /* Release PE */
> + eeh_pe_for_each_dev(pe, edev, tmp) {
> + if (eeh_dev_passed(edev)) {
> + release_pe = false;
> + break;
> + }
> + }
> +
> + if (release_pe)
> + eeh_pe_set_passed(pe, false);
> +}
> +EXPORT_SYMBOL(eeh_vfio_release);
> +
> +static int eeh_vfio_check_dev(struct pci_dev *pdev,
> + struct eeh_dev **pedev,
> + struct eeh_pe **ppe)
> +{
> + struct eeh_dev *edev;
> +
> + /* No device ? */
> + if (!pdev)
> + return -ENODEV;
> +
> + edev = pci_dev_to_eeh_dev(pdev);
> + if (!edev || !eeh_dev_passed(edev) ||
> + !edev->pe || !eeh_pe_passed(edev->pe))
> + return -ENODEV;
> +
> + if (pedev)
> + *pedev = edev;
> + if (ppe)
> + *ppe = edev->pe;
> +
> + return 0;
> +}
> +
> +int eeh_vfio_set_pe_option(struct pci_dev *pdev, int option, int *retval)
> +{
> + struct eeh_dev *edev;
> + struct eeh_pe *pe;
> + int ret = 0;
> +
> + /* Device existing ? */
> + ret = eeh_vfio_check_dev(pdev, &edev, &pe);
> + if (ret) {
> + pr_debug("%s: Cannot find device %s\n",
> + __func__, pdev ? pci_name(pdev) : "NULL");
> + *retval = -7;
What are these? Please use proper kernel internal return values for
errors. I don't want to see anything even remotely tied to RTAS in any
of these patches.
> + goto out;
> + }
> +
> + /* Invalid option ? */
> + if (option < EEH_OPT_DISABLE ||
> + option > EEH_OPT_THAW_DMA) {
This is quite confusing to read because it's not obvious what is in
between these. Just make this a switch() statement that lists the
allowed options. Gcc will be smart enough to optimize that into a bounds
check.
> + pr_debug("%s: Option %d out of range (%d, %d)\n",
> + __func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA);
> + *retval = -3;
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + if (option == EEH_OPT_DISABLE ||
> + option == EEH_OPT_ENABLE) {
> + *retval = 0;
> + } else {
> + if (!eeh_ops || !eeh_ops->set_option) {
> + *retval = -7;
> + ret = -ENOENT;
> + goto out;
> + }
> +
> + ret = eeh_ops->set_option(pe, option);
> + if (ret) {
> + pr_debug("%s: Failure %d from backend\n",
> + __func__, ret);
> + *retval = -1;
> + goto out;
> + }
> +
> + *retval = 0;
> + }
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(eeh_vfio_set_pe_option);
> +
> +int eeh_vfio_get_pe_addr(struct pci_dev *pdev, int option,
> + int *retval, int *info)
> +{
> + struct pci_bus *bus;
> + struct eeh_dev *edev;
> + struct eeh_pe *pe;
> + int ret = 0;
> +
> + /* Device existing ? */
> + ret = eeh_vfio_check_dev(pdev, &edev, &pe);
> + if (ret) {
> + *retval = -3;
> + goto out;
> + }
> +
> + /* Invalid option ? */
> + if (option != 0 && option != 1) {
0? 1? What? Don't these have names? And again, please use a switch() for
this function.
> + pr_debug("%s: option %d out of range (0, 1)\n",
> + __func__, option);
> + *retval = -3;
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + /*
> + * Fill result according to option. We don't differentiate
> + * PCI bus and device dependent PE here. So all PEs are
> + * built in "shared" mode. Also, the PE address has the format
> + * of "00BBSS00".
> + */
> + if (option == 0) {
> + bus = eeh_pe_bus_get(pe);
> + if (!bus) {
> + *retval = -3;
> + ret = -ENODEV;
> + goto out;
> + }
> +
> + *retval = 0;
> + *info = bus->number << 16;
How about positive numbers for the number and negative ones for errors?
> + } else {
> + *retval = 0;
> + *info = 1;
> + }
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(eeh_vfio_get_pe_addr);
> +
> +int eeh_vfio_get_pe_state(struct pci_dev *pdev, int *retval, int *state)
> +{
> + struct eeh_dev *edev;
> + struct eeh_pe *pe;
> + int result, ret = 0;
> +
> + /* Device existing ? */
> + ret = eeh_vfio_check_dev(pdev, &edev, &pe);
> + if (ret) {
> + *retval = -3;
> + goto out;
> + }
> +
> + if (!eeh_ops || !eeh_ops->get_state) {
> + pr_debug("%s: Unsupported request\n",
> + __func__);
> + ret = -ENOENT;
> + *retval = -3;
> + goto out;
> + }
> +
> + result = eeh_ops->get_state(pe, NULL);
> + if (!(result & EEH_STATE_RESET_ACTIVE) &&
> + (result & EEH_STATE_DMA_ENABLED) &&
> + (result & EEH_STATE_MMIO_ENABLED))
> + *state = 0;
> + else if (result & EEH_STATE_RESET_ACTIVE)
> + *state = 1;
> + else if (!(result & EEH_STATE_RESET_ACTIVE) &&
> + !(result & EEH_STATE_DMA_ENABLED) &&
> + !(result & EEH_STATE_MMIO_ENABLED))
> + *state = 2;
> + else if (!(result & EEH_STATE_RESET_ACTIVE) &&
> + (result & EEH_STATE_DMA_ENABLED) &&
> + !(result & EEH_STATE_MMIO_ENABLED))
> + *state = 4;
> + else
> + *state = 5;
What are these numbers?
> +
> + *retval = 0;
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(eeh_vfio_get_pe_state);
> +
> +int eeh_vfio_reset_pe(struct pci_dev *pdev, int option, int *retval)
> +{
> + struct eeh_dev *edev;
> + struct eeh_pe *pe;
> + int ret = 0;
> +
> + /* Device existing ? */
> + ret = eeh_vfio_check_dev(pdev, &edev, &pe);
> + if (ret) {
> + *retval = -3;
> + goto out;
> + }
> +
> + /* Invalid option ? */
> + if (option != EEH_RESET_DEACTIVATE &&
> + option != EEH_RESET_HOT &&
> + option != EEH_RESET_FUNDAMENTAL) {
> + pr_debug("%s: Unsupported option %d\n",
> + __func__, option);
> + ret = -EINVAL;
> + *retval = -3;
> + goto out;
> + }
> +
> + if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset) {
> + pr_debug("%s: Unsupported request\n",
> + __func__);
> + ret = -ENOENT;
> + *retval = -7;
> + goto out;
> + }
> +
> + ret = eeh_ops->reset(pe, option);
> + if (ret) {
> + pr_debug("%s: Failure %d from backend\n",
> + __func__, ret);
> + *retval = -1;
> + goto out;
> + }
> +
> + /*
> + * The PE is still in frozen state and we need clear that.
> + * It's good to clear frozen state after deassert to avoid
> + * messy IO access during reset, which might cause recrusive
recursive
> + * frozen PE.
> + */
> + if (option == EEH_RESET_DEACTIVATE) {
> + ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO);
> + if (ret) {
> + pr_debug("%s: Cannot enable IO for PHB#%d-PE#%d (%d)\n",
> + __func__, pe->phb->global_number, pe->addr, ret);
> + *retval = -1;
> + goto out;
> + }
> +
> + ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA);
> + if (ret) {
> + pr_debug("%s: Cannot enable DMA for PHB#%d-PE#%d (%d)\n",
> + __func__, pe->phb->global_number, pe->addr, ret);
> + *retval = -1;
> + goto out;
> + }
> +
> + eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
> + }
> +
> + *retval = 0;
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(eeh_vfio_reset_pe);
> +
> +int eeh_vfio_configure_pe(struct pci_dev *pdev, int *retval)
> +{
> + struct eeh_dev *edev;
> + struct eeh_pe *pe;
> + int ret = 0;
> +
> + /* Device existing ? */
> + ret = eeh_vfio_check_dev(pdev, &edev, &pe);
> + if (ret) {
> + *retval = -3;
> + goto out;
> + }
> +
> + /*
> + * The access to PCI config space on VFIO device has some
> + * limitations. Part of PCI config space, including BAR
> + * registers are not readable and writable. So the guest
> + * should have stale values for those registers and we have
> + * to restore them in host side.
I don't understand this comment. When is "configure_pe" called in the
first place? Please provide proper function descriptions for each of
these exported functions that tell someone who may want to use them what
they do.
Also, don't mention VFIO or guests in any function inside this file.
> + */
> + eeh_pe_restore_bars(pe);
> + *retval = 0;
> +
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(eeh_vfio_configure_pe);
> +
> +#endif /* CONFIG_VFIO_PCI_EEH */
> +
> static int proc_eeh_show(struct seq_file *m, void *v)
> {
> if (!eeh_enabled()) {
> diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
> index 7ba0424..05c3dde 100644
> --- a/drivers/vfio/pci/vfio_pci.c
> +++ b/drivers/vfio/pci/vfio_pci.c
> @@ -25,6 +25,9 @@
> #include <linux/types.h>
> #include <linux/uaccess.h>
> #include <linux/vfio.h>
> +#ifdef CONFIG_VFIO_PCI_EEH
> +#include <asm/eeh.h>
> +#endif
>
> #include "vfio_pci_private.h"
>
> @@ -152,32 +155,57 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev)
> pci_restore_state(pdev);
> }
>
> +static void vfio_eeh_pci_release(struct pci_dev *pdev)
> +{
> +#ifdef CONFIG_VFIO_PCI_EEH
> + eeh_vfio_release(pdev);
> +#endif
> +}
> +
> static void vfio_pci_release(void *device_data)
> {
> struct vfio_pci_device *vdev = device_data;
>
> - if (atomic_dec_and_test(&vdev->refcnt))
> + if (atomic_dec_and_test(&vdev->refcnt)) {
> + vfio_eeh_pci_release(vdev->pdev);
> vfio_pci_disable(vdev);
> + }
>
> module_put(THIS_MODULE);
> }
>
> +static int vfio_eeh_pci_open(struct pci_dev *pdev)
> +{
> + int ret = 0;
> +
> +#ifdef CONFIG_VFIO_PCI_EEH
> + ret = eeh_vfio_open(pdev);
> +#endif
> + return ret;
> +}
> +
> static int vfio_pci_open(void *device_data)
> {
> struct vfio_pci_device *vdev = device_data;
> + int ret;
>
> if (!try_module_get(THIS_MODULE))
> return -ENODEV;
>
> if (atomic_inc_return(&vdev->refcnt) == 1) {
> - int ret = vfio_pci_enable(vdev);
> - if (ret) {
> - module_put(THIS_MODULE);
> - return ret;
> - }
> + ret = vfio_pci_enable(vdev);
> + if (ret)
> + goto error;
> +
> + ret = vfio_eeh_pci_open(vdev->pdev);
> + if (ret)
> + goto error;
> }
>
> return 0;
> +error:
> + module_put(THIS_MODULE);
> + return ret;
> }
>
> static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
> @@ -321,6 +349,51 @@ static int vfio_pci_for_each_slot_or_bus(struct pci_dev *pdev,
> return walk.ret;
> }
>
> +static int vfio_eeh_pci_ioctl(struct pci_dev *pdev, struct vfio_eeh_op *info)
I still don't like the idea of that multiplexing ioctl. I don't see any
benefit in it whatsoever. Just create 5 individual ioctls with their own
simple interfaces.
Also, this interface has nothing to do with RTAS. So don't sneak in RTAS
error numbers anywhere ;). It's QEMU's task to convert from kernel error
codes to RTAS error codes.
Alex
> +{
> + int ret = 0;
> +
> +#ifdef CONFIG_VFIO_PCI_EEH
> + switch (info->op) {
> + case VFIO_EEH_OP_SET_OPTION:
> + ret = eeh_vfio_set_pe_option(pdev,
> + info->option.option,
> + &info->option.ret);
> + break;
> + case VFIO_EEH_OP_GET_ADDR:
> + ret = eeh_vfio_get_pe_addr(pdev,
> + info->addr.option,
> + &info->addr.ret,
> + &info->addr.info);
> + break;
> + case VFIO_EEH_OP_GET_STATE:
> + ret = eeh_vfio_get_pe_state(pdev,
> + &info->state.ret,
> + &info->state.reset_state);
> + info->state.cfg_cap = 1;
> + info->state.pe_unavail_info = 1000;
> + info->state.pe_recovery_info = 0;
> + break;
> + case VFIO_EEH_OP_PE_RESET:
> + ret = eeh_vfio_reset_pe(pdev,
> + info->reset.option,
> + &info->reset.ret);
> + break;
> + case VFIO_EEH_OP_PE_CONFIG:
> + ret = eeh_vfio_configure_pe(pdev,
> + &info->config.ret);
> + default:
> + ret = -EINVAL;
> + pr_debug("%s: Cannot handle op#%d\n",
> + __func__, info->op);
> + }
> +#else
> + ret = -ENOENT;
> +#endif
> +
> + return ret;
> +}
> +
> static long vfio_pci_ioctl(void *device_data,
> unsigned int cmd, unsigned long arg)
> {
> @@ -682,6 +755,20 @@ hot_reset_release:
>
> kfree(groups);
> return ret;
> + } else if (cmd == VFIO_EEH_OP) {
> + struct vfio_eeh_op info;
> + int ret = 0;
> +
> + minsz = sizeof(info);
> + if (copy_from_user(&info, (void __user *)arg, minsz))
> + return -EFAULT;
> + if (info.argsz < minsz)
> + return -EINVAL;
> +
> + ret = vfio_eeh_pci_ioctl(vdev->pdev, &info);
> + if (copy_to_user((void __user *)arg, &info, minsz))
> + ret = -EFAULT;
> + return ret;
> }
>
> return -ENOTTY;
> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> index cb9023d..518961d 100644
> --- a/include/uapi/linux/vfio.h
> +++ b/include/uapi/linux/vfio.h
> @@ -455,6 +455,49 @@ struct vfio_iommu_spapr_tce_info {
>
> #define VFIO_IOMMU_SPAPR_TCE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
>
> +/*
> + * The VFIO operation struct provides way to support EEH functionality
> + * for PCI device that is passed from host to guest via VFIO.
> + */
> +#define VFIO_EEH_OP_SET_OPTION 0
> +#define VFIO_EEH_OP_GET_ADDR 1
> +#define VFIO_EEH_OP_GET_STATE 2
> +#define VFIO_EEH_OP_PE_RESET 3
> +#define VFIO_EEH_OP_PE_CONFIG 4
> +
> +struct vfio_eeh_op {
> + __u32 argsz;
> + __u32 op;
> +
> + union {
> + struct vfio_eeh_set_option {
> + __u32 option;
> + __s32 ret;
> + } option;
> + struct vfio_eeh_pe_addr {
> + __u32 option;
> + __s32 ret;
> + __u32 info;
> + } addr;
> + struct vfio_eeh_pe_state {
> + __s32 ret;
> + __u32 reset_state;
> + __u32 cfg_cap;
> + __u32 pe_unavail_info;
> + __u32 pe_recovery_info;
> + } state;
> + struct vfio_eeh_reset {
> + __u32 option;
> + __s32 ret;
> + } reset;
> + struct vfio_eeh_config {
> + __s32 ret;
> + } config;
> + };
> +};
> +
> +#define VFIO_EEH_OP _IO(VFIO_TYPE, VFIO_BASE + 21)
> +
> /* ***************************************************************** */
>
> #endif /* _UAPIVFIO_H */
^ permalink raw reply
* Re: [PATCH v5 4/4] powerpc/eeh: Avoid event on passed PE
From: Alexander Graf @ 2014-05-21 13:13 UTC (permalink / raw)
To: Gavin Shan, kvm-ppc; +Cc: aik, alex.williamson, qiudayu, linuxppc-dev
In-Reply-To: <1400648623-9127-5-git-send-email-gwshan@linux.vnet.ibm.com>
On 21.05.14 07:03, Gavin Shan wrote:
> If we detects frozen state on PE that has been passed to guest, we
> needn't handle it. Instead, we rely on the guest to detect and recover
> it. The patch avoid EEH event on the frozen passed PE so that the guest
> can have chance to handle that.
>
> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/eeh.c | 8 ++++++++
> arch/powerpc/platforms/powernv/eeh-ioda.c | 3 ++-
> 2 files changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
> index 2aaf90e..25fd12d 100644
> --- a/arch/powerpc/kernel/eeh.c
> +++ b/arch/powerpc/kernel/eeh.c
> @@ -400,6 +400,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
> if (ret > 0)
> return ret;
>
> + /*
> + * If the PE has been passed to guest, we won't check the
> + * state. Instead, let the guest handle it if the PE has
What guest? The kernel doesn't care whether we use VFIO for a guest or not.
Alex
> + * been frozen.
> + */
> + if (eeh_pe_passed(pe))
> + return 0;
> +
> /* If we already have a pending isolation event for this
> * slot, we know it's bad already, we don't need to check.
> * Do this checking under a lock; as multiple PCI devices
> diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
> index 1b5982f..03a3ed2 100644
> --- a/arch/powerpc/platforms/powernv/eeh-ioda.c
> +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
> @@ -890,7 +890,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
> opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no,
> OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
> ret = EEH_NEXT_ERR_NONE;
> - } else if ((*pe)->state & EEH_PE_ISOLATED) {
> + } else if ((*pe)->state & EEH_PE_ISOLATED ||
> + eeh_pe_passed(*pe)) {
> ret = EEH_NEXT_ERR_NONE;
> } else {
> pr_err("EEH: Frozen PHB#%x-PE#%x (%s) detected\n",
^ permalink raw reply
* Re: [PATCH V4 0/2] mm: FAULT_AROUND_ORDER patchset performance data for powerpc
From: Kirill A. Shutemov @ 2014-05-21 13:40 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-arch, x86, riel, Madhavan Srinivasan, dave.hansen, peterz,
Rusty Russell, Hugh Dickins, linux-kernel, linux-mm, ak, paulus,
mgorman, linuxppc-dev, mingo, Kirill A. Shutemov
In-Reply-To: <20140520125956.aa61a3bfd84d4d6190740ce2@linux-foundation.org>
Andrew Morton wrote:
> On Tue, 20 May 2014 13:27:38 +0300 (EEST) "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> wrote:
>
> > Rusty Russell wrote:
> > > "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> writes:
> > > > Andrew Morton wrote:
> > > >> On Mon, 19 May 2014 16:23:07 -0700 (PDT) Hugh Dickins <hughd@google.com> wrote:
> > > >>
> > > >> > Shouldn't FAULT_AROUND_ORDER and fault_around_order be changed to be
> > > >> > the order of the fault-around size in bytes, and fault_around_pages()
> > > >> > use 1UL << (fault_around_order - PAGE_SHIFT)
> > > >>
> > > >> Yes. And shame on me for missing it (this time!) at review.
> > > >>
> > > >> There's still time to fix this. Patches, please.
> > > >
> > > > Here it is. Made at 3.30 AM, build tested only.
> > >
> > > Prefer on top of Maddy's patch which makes it always a variable, rather
> > > than CONFIG_DEBUG_FS. It's got enough hair as it is.
> >
> > Something like this?
>
> This appears to be against mainline, not against Madhavan's patch. As
> mentioned previously, I'd prefer it that way but confused.
>
>
> > From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
> > Date: Tue, 20 May 2014 13:02:03 +0300
> > Subject: [PATCH] mm: nominate faultaround area in bytes rather then page order
> >
> > There are evidences that faultaround feature is less relevant on
> > architectures with page size bigger then 4k. Which makes sense since
> > page fault overhead per byte of mapped area should be less there.
> >
> > Let's rework the feature to specify faultaround area in bytes instead of
> > page order. It's 64 kilobytes for now.
> >
> > The patch effectively disables faultaround on architectures with
> > page size >= 64k (like ppc64).
> >
> > It's possible that some other size of faultaround area is relevant for a
> > platform. We can expose `fault_around_bytes' variable to arch-specific
> > code once such platforms will be found.
> >
> > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> > ---
> > mm/memory.c | 62 +++++++++++++++++++++++--------------------------------------
> > 1 file changed, 23 insertions(+), 39 deletions(-)
> >
> > diff --git a/mm/memory.c b/mm/memory.c
> > index 037b812a9531..252b319e8cdf 100644
> > --- a/mm/memory.c
> > +++ b/mm/memory.c
> > @@ -3402,63 +3402,47 @@ void do_set_pte(struct vm_area_struct *vma, unsigned long address,
> > update_mmu_cache(vma, address, pte);
> > }
> >
> > -#define FAULT_AROUND_ORDER 4
> > +static unsigned long fault_around_bytes = 65536;
> > +
> > +static inline unsigned long fault_around_pages(void)
> > +{
> > + return rounddown_pow_of_two(fault_around_bytes) / PAGE_SIZE;
> > +}
>
> I think we should round up, not down. So if the user asks for 1kb,
> they get one page.
>
> So this becomes
>
> return PAGE_ALIGN(fault_around_bytes) / PAGE_SIZE;
See below.
> > +static inline unsigned long fault_around_mask(void)
> > +{
> > + return ~(rounddown_pow_of_two(fault_around_bytes) - 1) & PAGE_MASK;
> > +}
>
> And this has me a bit stumped. It's not helpful that do_fault_around()
> is undocumented. Does it fault in N/2 pages ahead and N/2 pages
> behind? Or does it align the address down to the highest multiple of
> fault_around_bytes? It appears to be the latter, so the location of
> the faultaround window around the fault address is basically random,
> depending on what address userspace happened to pick. I don't know why
> we did this :(
When we call ->map_pages() we need to make sure that we stay within VMA
and the page table. We don't want to cross page table boundary, because
page table is what ptlock covers in split ptlock case.
I've designed the feature with fault area nominated in page order in mind
and I found it's easier to make sure we don't cross boundaries, if we
would align virtual address of fault around area to PAGE_SIZE <<
FAULT_AROUND_ORDER.
And yes fault address may be anywhere within the area. You can think about
this as a virtual page with size PAGE_SIZE << FAULT_AROUND_ORDER: no matter
what is fault address, we handle area naturally aligned to page size which
fault address belong to.
I've used rounddown_pow_of_two() in the patch to align to nearest page
order, not to page size, because that's what current do_fault_around()
expect to see. And roundup is not an option: nobody expects fault around
area to be 128k if fault_around_bytes set to 64k + 1 bytes.
If you think we need this I can rework do_fault_around() to handle
non-pow-of-two fault_around_pages(), but I don't think it's good idea to
do this for v3.15. Anyway, patch I've proposed allows change
fault_around_bytes only from DEBUG_FS and roundown should be good
enough there.
> Or something. Can we please get some code commentary over
> do_fault_around() describing this design decision and explaining the
> reasoning behind it?
I'll do this. But if do_fault_around() rework is needed, I want to do that
first.
> Also, "neast" is not a word.
:facepalm:
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Date: Wed, 21 May 2014 16:36:42 +0300
Subject: [PATCH] mm: fix typo in comment in do_fault_around()
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
mm/memory.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/memory.c b/mm/memory.c
index 252b319e8cdf..f76663c31da6 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3460,7 +3460,7 @@ static void do_fault_around(struct vm_area_struct *vma, unsigned long address,
/*
* max_pgoff is either end of page table or end of vma
- * or fault_around_pages() from pgoff, depending what is neast.
+ * or fault_around_pages() from pgoff, depending what is nearest.
*/
max_pgoff = pgoff - ((start_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +
PTRS_PER_PTE - 1;
--
Kirill A. Shutemov
^ permalink raw reply related
* Re: Node 0 not necessary for powerpc?
From: Christoph Lameter @ 2014-05-21 14:16 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Tejun Heo, linux-mm, tony.luck, anton, David Rientjes,
linuxppc-dev
In-Reply-To: <20140519182400.GM8941@linux.vnet.ibm.com>
On Mon, 19 May 2014, Nishanth Aravamudan wrote:
> I'm seeing a panic at boot with this change on an LPAR which actually
> has no Node 0. Here's what I think is happening:
>
> start_kernel
> ...
> -> setup_per_cpu_areas
> -> pcpu_embed_first_chunk
> -> pcpu_fc_alloc
> -> ___alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu), ...
> -> smp_prepare_boot_cpu
> -> set_numa_node(boot_cpuid)
>
> So we panic on the NODE_DATA call. It seems that ia64, at least, uses
> pcpu_alloc_first_chunk rather than embed. x86 has some code to handle
> early calls of cpu_to_node (early_cpu_to_node) and sets the mapping for
> all CPUs in setup_per_cpu_areas().
Maybe we can switch ia64 too embed? Tejun: Why are there these
dependencies?
> Thoughts? Does that mean we need something similar to x86 for powerpc?
Tejun is the expert in this area. CCing him.
^ permalink raw reply
* Re: [PATCH] powerpc: fix typo 'CONFIG_PMAC'
From: Andreas Schwab @ 2014-05-21 16:08 UTC (permalink / raw)
To: Paul Bolle; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <1400617498.4912.66.camel@x220>
Paul Bolle <pebolle@tiscali.nl> writes:
> Commit b0d278b7d3ae ("powerpc/perf_event: Reduce latency of calling
> perf_event_do_pending") added a check for CONFIG_PMAC were a check for
> CONFIG_PPC_PMAC was clearly intended.
>
> Fixes: b0d278b7d3ae ("powerpc/perf_event: Reduce latency of calling perf_event_do_pending")
> Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
> ---
> Untested. Needs testing on 32 bit powermac, I guess.
>
> This typo was introduced in v2.6.36. No one noticed because very few
> people still use 32 bit powermacs?
How does that bug manifest itself?
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply
* Re: Node 0 not necessary for powerpc?
From: Tejun Heo @ 2014-05-21 18:58 UTC (permalink / raw)
To: Christoph Lameter
Cc: tony.luck, Nishanth Aravamudan, linux-mm, anton, David Rientjes,
linuxppc-dev
In-Reply-To: <alpine.DEB.2.10.1405210915170.7859@gentwo.org>
Hello,
On Wed, May 21, 2014 at 09:16:27AM -0500, Christoph Lameter wrote:
> On Mon, 19 May 2014, Nishanth Aravamudan wrote:
> > I'm seeing a panic at boot with this change on an LPAR which actually
> > has no Node 0. Here's what I think is happening:
> >
> > start_kernel
> > ...
> > -> setup_per_cpu_areas
> > -> pcpu_embed_first_chunk
> > -> pcpu_fc_alloc
> > -> ___alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu), ...
> > -> smp_prepare_boot_cpu
> > -> set_numa_node(boot_cpuid)
> >
> > So we panic on the NODE_DATA call. It seems that ia64, at least, uses
> > pcpu_alloc_first_chunk rather than embed. x86 has some code to handle
> > early calls of cpu_to_node (early_cpu_to_node) and sets the mapping for
> > all CPUs in setup_per_cpu_areas().
>
> Maybe we can switch ia64 too embed? Tejun: Why are there these
> dependencies?
>
> > Thoughts? Does that mean we need something similar to x86 for powerpc?
I'm missing context to properly understand what's going on but the
specific allocator in use shouldn't matter. e.g. x86 can use both
embed and page allocators. If the problem is that the arch is
accessing percpu memory before percpu allocator is initialized and the
problem was masked before somehow, the right thing to do would be
removing those premature percpu accesses. If early percpu variables
are really necessary, doing similar early_percpu thing as in x86 would
be necessary.
Thanks.
--
tejun
^ permalink raw reply
* Re: Node 0 not necessary for powerpc?
From: Nishanth Aravamudan @ 2014-05-21 19:57 UTC (permalink / raw)
To: Tejun Heo
Cc: tony.luck, linux-mm, anton, David Rientjes, Christoph Lameter,
linuxppc-dev
In-Reply-To: <20140521185812.GA5259@htj.dyndns.org>
Hi Tejun,
On 21.05.2014 [14:58:12 -0400], Tejun Heo wrote:
> Hello,
>
> On Wed, May 21, 2014 at 09:16:27AM -0500, Christoph Lameter wrote:
> > On Mon, 19 May 2014, Nishanth Aravamudan wrote:
> > > I'm seeing a panic at boot with this change on an LPAR which actually
> > > has no Node 0. Here's what I think is happening:
> > >
> > > start_kernel
> > > ...
> > > -> setup_per_cpu_areas
> > > -> pcpu_embed_first_chunk
> > > -> pcpu_fc_alloc
> > > -> ___alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu), ...
> > > -> smp_prepare_boot_cpu
> > > -> set_numa_node(boot_cpuid)
> > >
> > > So we panic on the NODE_DATA call. It seems that ia64, at least, uses
> > > pcpu_alloc_first_chunk rather than embed. x86 has some code to handle
> > > early calls of cpu_to_node (early_cpu_to_node) and sets the mapping for
> > > all CPUs in setup_per_cpu_areas().
> >
> > Maybe we can switch ia64 too embed? Tejun: Why are there these
> > dependencies?
> >
> > > Thoughts? Does that mean we need something similar to x86 for powerpc?
>
> I'm missing context to properly understand what's going on but the
> specific allocator in use shouldn't matter. e.g. x86 can use both
> embed and page allocators. If the problem is that the arch is
> accessing percpu memory before percpu allocator is initialized and the
> problem was masked before somehow, the right thing to do would be
> removing those premature percpu accesses. If early percpu variables
> are really necessary, doing similar early_percpu thing as in x86 would
> be necessary.
For context: I was looking at why N_ONLINE was statically setting Node 0
to be online, whether or not the topology is that way -- I've been
getting several bugs lately where Node 0 is online, but has no CPUs and
no memory on it, on powerpc.
On powerpc, setup_per_cpu_areas calls into ___alloc_bootmem_node using
NODE_DATA(cpu_to_node(cpu)).
Currently, cpu_to_node() in arch/powerpc/include/asm/topology.h does:
/*
* During early boot, the numa-cpu lookup table might not have been
* setup for all CPUs yet. In such cases, default to node 0.
*/
return (nid < 0) ? 0 : nid;
And so early at boot, if node 0 is not present, we end up accessing an
unitialized NODE_DATA(). So this seems buggy (I'll contact the powerpc
deveopers separately on that).
I recently submitted patches to have powerpc turn on
USE_PERCPU_NUMA_NODEID and HAVE_MEMORYLESS_NODES. But then, cpu_to_node
will be accessing percpu data in setup_per_cpu_areas, which seems like a
no-no. And more specifically, since we haven't yet run
smp_prepare_boot_cpu() at this point, cpu_to_node has not yet been
initialized to provide a sane value.
Thanks,
Nish
^ permalink raw reply
* NUMA topology question wrt. d4edc5b6
From: Nishanth Aravamudan @ 2014-05-21 20:04 UTC (permalink / raw)
To: srivatsa.bhat; +Cc: linuxppc-dev
Hi Srivatsa,
After d4edc5b6 ("powerpc: Fix the setup of CPU-to-Node mappings during
CPU online"), cpu_to_node() looks like:
static inline int cpu_to_node(int cpu)
{
int nid;
nid = numa_cpu_lookup_table[cpu];
/*
* During early boot, the numa-cpu lookup table might not have been
* setup for all CPUs yet. In such cases, default to node 0.
*/
return (nid < 0) ? 0 : nid;
}
However, I'm curious if this is correct in all cases. I have seen
several LPARs that do not have any CPUs on node 0. In fact, because node
0 is statically set online in the initialization of the N_ONLINE
nodemask, 0 is always present to Linux, whether it is present on the
system. I'm not sure what the best thing to do here is, but I'm curious
if you have any ideas? I would like to remove the static initialization
of node 0, as it's confusing to users to see an empty node (particularly
when it's completely separate in the numbering from other nodes), but
we trip a panic (refer to:
http://www.spinics.net/lists/linux-mm/msg73321.html).
Thanks,
Nish
^ permalink raw reply
* Re: [PATCH V4 0/2] mm: FAULT_AROUND_ORDER patchset performance data for powerpc
From: Andrew Morton @ 2014-05-21 20:34 UTC (permalink / raw)
To: Kirill A. Shutemov
Cc: linux-arch, x86, riel, Madhavan Srinivasan, dave.hansen, peterz,
Rusty Russell, Hugh Dickins, linux-kernel, linux-mm, ak, paulus,
mgorman, linuxppc-dev, mingo
In-Reply-To: <20140521134027.263DDE009B@blue.fi.intel.com>
On Wed, 21 May 2014 16:40:27 +0300 (EEST) "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> wrote:
> > Or something. Can we please get some code commentary over
> > do_fault_around() describing this design decision and explaining the
> > reasoning behind it?
>
> I'll do this. But if do_fault_around() rework is needed, I want to do that
> first.
This sort of thing should be at least partially driven by observation
and I don't have the data for that. My seat of the pants feel is that
after the first fault, accesses at higher addresses are more
common/probable than accesses at lower addresses. In which case we
should see improvements by centering the window at some higher address
than the fault. Much instrumentation and downstream analysis is needed
and the returns will be pretty small!
But we don't need to do all that right now. Let's get the current
implementation wrapped up for 3.15: get the interface finalized (bytes,
not pages!) and get the current design decisions appropriately
documented.
^ permalink raw reply
* Re: [PATCH 1/2] mtd/spi: support en25s64 device
From: Scott Wood @ 2014-05-21 20:50 UTC (permalink / raw)
To: Shengzhou Liu; +Cc: linuxppc-dev
In-Reply-To: <1400666751-11459-1-git-send-email-Shengzhou.Liu@freescale.com>
On Wed, 2014-05-21 at 18:05 +0800, Shengzhou Liu wrote:
> Add support for EON en25s64 spi device.
>
> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> ---
> drivers/mtd/devices/m25p80.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 7eda71d..6989311 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -745,6 +745,7 @@ static const struct spi_device_id m25p_ids[] = {
> { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
> { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
> { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
> + { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, 0) },
> { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
>
> /* ESMT */
This needs to be sent to the mtd and/or spi maintainers, not here.
What does this have to do with patch 2/2? Don't put unrelated things in
the same patchset, especially when they're destined for different
maintainers.
-Scott
^ 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