LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH V4] powerpc/prom: Export device tree physical address via proc
From: Grant Likely @ 2010-07-15  6:21 UTC (permalink / raw)
  To: Matthew McClintock; +Cc: Kumar Gala, linuxppc-dev, Timur Tabi
In-Reply-To: <1279120733-13584-1-git-send-email-msm@freescale.com>

On Wed, Jul 14, 2010 at 9:18 AM, Matthew McClintock <msm@freescale.com> wro=
te:
> To build a proper flat device tree for kexec we need to know which
> memreserve region was used for the device tree for the currently
> running kernel, so we can remove it and replace it with the new
> memreserve for the kexec'ed kernel
>
> Signed-off-by: Matthew McClintock <msm@freescale.com>

Hi Matthew.

I don't understand.  Why does userspace need to know about the old
memreserve sections?  Doesn't kexec tear down all of the old
allocations anyway?  How are they relevant for constructing the dtb
for the kexec kernel?  I'll need a lot more details before I consider
merging this.

Also, please cc: me and Ben Herrenschmidt on powerpc related device
tree changes.

Cheers,
g.

> ---
> V4: Fixed misspelling
>
> V3: Remove unneeded cast, and fixed indentation screw up
>
> V2: messed up changes
>
> =A0arch/powerpc/kernel/prom.c | =A0 45 ++++++++++++++++++++++++++++++++++=
++++++++++
> =A01 files changed, 45 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index fd9359a..ff3e240 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -32,6 +32,7 @@
> =A0#include <linux/debugfs.h>
> =A0#include <linux/irq.h>
> =A0#include <linux/lmb.h>
> +#include <linux/bootmem.h>
>
> =A0#include <asm/prom.h>
> =A0#include <asm/rtas.h>
> @@ -911,3 +912,47 @@ static int __init export_flat_device_tree(void)
> =A0}
> =A0__initcall(export_flat_device_tree);
> =A0#endif
> +
> +#ifdef CONFIG_KEXEC
> +static phys_addr_t flat_dt_start;
> +static phys_addr_t flat_dt_end;
> +
> +static struct property flat_dt_start_prop =3D {
> + =A0 =A0 =A0 .name =3D "linux,devicetree-start",
> + =A0 =A0 =A0 .length =3D sizeof(phys_addr_t),
> + =A0 =A0 =A0 .value =3D &flat_dt_start,
> +};
> +
> +static struct property flat_dt_end_prop =3D {
> + =A0 =A0 =A0 .name =3D "linux,devicetree-end",
> + =A0 =A0 =A0 .length =3D sizeof(phys_addr_t),
> + =A0 =A0 =A0 .value =3D &flat_dt_end,
> +};
> +
> +static int __init export_flat_device_tree_phys_addr(void)
> +{
> + =A0 =A0 =A0 struct property *prop;
> + =A0 =A0 =A0 struct device_node *node;
> +
> + =A0 =A0 =A0 node =3D of_find_node_by_path("/chosen");
> + =A0 =A0 =A0 if (!node)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOENT;
> +
> + =A0 =A0 =A0 prop =3D of_find_property(node, "linux,devicetree-start", N=
ULL);
> + =A0 =A0 =A0 if (prop)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 prom_remove_property(node, prop);
> +
> + =A0 =A0 =A0 prop =3D of_find_property(node, "linux,devicetree-end", NUL=
L);
> + =A0 =A0 =A0 if (prop)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 prom_remove_property(node, prop);
> +
> + =A0 =A0 =A0 flat_dt_start =3D virt_to_phys(initial_boot_params);
> + =A0 =A0 =A0 flat_dt_end =3D virt_to_phys(initial_boot_params)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 + initial_b=
oot_params->totalsize;
> + =A0 =A0 =A0 prom_add_property(node, &flat_dt_start_prop);
> + =A0 =A0 =A0 prom_add_property(node, &flat_dt_end_prop);
> +
> + =A0 =A0 =A0 return 0;
> +}
> +__initcall(export_flat_device_tree_phys_addr);
> +#endif
> --
> 1.6.6.1
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH 0/8] sdhci: Move real work out of an atomic context
From: Matt Fleming @ 2010-07-15  6:02 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Albert Herranz, linux-mmc, linux-kernel, linuxppc-dev, Ben Dooks,
	Andrew Morton, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

On Wed, 14 Jul 2010 17:07:28 +0400, Anton Vorontsov <avorontsov@mvista.com> wrote:
> Hi all,
> 
> Currently the sdhci driver does everything in the atomic context.
> And what is worse, PIO transfers are made from the IRQ handler.
> 
> This causes huge latencies (up to 120 ms). On some P2020 SOCs,
> DMA and card detection is broken, which means that kernel polls
> for the card via PIO transfers every second. Needless to say
> that this is quite bad.
> 
> So, this patch set reworks sdhci code to avoid atomic context,
> almost completely. We only do two device memory operations
> in the atomic context, and all the rest is threaded.
> 
> I noticed no throughput drop neither with PIO transfers nor
> with DMA (tested on MPC8569E CPU), while latencies should be
> greatly improved.

I haven't had time to read these patches in detail yet but they all seem
to be sensible changes. A very nice series!

^ permalink raw reply

* [PATCH] powerpc/mm: Handle hypervisor pte insert failure in __hash_page_huge
From: Anton Blanchard @ 2010-07-15  5:31 UTC (permalink / raw)
  To: benh, dwg; +Cc: linuxppc-dev


If the hypervisor gives us an error on a hugepage insert we panic. The
normal page code already handles this by returning an error instead and we end
calling low_hash_fault which will just kill the task if possible.

The patch below does a similar thing for the hugepage case.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: powerpc.git/arch/powerpc/mm/hugetlbpage-hash64.c
===================================================================
--- powerpc.git.orig/arch/powerpc/mm/hugetlbpage-hash64.c	2010-07-15 15:24:19.520742137 +1000
+++ powerpc.git/arch/powerpc/mm/hugetlbpage-hash64.c	2010-07-15 15:24:30.343243050 +1000
@@ -121,8 +121,15 @@ repeat:
                         }
 		}
 
-		if (unlikely(slot == -2))
-			panic("hash_huge_page: pte_insert failed\n");
+		/*
+		 * Hypervisor failure. Restore old pte and return -1
+		 * similar to __hash_page_*
+		 */
+		if (unlikely(slot == -2)) {
+			*ptep = __pte(old_pte);
+			err = -1;
+			goto out;
+		}
 
 		new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX);
 	}

^ permalink raw reply

* [PATCH 1/1] powerpc: Remove redundant xics badness warning
From: Brian King @ 2010-07-14 18:48 UTC (permalink / raw)
  To: benh; +Cc: brking, linuxppc-dev


While testing cpu offlining, we are regularly seeing the WARN_ON go off
in xics_ipi_dispatch. It can occur when an IPI gets sent to the CPU while
it is going offline. There is already a similar WARN_ON in the handlers
for PPC_MSG_CALL_FUNCTION and PPC_MSG_CALL_FUNC_SINGLE, so the warning
is not needed in that path. The debugger handler handles this case by
simply ignoring IPIs for offline CPUs, so no warning is needed there.
And the reschedule IPI, which is what is occurring in our test environment,
can be safely ignored, so we can simply remove the WARN_ON from xics_ipi_dispatch.

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 arch/powerpc/platforms/pseries/xics.c |    2 --
 1 file changed, 2 deletions(-)

diff -puN arch/powerpc/platforms/pseries/xics.c~powerpc_xics_fix_badness arch/powerpc/platforms/pseries/xics.c
--- linux-2.6/arch/powerpc/platforms/pseries/xics.c~powerpc_xics_fix_badness	2010-07-14 13:47:13.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/platforms/pseries/xics.c	2010-07-14 13:47:13.000000000 -0500
@@ -549,8 +549,6 @@ static irqreturn_t xics_ipi_dispatch(int
 {
 	unsigned long *tgt = &per_cpu(xics_ipi_message, cpu);
 
-	WARN_ON(cpu_is_offline(cpu));
-
 	mb();	/* order mmio clearing qirr */
 	while (*tgt) {
 		if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, tgt)) {
_

^ permalink raw reply

* Re: [PATCH 4/7] Allow sysfs memory directories to be split
From: Nathan Fontenot @ 2010-07-14 17:16 UTC (permalink / raw)
  To: Dave Hansen; +Cc: linuxppc-dev, linux-kernel, KAMEZAWA Hiroyuki
In-Reply-To: <1279078016.10995.58.camel@nimitz>

On 07/13/2010 10:26 PM, Dave Hansen wrote:
> On Wed, 2010-07-14 at 09:35 +0900, KAMEZAWA Hiroyuki wrote:
>>   2. I'd like to write a configfs module for handling memory hotplug even when
>>      sysfs directroy is not created.
>>      Because configfs support rmdir/mkdir, the user (ppc's daemon?) has to do
>>      
>>      When offlining section X.
>>      # insmod configfs_memory.ko
>>      # mount -t configfs none /configfs
>>      # mkdir /configfs/memoryX
>>      # echo offline > /configfs/memoryX/state
>>      # rmdir /configfs/memoryX
>>
>>   And making this operation as the default bahavior for all arch's memory hotplug may
>>   be better...
>>
>> Dave, how do you think ? Because ppc guys uses "probe" interface already,
>> this can be handled... no ?
> 
> I think creating a interface to duplicate the existing sysfs one is a
> bad idea.  I also think removing the existing sysfs one isn't feasible
> since there are users, and it's truly part of the ABI.  So, I'm not
> really a fan on the configfs interface. :(
> 
> I really do think the sysfs interface is fixable.  We should at least
> give it a good shot before largely duplicating its functionality.

I agree with Dave, I don't think another memory hotplug interface is needed.

I am working to update the patchset to remove the split functionality and
fix other items commented on.  this new patch will just split the memory_block
structure so that a memory_block can span multiple memory sections.

Kame, I understand that offlining 16 MB is easier than 256 MB.  From the ppc
perspective though, we are still offlining 256 MB.  We do memory add/remove
on LMB size chunks, so we have to add/remove all of the memory sections contained
in an LMB.  If any one memory section covered by a LMB fails to add/remove, we
restore the memory sections to their orignal state an fail the add/remove operation.
NOTE: the code doing this is not in the kernel, but in the user-space drmgr
command (from powerpc-utils package).

-Nathan 

^ permalink raw reply

* Re: [RFC PATCH] Kconfig: Enable Kconfig fragments to be used for defconfig
From: Daniel Walker @ 2010-07-14 16:22 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: linux-kbuild, Tony Lindgren, linux-kernel, Linus Torvalds,
	Russell King, Uwe Kleine-König, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1007131941140.10598@xanadu.home>

On Tue, 2010-07-13 at 20:07 -0400, Nicolas Pitre wrote:

> That's one issue indeed.
> 
> But there is another issue that is somewhat related, which is to be able 
> to categorize config options.
> 
> Currently the defconfig files carry information about the proper driver 
> to enable in order to support devices soldered on the board and 
> therefore which are not "optional".  That might be a particular RTC 
> chip, or a particular ethernet block integrated into a SOC, etc.  Of 
> course we want to preserve the ability to disable support for those 
> things, but by default people want to have all the right drivers 
> selected for all the built-in hardware when selecting a target 
> machine/board without having to dig into a datasheet for that target.
> 
> The defconfig files also carry config options that are totally 
> arbitrary.  What type of filesystem, what kind of network protocol, what 
> USB device drivers (not host controller driver), what amount of 
> debugging options, all those are unrelated to the actual hardware and 
> may vary from one user to another.

Right.

> Furthermore, in order to reduce the number of defconfig files, we tried 
> to combine as many targets into a single kernel image.  That increases 
> build test coverage with fewer builds which is good, but then the info 
> about specific drivers required for a specific target but not for 
> another target in the same defconfig is now lost.  It is therefore quite 
> hard to produce a highly optimized configuration for a single target 
> without doing some digging again.
> 
> So it is really in the Kconfig file that all those hardware specific 
> options can be expressed in a clear and readable way.  When BOARD_XYZ is 
> selected and STD_CONFIG is selected, then automatically select RTC_FOO, 
> select ETH_BAR, select LED_BAZ, etc. Of course we would want required 
> dependencies to be automatically selected as well.

I see..

> But all the rest is arbitrary and could be part of common shared 
> profiles or the like in defconfig format.

I'm sure most people will want to have a config isolated to their
specific device. That to me seems reasonable because everyone wants the
smallest possible kernel they can get for their given device.

Then there would be a smaller group who wants to create multi-device
images. I don't see this being the average users tho, or kernel hackers.

To me there is little difference between doing,

CONFIG_ARCH_MSM=y

or

select ARCH_MSM

they are basically doing the same thing. So doing anything in Kconfig is
a lateral move .. Converting over to Kconfig in this case doesn't makes
sense to me.

Could we do something more like adding an "#include" option into the
defconfigs .. Then you could create defconfigs that hold multiple
devices without a massive rework to what we currently have. 

Daniel


-- 
Sent by an consultant of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* Re: [PATCH] kbuild: Enable building defconfigs from Kconfig files
From: Linus Torvalds @ 2010-07-14 15:37 UTC (permalink / raw)
  To: Grant Likely
  Cc: Michal Marek, Stephen Rothwell, Catalin Marinas, LKML,
	Russell King, Andrew Morton, ppc-dev, linux-arm-kernel
In-Reply-To: <AANLkTimYDDviG2no6RVPZZj8rD2d2URMAPUCWuftiFiB@mail.gmail.com>

On Tue, Jul 13, 2010 at 10:47 PM, Grant Likely
<grant.likely@secretlab.ca> wrote:
>
> Okay, well I advocate for the -D /dev/null approach then. =A0I think
> that validating our defaults, and looking for the subtle interactions
> are exactly what we want to be doing when it comes to defconfigs. =A0The
> fact that a defconfig does *not* want the default value is exactly
> what the defconfigs should be capturing.

Sure. That does have the downside that it absolutely _requires_
changes to the Kconfig language. Because currently "select" can only
set a config variable, it cannot clear it or downgrade it from the
defaults - so if you start from anything but a noconfig, you can't
unset anything.

But that's not a big downside, since honestly either approach will
want it anyway (even -n wants it for setting integer or string options
- never mind the whole issue of making it easier/cleaner to write the
files in the first place).

>> =A0 =A0 =A0 =A0 =A0set NODES_SHIFT 10
>
> I'm partial to extending select statements myself because it fits
> nicely into the existing grammer; but I can see value in having a set
> statement too.

If it turns out easier to just implement the "set value" as a "select
with a value", that's fine by me too. If the syntax for setting a
particular value ends up being

   select NODES_SHIFT 10

that still works (with or without a "=3D" there). It looks a bit odd to
me, but that's probably just because it's new. It doesn't look _wrong_
by any stretch.

>=A0It would eliminate the temporary config options that
> both my and Stephen's patch would add.

I don't think there is anything wrong with having the extra config
option just to drive the "select" syntax. In fact, in many cases I
think it would be "documentation", because I think the extra config
option should generally be named by the platform that you're actually
selecting for - even if that name may not be used for anything else.

So having the basic syntax for a Kconfig.xyz file be something like

         config SIDEWINDER_PLATFORM
              def_bool y
              select ...

where that initial config/def_bool is strictly not needed for the
actual end result, but is used to get to the select statements, and to
include that "SIDEWINDER_PLATFORM=3Dy" in the resulting .config as a
kind of top-level comment all looks fine.

                 Linus

^ permalink raw reply

* Re: [PATCH V4] powerpc/prom: Export device tree physical address via proc
From: Segher Boessenkool @ 2010-07-14 15:46 UTC (permalink / raw)
  To: Matthew McClintock; +Cc: Kumar Gala, linuxppc-dev, Timur Tabi
In-Reply-To: <1279122163.13098.2.camel@localhost>

>> Any particular reason you fixed only one of the two
>> mispelings I pointed out?  (device tree is two words,
>> not one).
>
> Ahh, my fault.

Well I wasn't terribly clear ;-)

>> You could use one property instead of two; use addr+len
>> like every other property does.
>>
>> You also should use a better name for the property; is this
>> the previous kernel's device tree?  Just "device-tree" makes
>> no sense, it is not pointing to "the" device tree for sure!
>
> What about just one node called "flat-device-tree"?

But *what* flat device tree?  It cannot be "the" flat device tree,
or it would be useless information, since we are already reading it!


Segher

^ permalink raw reply

* Re: [PATCH V4] powerpc/prom: Export device tree physical address via proc
From: Matthew McClintock @ 2010-07-14 15:42 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Kumar Gala, linuxppc-dev, Timur Tabi
In-Reply-To: <C26140FB-4F77-4D8E-B6C4-63BC9C9EDD83@kernel.crashing.org>

On Wed, 2010-07-14 at 17:35 +0200, Segher Boessenkool wrote:
> > V4: Fixed misspelling
> 
> Any particular reason you fixed only one of the two
> mispelings I pointed out?  (device tree is two words,
> not one).

Ahh, my fault.

> 
> > +	prop = of_find_property(node, "linux,devicetree-start", NULL);
> > +	if (prop)
> > +		prom_remove_property(node, prop);
> > +
> > +	prop = of_find_property(node, "linux,devicetree-end", NULL);
> > +	if (prop)
> > +		prom_remove_property(node, prop);
> > +
> > +	flat_dt_start = virt_to_phys(initial_boot_params);
> > +	flat_dt_end = virt_to_phys(initial_boot_params)
> > +				+ initial_boot_params->totalsize;
> > +	prom_add_property(node, &flat_dt_start_prop);
> > +	prom_add_property(node, &flat_dt_end_prop);
> 
> You could use one property instead of two; use addr+len
> like every other property does.
> 
> You also should use a better name for the property; is this
> the previous kernel's device tree?  Just "device-tree" makes
> no sense, it is not pointing to "the" device tree for sure!
> 

What about just one node called "flat-device-tree"?

-Matthew

^ permalink raw reply

* Re: [PATCH V4] powerpc/prom: Export device tree physical address via proc
From: Segher Boessenkool @ 2010-07-14 15:35 UTC (permalink / raw)
  To: Matthew McClintock; +Cc: Kumar Gala, linuxppc-dev, Timur Tabi
In-Reply-To: <1279120733-13584-1-git-send-email-msm@freescale.com>

> V4: Fixed misspelling

Any particular reason you fixed only one of the two
mispelings I pointed out?  (device tree is two words,
not one).

> +	prop = of_find_property(node, "linux,devicetree-start", NULL);
> +	if (prop)
> +		prom_remove_property(node, prop);
> +
> +	prop = of_find_property(node, "linux,devicetree-end", NULL);
> +	if (prop)
> +		prom_remove_property(node, prop);
> +
> +	flat_dt_start = virt_to_phys(initial_boot_params);
> +	flat_dt_end = virt_to_phys(initial_boot_params)
> +				+ initial_boot_params->totalsize;
> +	prom_add_property(node, &flat_dt_start_prop);
> +	prom_add_property(node, &flat_dt_end_prop);

You could use one property instead of two; use addr+len
like every other property does.

You also should use a better name for the property; is this
the previous kernel's device tree?  Just "device-tree" makes
no sense, it is not pointing to "the" device tree for sure!


Segher

^ permalink raw reply

* Re: [PATCH V4] powerpc/prom: Export device tree physical address via proc
From: Tabi Timur-B04825 @ 2010-07-14 15:33 UTC (permalink / raw)
  To: McClintock Matthew-B29882; +Cc: Gala Kumar-B11780, linuxppc-dev
In-Reply-To: <1279120733-13584-1-git-send-email-msm@freescale.com>

[-- Attachment #1: Type: text/plain, Size: 1276 bytes --]

Matthew McClintock wrote:

> +static struct property flat_dt_start_prop = {
> +	.name = "linux,devicetree-start",
> +	.length = sizeof(phys_addr_t),
> +	.value =&flat_dt_start,
> +};
> +
> +static struct property flat_dt_end_prop = {
> +	.name = "linux,devicetree-end",
> +	.length = sizeof(phys_addr_t),
> +	.value =&flat_dt_end,
> +};

I think Segher was suggesting that you use "linux,device-tree-xxx".

> +
> +static int __init export_flat_device_tree_phys_addr(void)
> +{
> +	struct property *prop;
> +	struct device_node *node;
> +
> +	node = of_find_node_by_path("/chosen");
> +	if (!node)
> +		return -ENOENT;
> +
> +	prop = of_find_property(node, "linux,devicetree-start", NULL);

Does this work?

prop = of_find_property(node, flat_dt_start_prop.name, NULL);

> +	if (prop)
> +		prom_remove_property(node, prop);
> +
> +	prop = of_find_property(node, "linux,devicetree-end", NULL);
> +	if (prop)
> +		prom_remove_property(node, prop);
> +
> +	flat_dt_start = virt_to_phys(initial_boot_params);
> +	flat_dt_end = virt_to_phys(initial_boot_params)
> +				+ initial_boot_params->totalsize;

This is better, I think:

	flat_dt_end = flat_dt_start + initial_boot_params->totalsize;

-- 
Timur Tabi
Linux kernel developer

[-- Attachment #2: Type: text/html, Size: 2835 bytes --]

^ permalink raw reply

* [PATCH V4] powerpc/prom: Export device tree physical address via proc
From: Matthew McClintock @ 2010-07-14 15:18 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Matthew McClintock, Kumar Gala, Timur Tabi

To build a proper flat device tree for kexec we need to know which
memreserve region was used for the device tree for the currently
running kernel, so we can remove it and replace it with the new
memreserve for the kexec'ed kernel

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
V4: Fixed misspelling

V3: Remove unneeded cast, and fixed indentation screw up

V2: messed up changes

 arch/powerpc/kernel/prom.c |   45 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index fd9359a..ff3e240 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -32,6 +32,7 @@
 #include <linux/debugfs.h>
 #include <linux/irq.h>
 #include <linux/lmb.h>
+#include <linux/bootmem.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -911,3 +912,47 @@ static int __init export_flat_device_tree(void)
 }
 __initcall(export_flat_device_tree);
 #endif
+
+#ifdef CONFIG_KEXEC
+static phys_addr_t flat_dt_start;
+static phys_addr_t flat_dt_end;
+
+static struct property flat_dt_start_prop = {
+	.name = "linux,devicetree-start",
+	.length = sizeof(phys_addr_t),
+	.value = &flat_dt_start,
+};
+
+static struct property flat_dt_end_prop = {
+	.name = "linux,devicetree-end",
+	.length = sizeof(phys_addr_t),
+	.value = &flat_dt_end,
+};
+
+static int __init export_flat_device_tree_phys_addr(void)
+{
+	struct property *prop;
+	struct device_node *node;
+
+	node = of_find_node_by_path("/chosen");
+	if (!node)
+		return -ENOENT;
+
+	prop = of_find_property(node, "linux,devicetree-start", NULL);
+	if (prop)
+		prom_remove_property(node, prop);
+
+	prop = of_find_property(node, "linux,devicetree-end", NULL);
+	if (prop)
+		prom_remove_property(node, prop);
+
+	flat_dt_start = virt_to_phys(initial_boot_params);
+	flat_dt_end = virt_to_phys(initial_boot_params)
+				+ initial_boot_params->totalsize;
+	prom_add_property(node, &flat_dt_start_prop);
+	prom_add_property(node, &flat_dt_end_prop);
+
+	return 0;
+}
+__initcall(export_flat_device_tree_phys_addr);
+#endif
-- 
1.6.6.1

^ permalink raw reply related

* [PATCH 5/5] Remove REDWOOD_5 and REDWOOD_6 config options and conditional code
From: Christian Dietrich @ 2010-07-14 14:05 UTC (permalink / raw)
  To: Josh Boyer, Matt Porter, Benjamin Herrenschmidt, Paul Mackerras,
	Solomon Peachy, David Woodhouse, Mike Frysinger, Jiri Kosina,
	Artem Bityutskiy, Alexander Kurz, David S. Miller, Randy Dunlap,
	John Linn, Florian Fainelli, linuxppc-dev, linux-kernel,
	linux-mtd, netdev
  Cc: vamos-dev
In-Reply-To: <c3c850bed3f5714f1efcfad24ad4f8bfcb6b5b54.1279116162.git.qy03fugy@stud.informatik.uni-erlangen.de>

The config options for REDWOOD_[56] were commented out in the powerpc
Kconfig. The ifdefs referencing this options therefore are dead and all
references to this can be removed (Also dependencies in other KConfig
files).

Signed-off-by: Christian Dietrich <qy03fugy@stud.informatik.uni-erlangen.de>
---
 arch/powerpc/platforms/40x/Kconfig |   16 -------------
 drivers/mtd/maps/Kconfig           |    2 +-
 drivers/mtd/maps/redwood.c         |   43 ------------------------------------
 drivers/net/Kconfig                |    2 +-
 4 files changed, 2 insertions(+), 61 deletions(-)

diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index ec64264..b721764 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -71,22 +71,6 @@ config MAKALU
 	help
 	  This option enables support for the AMCC PPC405EX board.
 
-#config REDWOOD_5
-#	bool "Redwood-5"
-#	depends on 40x
-#	default n
-#	select STB03xxx
-#	help
-#	  This option enables support for the IBM STB04 evaluation board.
-
-#config REDWOOD_6
-#	bool "Redwood-6"
-#	depends on 40x
-#	default n
-#	select STB03xxx
-#	help
-#	  This option enables support for the IBM STBx25xx evaluation board.
-
 #config SYCAMORE
 #	bool "Sycamore"
 #	depends on 40x
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index f22bc9f..b5ebb72 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -321,7 +321,7 @@ config MTD_CFI_FLAGADM
 
 config MTD_REDWOOD
 	tristate "CFI Flash devices mapped on IBM Redwood"
-	depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
+	depends on MTD_CFI && REDWOOD_4
 	help
 	  This enables access routines for the flash chips on the IBM
 	  Redwood board. If you have one of these boards and would like to
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c
index 933c0b6..d2c9db0 100644
--- a/drivers/mtd/maps/redwood.c
+++ b/drivers/mtd/maps/redwood.c
@@ -22,8 +22,6 @@
 
 #include <asm/io.h>
 
-#if !defined (CONFIG_REDWOOD_6)
-
 #define WINDOW_ADDR 0xffc00000
 #define WINDOW_SIZE 0x00400000
 
@@ -69,47 +67,6 @@ static struct mtd_partition redwood_flash_partitions[] = {
 	}
 };
 
-#else /* CONFIG_REDWOOD_6 */
-/* FIXME: the window is bigger - armin */
-#define WINDOW_ADDR 0xff800000
-#define WINDOW_SIZE 0x00800000
-
-#define RW_PART0_OF	0
-#define RW_PART0_SZ	0x400000	/* 4 MiB data */
-#define RW_PART1_OF	RW_PART0_OF + RW_PART0_SZ
-#define RW_PART1_SZ	0x10000		/* 64K VPD */
-#define RW_PART2_OF	RW_PART1_OF + RW_PART1_SZ
-#define RW_PART2_SZ	0x400000 - (0x10000 + 0x20000)
-#define RW_PART3_OF	RW_PART2_OF + RW_PART2_SZ
-#define RW_PART3_SZ	0x20000
-
-static struct mtd_partition redwood_flash_partitions[] = {
-	{
-		.name = "Redwood filesystem",
-		.offset = RW_PART0_OF,
-		.size = RW_PART0_SZ
-	},
-	{
-		.name = "Redwood OpenBIOS Vital Product Data",
-		.offset = RW_PART1_OF,
-		.size = RW_PART1_SZ,
-		.mask_flags = MTD_WRITEABLE	/* force read-only */
-	},
-	{
-		.name = "Redwood kernel",
-		.offset = RW_PART2_OF,
-		.size = RW_PART2_SZ
-	},
-	{
-		.name = "Redwood OpenBIOS",
-		.offset = RW_PART3_OF,
-		.size = RW_PART3_SZ,
-		.mask_flags = MTD_WRITEABLE	/* force read-only */
-	}
-};
-
-#endif /* CONFIG_REDWOOD_6 */
-
 struct map_info redwood_flash_map = {
 	.name = "IBM Redwood",
 	.size = WINDOW_SIZE,
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ce2fcdd..313d306 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -913,7 +913,7 @@ config SMC91X
 	tristate "SMC 91C9x/91C1xxx support"
 	select CRC32
 	select MII
-	depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || \
+	depends on ARM || M32R || SUPERH || \
 		MIPS || BLACKFIN || MN10300 || COLDFIRE
 	help
 	  This is a driver for SMC's 91x series of Ethernet chipsets,
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 8/8] sdhci: Use jiffies instead of a timeout counter
From: Anton Vorontsov @ 2010-07-14 13:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

Just a cosmetic change, should not affect functionality.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index e6adda8..c754df1 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
+#include <linux/jiffies.h>
 
 #include <linux/leds.h>
 
@@ -160,17 +161,16 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
 		host->clock = 0;
 
 	/* Wait max 100 ms */
-	timeout = 100;
+	timeout = jiffies + msecs_to_jiffies(100);
 
 	/* hw clears the bit when it's done */
 	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
-		if (timeout == 0) {
+		if (time_after(jiffies, timeout)) {
 			printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
 				mmc_hostname(host->mmc), (int)mask);
 			sdhci_dumpregs(host);
 			return;
 		}
-		timeout--;
 		msleep(1);
 	}
 
@@ -884,7 +884,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 	WARN_ON(host->cmd);
 
 	/* Wait max 10 ms */
-	timeout = 10;
+	timeout = jiffies + msecs_to_jiffies(10);
 
 	mask = SDHCI_CMD_INHIBIT;
 	if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
@@ -896,7 +896,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 		mask &= ~SDHCI_DATA_INHIBIT;
 
 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
-		if (timeout == 0) {
+		if (time_after(jiffies, timeout)) {
 			printk(KERN_ERR "%s: Controller never released "
 				"inhibit bit(s).\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
@@ -904,7 +904,6 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 			schedule_work(&host->finish_work);
 			return;
 		}
-		timeout--;
 		mdelay(1);
 	}
 
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 7/8] sdhci: Get rid of mdelay()s where it is safe and makes sense
From: Anton Vorontsov @ 2010-07-14 13:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

Since we don't run in the atomic context any longer, we can
turn mdelay()s into msleep()s.

The only place where the driver is still using mdelay() is
sdhci_send_command(). There it is possible to use sleepable
delays too, but we don't actually want to force rescheduling
in a hot path.

Sure, we might end up calling msleep() there too, just not
via this safe patch.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci-of-esdhc.c |    2 +-
 drivers/mmc/host/sdhci.c          |    6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index c8623de..e9f99fe 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -94,7 +94,7 @@ static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
 	setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
 		  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
 		  div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT);
-	mdelay(100);
+	msleep(100);
 out:
 	host->clock = clock;
 }
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 56d5c56..e6adda8 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -171,7 +171,7 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
 			return;
 		}
 		timeout--;
-		mdelay(1);
+		msleep(1);
 	}
 
 	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
@@ -1019,7 +1019,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
 			return;
 		}
 		timeout--;
-		mdelay(1);
+		msleep(1);
 	}
 
 	clk |= SDHCI_CLOCK_CARD_EN;
@@ -1086,7 +1086,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	 * can apply clock after applying power
 	 */
 	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
-		mdelay(10);
+		msleep(10);
 }
 
 /*****************************************************************************\
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 6/8] sdhci: Get rid of card detect work
From: Anton Vorontsov @ 2010-07-14 13:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

Nowadays we can just call the card detection handler directly,
no need for the separate work struct.

We still need host->finish_work as sdhci_finish_work() calls
mmc_request_done(), which tries to re-enter the driver.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   14 ++------------
 drivers/mmc/host/sdhci.h |    1 -
 2 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5eddbdb..56d5c56 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1239,14 +1239,8 @@ static const struct mmc_host_ops sdhci_ops = {
  *                                                                           *
 \*****************************************************************************/
 
-static void sdhci_card_detect_work(struct work_struct *wk)
+static void sdhci_card_detect(struct sdhci_host *host)
 {
-	struct sdhci_host *host;
-
-	host = container_of(wk, struct sdhci_host, card_detect_work);
-
-	mutex_lock(&host->lock);
-
 	if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
 		if (host->mrq) {
 			printk(KERN_ERR "%s: Card removed during transfer!\n",
@@ -1262,8 +1256,6 @@ static void sdhci_card_detect_work(struct work_struct *wk)
 		}
 	}
 
-	mutex_unlock(&host->lock);
-
 	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
 }
 
@@ -1511,7 +1503,7 @@ static irqreturn_t sdhci_irq_thread(int irq, void *dev_id)
 	sdhci_writel(host, intmask, SDHCI_INT_STATUS);
 
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
-		schedule_work(&host->card_detect_work);
+		sdhci_card_detect(host);
 
 	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
 
@@ -1865,7 +1857,6 @@ int sdhci_add_host(struct sdhci_host *host)
 	/*
 	 * Init work structs.
 	 */
-	INIT_WORK(&host->card_detect_work, sdhci_card_detect_work);
 	INIT_WORK(&host->finish_work, sdhci_finish_work);
 
 	INIT_DELAYED_WORK(&host->timeout_work, sdhci_timeout_work);
@@ -1950,7 +1941,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
 	flush_delayed_work(&host->timeout_work);
 
-	flush_work(&host->card_detect_work);
 	flush_work(&host->finish_work);
 
 	kfree(host->adma_desc);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 364d4e8..5f7d649 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -289,7 +289,6 @@ struct sdhci_host {
 	dma_addr_t		adma_addr;	/* Mapped ADMA descr. table */
 	dma_addr_t		align_addr;	/* Mapped bounce buffer */
 
-	struct work_struct	card_detect_work;
 	struct work_struct	finish_work;
 
 	struct delayed_work	timeout_work;	/* Work for timeouts */
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 5/8] sdhci: Turn host->lock into a mutex
From: Anton Vorontsov @ 2010-07-14 13:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

Finally, we can get rid of the host->lock spinlock, and turn it
into a mutex.

This patch does just this.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   53 +++++++++++++++++++--------------------------
 drivers/mmc/host/sdhci.h |    3 +-
 2 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0358b35..5eddbdb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <linux/scatterlist.h>
 
 #include <linux/leds.h>
@@ -228,16 +229,15 @@ static void sdhci_led_control(struct led_classdev *led,
 	enum led_brightness brightness)
 {
 	struct sdhci_host *host = container_of(led, struct sdhci_host, led);
-	unsigned long flags;
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	if (brightness == LED_OFF)
 		sdhci_deactivate_led(host);
 	else
 		sdhci_activate_led(host);
 
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 }
 #endif
 
@@ -1099,11 +1099,10 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host;
 	bool present;
-	unsigned long flags;
 
 	host = mmc_priv(mmc);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	WARN_ON(host->mrq != NULL);
 
@@ -1127,18 +1126,17 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 		sdhci_send_command(host, mrq->cmd);
 
 	mmiowb();
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 }
 
 static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct sdhci_host *host;
-	unsigned long flags;
 	u8 ctrl;
 
 	host = mmc_priv(mmc);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	if (host->flags & SDHCI_DEVICE_DEAD)
 		goto out;
@@ -1183,25 +1181,24 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 out:
 	mmiowb();
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 }
 
 static int sdhci_get_ro(struct mmc_host *mmc)
 {
 	struct sdhci_host *host;
-	unsigned long flags;
 	int present;
 
 	host = mmc_priv(mmc);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	if (host->flags & SDHCI_DEVICE_DEAD)
 		present = 0;
 	else
 		present = sdhci_readl(host, SDHCI_PRESENT_STATE);
 
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 
 	if (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT)
 		return !!(present & SDHCI_WRITE_PROTECT);
@@ -1211,11 +1208,10 @@ static int sdhci_get_ro(struct mmc_host *mmc)
 static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 {
 	struct sdhci_host *host;
-	unsigned long flags;
 
 	host = mmc_priv(mmc);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	if (host->flags & SDHCI_DEVICE_DEAD)
 		goto out;
@@ -1227,7 +1223,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
 out:
 	mmiowb();
 
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 }
 
 static const struct mmc_host_ops sdhci_ops = {
@@ -1246,11 +1242,10 @@ static const struct mmc_host_ops sdhci_ops = {
 static void sdhci_card_detect_work(struct work_struct *wk)
 {
 	struct sdhci_host *host;
-	unsigned long flags;
 
 	host = container_of(wk, struct sdhci_host, card_detect_work);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
 		if (host->mrq) {
@@ -1267,7 +1262,7 @@ static void sdhci_card_detect_work(struct work_struct *wk)
 		}
 	}
 
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 
 	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
 }
@@ -1275,12 +1270,11 @@ static void sdhci_card_detect_work(struct work_struct *wk)
 static void sdhci_finish_work(struct work_struct *wk)
 {
 	struct sdhci_host *host;
-	unsigned long flags;
 	struct mmc_request *mrq;
 
 	host = container_of(wk, struct sdhci_host, finish_work);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	__cancel_delayed_work(&host->timeout_work);
 
@@ -1321,7 +1315,7 @@ static void sdhci_finish_work(struct work_struct *wk)
 #endif
 
 	mmiowb();
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 
 	mmc_request_done(host->mmc, mrq);
 }
@@ -1329,11 +1323,10 @@ static void sdhci_finish_work(struct work_struct *wk)
 static void sdhci_timeout_work(struct work_struct *wk)
 {
 	struct sdhci_host *host;
-	unsigned long flags;
 
 	host = container_of(wk, struct sdhci_host, timeout_work.work);
 
-	spin_lock_irqsave(&host->lock, flags);
+	mutex_lock(&host->lock);
 
 	if (host->mrq) {
 		printk(KERN_ERR "%s: Timeout waiting for hardware "
@@ -1354,7 +1347,7 @@ static void sdhci_timeout_work(struct work_struct *wk)
 	}
 
 	mmiowb();
-	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->lock);
 }
 
 /*****************************************************************************\
@@ -1512,7 +1505,7 @@ static irqreturn_t sdhci_irq_thread(int irq, void *dev_id)
 	u32 intmask;
 	int cardint = 0;
 
-	spin_lock(&host->lock);
+	mutex_lock(&host->lock);
 
 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
 	sdhci_writel(host, intmask, SDHCI_INT_STATUS);
@@ -1551,7 +1544,7 @@ static irqreturn_t sdhci_irq_thread(int irq, void *dev_id)
 
 	mmiowb();
 
-	spin_unlock(&host->lock);
+	mutex_unlock(&host->lock);
 
 	/*
 	 * We have to delay this as it calls back into the driver.
@@ -1816,7 +1809,7 @@ int sdhci_add_host(struct sdhci_host *host)
 		return -ENODEV;
 	}
 
-	spin_lock_init(&host->lock);
+	mutex_init(&host->lock);
 
 	/*
 	 * Maximum number of segments. Depends on if the hardware
@@ -1926,10 +1919,8 @@ EXPORT_SYMBOL_GPL(sdhci_add_host);
 
 void sdhci_remove_host(struct sdhci_host *host, int dead)
 {
-	unsigned long flags;
-
 	if (dead) {
-		spin_lock_irqsave(&host->lock, flags);
+		mutex_lock(&host->lock);
 
 		host->flags |= SDHCI_DEVICE_DEAD;
 
@@ -1941,7 +1932,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 			schedule_work(&host->finish_work);
 		}
 
-		spin_unlock_irqrestore(&host->lock, flags);
+		mutex_unlock(&host->lock);
 	}
 
 	sdhci_disable_card_detection(host);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index d96e4dd..364d4e8 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -15,6 +15,7 @@
 #include <linux/workqueue.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/mutex.h>
 #include <linux/io.h>
 
 /*
@@ -256,7 +257,7 @@ struct sdhci_host {
 	char   led_name[32];
 #endif
 
-	spinlock_t		lock;		/* Mutex */
+	struct mutex		lock;		/* Mutex */
 
 	int			flags;		/* Host attributes */
 #define SDHCI_USE_SDMA		(1<<0)		/* Host is SDMA capable */
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 4/8] sdhci: Use threaded IRQ handler
From: Anton Vorontsov @ 2010-07-14 13:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

We only need atomic context to disable SDHCI interrupts, after that
we can run in a kernel thread.

Note that irq handler still grabs an irqsave spinlock, we'll deal
with it in a subsequent patch.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   47 +++++++++++++++++++++++++++------------------
 1 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9ec245c..0358b35 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1506,9 +1506,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
 	}
 }
 
-static irqreturn_t sdhci_irq(int irq, void *dev_id)
+static irqreturn_t sdhci_irq_thread(int irq, void *dev_id)
 {
-	irqreturn_t result;
 	struct sdhci_host* host = dev_id;
 	u32 intmask;
 	int cardint = 0;
@@ -1516,17 +1515,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 	spin_lock(&host->lock);
 
 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
-
-	if (!intmask || intmask == 0xffffffff) {
-		result = IRQ_NONE;
-		goto out;
-	}
-
 	sdhci_writel(host, intmask, SDHCI_INT_STATUS);
 
-	DBG("*** %s got interrupt: 0x%08x\n",
-		mmc_hostname(host->mmc), intmask);
-
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
 		schedule_work(&host->card_detect_work);
 
@@ -1559,10 +1549,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		sdhci_dumpregs(host);
 	}
 
-	result = IRQ_HANDLED;
-
 	mmiowb();
-out:
+
 	spin_unlock(&host->lock);
 
 	/*
@@ -1571,7 +1559,28 @@ out:
 	if (cardint)
 		mmc_signal_sdio_irq(host->mmc);
 
-	return result;
+	/* Restore interrupts */
+	intmask = sdhci_readl(host, SDHCI_INT_ENABLE);
+	sdhci_writel(host, intmask, SDHCI_SIGNAL_ENABLE);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t sdhci_irq(int irq, void *dev_id)
+{
+	struct sdhci_host *host = dev_id;
+	u32 intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+
+	if (!intmask || intmask == 0xffffffff)
+		return IRQ_NONE;
+
+	/* Disable interrupts */
+	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+
+	DBG("*** %s got interrupt: 0x%08x\n",
+		mmc_hostname(host->mmc), intmask);
+
+	return IRQ_WAKE_THREAD;
 }
 
 /*****************************************************************************\
@@ -1608,8 +1617,8 @@ int sdhci_resume_host(struct sdhci_host *host)
 			host->ops->enable_dma(host);
 	}
 
-	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-			  mmc_hostname(host->mmc), host);
+	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_irq_thread,
+			  IRQF_SHARED, mmc_hostname(host->mmc), host);
 	if (ret)
 		return ret;
 
@@ -1868,8 +1877,8 @@ int sdhci_add_host(struct sdhci_host *host)
 
 	INIT_DELAYED_WORK(&host->timeout_work, sdhci_timeout_work);
 
-	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-		mmc_hostname(mmc), host);
+	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_irq_thread,
+			  IRQF_SHARED, mmc_hostname(host->mmc), host);
 	if (ret)
 		return ret;
 
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 3/8] sdhci: Clear interrupt status register just once
From: Anton Vorontsov @ 2010-07-14 13:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

There's no need to clear the interrupt status register bit-by-bit,
we can just clear it once. This simplifies irq handler.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   23 ++++++-----------------
 1 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 748a2e3..9ec245c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1522,38 +1522,29 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		goto out;
 	}
 
+	sdhci_writel(host, intmask, SDHCI_INT_STATUS);
+
 	DBG("*** %s got interrupt: 0x%08x\n",
 		mmc_hostname(host->mmc), intmask);
 
-	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE))
 		schedule_work(&host->card_detect_work);
-	}
 
 	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
 
-	if (intmask & SDHCI_INT_CMD_MASK) {
-		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
-			SDHCI_INT_STATUS);
+	if (intmask & SDHCI_INT_CMD_MASK)
 		sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
-	}
 
-	if (intmask & SDHCI_INT_DATA_MASK) {
-		sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
-			SDHCI_INT_STATUS);
+	if (intmask & SDHCI_INT_DATA_MASK)
 		sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
-	}
 
 	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
 
 	intmask &= ~SDHCI_INT_ERROR;
 
-	if (intmask & SDHCI_INT_BUS_POWER) {
+	if (intmask & SDHCI_INT_BUS_POWER)
 		printk(KERN_ERR "%s: Card is consuming too much power!\n",
 			mmc_hostname(host->mmc));
-		sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
-	}
 
 	intmask &= ~SDHCI_INT_BUS_POWER;
 
@@ -1566,8 +1557,6 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 		printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
 			mmc_hostname(host->mmc), intmask);
 		sdhci_dumpregs(host);
-
-		sdhci_writel(host, intmask, SDHCI_INT_STATUS);
 	}
 
 	result = IRQ_HANDLED;
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 2/8] sdhci: Use work structs instead of tasklets
From: Anton Vorontsov @ 2010-07-14 13:07 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

The driver can happily live without an atomic context and tasklets,
so turn the tasklets into the work structs.

Tasklets handlers still grab irqsave spinlocks, but we'll deal
with it in a separate patch.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   48 ++++++++++++++++++++-------------------------
 drivers/mmc/host/sdhci.h |    4 +-
 2 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index dc6328c..748a2e3 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -872,7 +872,7 @@ static void sdhci_finish_data(struct sdhci_host *host)
 
 		sdhci_send_command(host, data->stop);
 	} else
-		tasklet_schedule(&host->finish_tasklet);
+		schedule_work(&host->finish_work);
 }
 
 static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
@@ -901,7 +901,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 				"inhibit bit(s).\n", mmc_hostname(host->mmc));
 			sdhci_dumpregs(host);
 			cmd->error = -EIO;
-			tasklet_schedule(&host->finish_tasklet);
+			schedule_work(&host->finish_work);
 			return;
 		}
 		timeout--;
@@ -922,7 +922,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 		printk(KERN_ERR "%s: Unsupported response type!\n",
 			mmc_hostname(host->mmc));
 		cmd->error = -EINVAL;
-		tasklet_schedule(&host->finish_tasklet);
+		schedule_work(&host->finish_work);
 		return;
 	}
 
@@ -973,7 +973,7 @@ static void sdhci_finish_command(struct sdhci_host *host)
 		sdhci_finish_data(host);
 
 	if (!host->cmd->data)
-		tasklet_schedule(&host->finish_tasklet);
+		schedule_work(&host->finish_work);
 
 	host->cmd = NULL;
 }
@@ -1122,7 +1122,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 	if (!present || host->flags & SDHCI_DEVICE_DEAD) {
 		host->mrq->cmd->error = -ENOMEDIUM;
-		tasklet_schedule(&host->finish_tasklet);
+		schedule_work(&host->finish_work);
 	} else
 		sdhci_send_command(host, mrq->cmd);
 
@@ -1239,16 +1239,16 @@ static const struct mmc_host_ops sdhci_ops = {
 
 /*****************************************************************************\
  *                                                                           *
- * Tasklets                                                                  *
+ * Work handlers                                                             *
  *                                                                           *
 \*****************************************************************************/
 
-static void sdhci_tasklet_card(unsigned long param)
+static void sdhci_card_detect_work(struct work_struct *wk)
 {
 	struct sdhci_host *host;
 	unsigned long flags;
 
-	host = (struct sdhci_host*)param;
+	host = container_of(wk, struct sdhci_host, card_detect_work);
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -1263,7 +1263,7 @@ static void sdhci_tasklet_card(unsigned long param)
 			sdhci_reset(host, SDHCI_RESET_DATA);
 
 			host->mrq->cmd->error = -ENOMEDIUM;
-			tasklet_schedule(&host->finish_tasklet);
+			schedule_work(&host->finish_work);
 		}
 	}
 
@@ -1272,13 +1272,13 @@ static void sdhci_tasklet_card(unsigned long param)
 	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
 }
 
-static void sdhci_tasklet_finish(unsigned long param)
+static void sdhci_finish_work(struct work_struct *wk)
 {
 	struct sdhci_host *host;
 	unsigned long flags;
 	struct mmc_request *mrq;
 
-	host = (struct sdhci_host*)param;
+	host = container_of(wk, struct sdhci_host, finish_work);
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -1349,7 +1349,7 @@ static void sdhci_timeout_work(struct work_struct *wk)
 			else
 				host->mrq->cmd->error = -ETIMEDOUT;
 
-			tasklet_schedule(&host->finish_tasklet);
+			schedule_work(&host->finish_work);
 		}
 	}
 
@@ -1382,7 +1382,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
 		host->cmd->error = -EILSEQ;
 
 	if (host->cmd->error) {
-		tasklet_schedule(&host->finish_tasklet);
+		schedule_work(&host->finish_work);
 		return;
 	}
 
@@ -1528,7 +1528,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
 	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
 		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
 			SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
-		tasklet_schedule(&host->card_tasklet);
+		schedule_work(&host->card_detect_work);
 	}
 
 	intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
@@ -1872,19 +1872,17 @@ int sdhci_add_host(struct sdhci_host *host)
 	mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
 
 	/*
-	 * Init tasklets.
+	 * Init work structs.
 	 */
-	tasklet_init(&host->card_tasklet,
-		sdhci_tasklet_card, (unsigned long)host);
-	tasklet_init(&host->finish_tasklet,
-		sdhci_tasklet_finish, (unsigned long)host);
+	INIT_WORK(&host->card_detect_work, sdhci_card_detect_work);
+	INIT_WORK(&host->finish_work, sdhci_finish_work);
 
 	INIT_DELAYED_WORK(&host->timeout_work, sdhci_timeout_work);
 
 	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
 		mmc_hostname(mmc), host);
 	if (ret)
-		goto untasklet;
+		return ret;
 
 	sdhci_init(host, 0);
 
@@ -1923,10 +1921,6 @@ reset:
 	sdhci_reset(host, SDHCI_RESET_ALL);
 	free_irq(host->irq, host);
 #endif
-untasklet:
-	tasklet_kill(&host->card_tasklet);
-	tasklet_kill(&host->finish_tasklet);
-
 	return ret;
 }
 
@@ -1946,7 +1940,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 				" transfer!\n", mmc_hostname(host->mmc));
 
 			host->mrq->cmd->error = -ENOMEDIUM;
-			tasklet_schedule(&host->finish_tasklet);
+			schedule_work(&host->finish_work);
 		}
 
 		spin_unlock_irqrestore(&host->lock, flags);
@@ -1967,8 +1961,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
 	flush_delayed_work(&host->timeout_work);
 
-	tasklet_kill(&host->card_tasklet);
-	tasklet_kill(&host->finish_tasklet);
+	flush_work(&host->card_detect_work);
+	flush_work(&host->finish_work);
 
 	kfree(host->adma_desc);
 	kfree(host->align_buffer);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 55c114d..d96e4dd 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -288,8 +288,8 @@ struct sdhci_host {
 	dma_addr_t		adma_addr;	/* Mapped ADMA descr. table */
 	dma_addr_t		align_addr;	/* Mapped bounce buffer */
 
-	struct tasklet_struct	card_tasklet;	/* Tasklet structures */
-	struct tasklet_struct	finish_tasklet;
+	struct work_struct	card_detect_work;
+	struct work_struct	finish_work;
 
 	struct delayed_work	timeout_work;	/* Work for timeouts */
 
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 1/8] sdhci: Turn timeout timer into delayed work
From: Anton Vorontsov @ 2010-07-14 13:07 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman
In-Reply-To: <20100714130728.GA27339@oksana.dev.rtsoft.ru>

There is no need for the timeout handler to run in the atomic
context, so this patch turns timeout timeout into the delayed
work.

Note that the timeout handler still grabs an irqsave spinlock,
we'll deal with it in a separate patch.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---
 drivers/mmc/host/sdhci.c |   14 ++++++++------
 drivers/mmc/host/sdhci.h |    3 ++-
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c6d1bd8..dc6328c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -13,6 +13,8 @@
  *     - JMicron (hardware and technical support)
  */
 
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
@@ -906,7 +908,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
 		mdelay(1);
 	}
 
-	mod_timer(&host->timer, jiffies + 10 * HZ);
+	schedule_delayed_work(&host->timeout_work, 10 * HZ);
 
 	host->cmd = cmd;
 
@@ -1280,7 +1282,7 @@ static void sdhci_tasklet_finish(unsigned long param)
 
 	spin_lock_irqsave(&host->lock, flags);
 
-	del_timer(&host->timer);
+	__cancel_delayed_work(&host->timeout_work);
 
 	mrq = host->mrq;
 
@@ -1324,12 +1326,12 @@ static void sdhci_tasklet_finish(unsigned long param)
 	mmc_request_done(host->mmc, mrq);
 }
 
-static void sdhci_timeout_timer(unsigned long data)
+static void sdhci_timeout_work(struct work_struct *wk)
 {
 	struct sdhci_host *host;
 	unsigned long flags;
 
-	host = (struct sdhci_host*)data;
+	host = container_of(wk, struct sdhci_host, timeout_work.work);
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -1877,7 +1879,7 @@ int sdhci_add_host(struct sdhci_host *host)
 	tasklet_init(&host->finish_tasklet,
 		sdhci_tasklet_finish, (unsigned long)host);
 
-	setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
+	INIT_DELAYED_WORK(&host->timeout_work, sdhci_timeout_work);
 
 	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
 		mmc_hostname(mmc), host);
@@ -1963,7 +1965,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
 	free_irq(host->irq, host);
 
-	del_timer_sync(&host->timer);
+	flush_delayed_work(&host->timeout_work);
 
 	tasklet_kill(&host->card_tasklet);
 	tasklet_kill(&host->finish_tasklet);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c846813..55c114d 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -12,6 +12,7 @@
 #define __SDHCI_H
 
 #include <linux/scatterlist.h>
+#include <linux/workqueue.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/io.h>
@@ -290,7 +291,7 @@ struct sdhci_host {
 	struct tasklet_struct	card_tasklet;	/* Tasklet structures */
 	struct tasklet_struct	finish_tasklet;
 
-	struct timer_list	timer;		/* Timer for timeouts */
+	struct delayed_work	timeout_work;	/* Work for timeouts */
 
 	unsigned long		private[0] ____cacheline_aligned;
 };
-- 
1.7.0.5

^ permalink raw reply related

* [PATCH 0/8] sdhci: Move real work out of an atomic context
From: Anton Vorontsov @ 2010-07-14 13:07 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Matt Fleming, Albert Herranz, linux-mmc, linux-kernel,
	linuxppc-dev, Ben Dooks, Pierre Ossman

Hi all,

Currently the sdhci driver does everything in the atomic context.
And what is worse, PIO transfers are made from the IRQ handler.

This causes huge latencies (up to 120 ms). On some P2020 SOCs,
DMA and card detection is broken, which means that kernel polls
for the card via PIO transfers every second. Needless to say
that this is quite bad.

So, this patch set reworks sdhci code to avoid atomic context,
almost completely. We only do two device memory operations
in the atomic context, and all the rest is threaded.

I noticed no throughput drop neither with PIO transfers nor
with DMA (tested on MPC8569E CPU), while latencies should be
greatly improved.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH] powerpc:prom Export device tree physical address via proc
From: Segher Boessenkool @ 2010-07-14 12:51 UTC (permalink / raw)
  To: Timur Tabi; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <4C3CB69D.4060400@freescale.com>

>> +	if (prop)
>> +		prom_remove_property(node, prop);
>> +		prop = of_find_property(node, "linux,devietree-end", NULL);
>
> Either the indentation is wrong, or you're missing some braces here

You're missing a "c" as well (and a dash).


Segher

^ permalink raw reply

* cpm_uart_console_write() stuck in waiting for transmitter fifo ready
From: Shawn Jin @ 2010-07-14  9:05 UTC (permalink / raw)
  To: ppcdev, galak, panto, Scott Wood

Hi Gurus,

Please give me some hints and directions to debug this problem. I've
been scratching my head for quite a while.

The problem is that after/when the kernel switches to the real console
from the boot console, printk() calls cpm_uart_console_write() to
print the first (?) message using the cpm_uart driver. But the
transmitter buffer never becomes ready. It's shown below with the gdb
session.

Program received signal SIGSTOP, Stopped (signal).
0xc00f3510 in cpm_uart_console_write (co=3D<value optimized out>,
s=3D0xc017703e "console [ttyCPM0] enabled, bootconsole disabled\n",
count=3D0x30) at /home/code/linux-2.6.33.5/arch/powerpc/include/asm/io.h:15=
4
(gdb) next
(gdb) x/4h bdbase
0xfddfa020:	0xffff	0xffff	0xffff	0xffff
(gdb)

Why would the TxBD be filled with all 0xF? Would it be possible that
the bdbase actually points somewhere else other than the TxBD?

The kernel boot messages are copied below. My target is MPC870, using
SMC1 as UART. I'm porting the kernel based on adder875 board.

=3D> bootm 1000000
## Booting image at 01000000 ...
   Image Name:   Linux-2.6.33.5
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    706700 Bytes =3D 690.1 kB
   Load Address: 00400000
   Entry Point:  00400554
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Memory <- <0x0 0x8000000> (128MB)
ENET0: local-mac-address <- 00:09:9b:01:58:64
CPU clock-frequency <- 0x7270e00 (120MHz)
CPU timebase-frequency <- 0x7270e0 (8MHz)
CPU bus-frequency <- 0x3938700 (60MHz)

zImage starting: loaded at 0x00400000 (sp: 0x07d1cbd0)
Allocating 0x186be5 bytes for kernel ...
gunzipping (0x00000000 <- 0x0040c000:0x005c1b78)...done 0x173b10 bytes

Linux/PowerPC load: root=3D/dev/ram
Finalizing device tree... flat tree at 0x5ce300
Probing machine type ...
  My MPC870 ... match !
id mach(): done
MMU:enter
MMU:hw init
MMU:mapin
MMU:setio
MMU:exit
Using My MPC870 machine description
Linux version 2.6.33.5 (shawn@ubuntu) (gcc version 4.2.2) #17 Wed Jul
14 01:24:03 PDT 2010
bootconsole [udbg0] enabled
setup_arch: bootmem
arch: exit
Top of RAM: 0x8000000, Total RAM: 0x8000000
Memory hole size: 0MB
Zone PFN ranges:
  DMA      0x00000000 -> 0x00008000
  Normal   0x00008000 -> 0x00008000
Movable zone start PFN for each node
early_node_map[1] active PFN ranges
    0: 0x00000000 -> 0x00008000
On node 0 totalpages: 32768
free_area_init_node: node 0, pgdat c016b5b0, node_mem_map c0189000
  DMA zone: 256 pages used for memmap
  DMA zone: 0 pages reserved
  DMA zone: 32512 pages, LIFO batch:7
MMU: Allocated 72 bytes of context maps for 16 contexts
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 32512
Kernel command line: root=3D/dev/ram
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 128096k/131072k available (1416k kernel code, 2836k reserved,
72k data, 74k bss, 76k init)
Kernel virtual memory layout:
  * 0xfffdf000..0xfffff000  : fixmap
  * 0xfde00000..0xfe000000  : consistent mem
  * 0xfddfa000..0xfde00000  : early ioremap
  * 0xc9000000..0xfddfa000  : vmalloc & ioremap
SLUB: Genslabs=3D12, HWalign=3D16, Order=3D0-3, MinObjects=3D0, CPUs=3D1, N=
odes=3D1
Hierarchical RCU implementation.
NR_IRQS:512 nr_irqs:512
irq: Allocated host of type 2 @0xc7804000
irq: irq_create_mapping(0xc7804000, 0x5)
irq: -> using host @c7804000
  alloc irq_desc for 16 on node 0
  alloc kstat_irqs on node 0
irq: irq 5 on host /soc@fa200000/interrupt-controller@0 mapped to virtual i=
rq 16
irq: Allocated host of type 2 @0xc7804200
irq: irq_create_mapping(0xc7804200, 0x0)
irq: -> using host @c7804200
  alloc irq_desc for 17 on node 0
  alloc kstat_irqs on node 0
irq: irq 0 on host /soc@fa200000/cpm@9c0/interrupt-controller@930
mapped to virtual irq 17
Decrementer Frequency =3D 0x7270e0
irq: irq_create_mapping(0xc7804000, 0xf)
irq: -> using host @c7804000
  alloc irq_desc for 18 on node 0
  alloc kstat_irqs on node 0
irq: irq 15 on host /soc@fa200000/interrupt-controller@0 mapped to
virtual irq 18
time_init: decrementer frequency =3D 7.500000 MHz
time_init: processor frequency   =3D 120.000000 MHz
clocksource: timebase mult[21555555] shift[22] registered
clockevent: decrementer mult[1eb851e] shift[32] cpu[0]
irq: irq_create_mapping(0xc7804200, 0x4)
irq: -> using host @c7804200
  alloc irq_desc for 19 on node 0
  alloc kstat_irqs on node 0
irq: irq 4 on host /soc@fa200000/cpm@9c0/interrupt-controller@930
mapped to virtual irq 1=EF=BF=BD

Thanks a lot,
-Shawn.

^ permalink raw reply

* Re: [PATCH 4/7] Allow sysfs memory directories to be split
From: KAMEZAWA Hiroyuki @ 2010-07-14  8:30 UTC (permalink / raw)
  To: KAMEZAWA Hiroyuki; +Cc: linuxppc-dev, linux-kernel, Dave Hansen
In-Reply-To: <20100714122503.74f746a2.kamezawa.hiroyu@jp.fujitsu.com>

On Wed, 14 Jul 2010 12:25:03 +0900
KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> wrote:

> On Tue, 13 Jul 2010 22:18:03 -0500
> Nathan Fontenot <nfont@austin.ibm.com> wrote:
> 
> > On 07/13/2010 07:35 PM, KAMEZAWA Hiroyuki wrote:
> > > On Tue, 13 Jul 2010 10:51:58 -0500
> > > Nathan Fontenot <nfont@austin.ibm.com> wrote:
> > > 
> > >>>
> > >>> And for what purpose this interface is ? Does this split memory block into 2 pieces
> > >>> of the same size ?? sounds __very__ strange interface to me.
> > >>
> > >> Yes, this splits the memory_block into two blocks of the same size.  This was
> > >> suggested as something we may want to do.  From ppc perspective I am not sure we
> > >> would use this.
> > >>
> > >> The split functionality is not required.  The main goal of the patch set is to
> > >> reduce the number of memory sysfs directories created.  From a ppc perspective
> > >> the split functionality is not really needed.
> > >>
> > > 
> > > Okay, this is an offer from me.
> > > 
> > >   1. I think you can add an boot option as "don't create memory sysfs".
> > >      please do.
> > 
> > I posted a patch to do that a week or so ago, it didn't go over very well.
> > 
> > > 
> > >   2. I'd like to write a configfs module for handling memory hotplug even when
> > >      sysfs directroy is not created.
> > >      Because configfs support rmdir/mkdir, the user (ppc's daemon?) has to do
> > >      
> > >      When offlining section X.
> > >      # insmod configfs_memory.ko
> > >      # mount -t configfs none /configfs
> > >      # mkdir /configfs/memoryX
> > >      # echo offline > /configfs/memoryX/state
> > >      # rmdir /configfs/memoryX
> > > 
> > >   And making this operation as the default bahavior for all arch's memory hotplug may
> > >   be better...
> > > 
> > > Dave, how do you think ? Because ppc guys uses "probe" interface already,
> > > this can be handled... no ?
> > 
> > ppc would still require the existance of the 'probe' interface.
> > 
> > Are you objecting to the 'split' functionality? 
> yes.
> 
> > If so I do not see any reason from ppc
> > perspective that it is needed.  This was something Dave suggested, unless I am missing
> > something.
> > 
> > Since ppc needs the 'probe' interface in sysfs, and for ppc having mutliple 
> > memory_block_sections reside under a single memory_block makes memory hotplug
> > simpler.  On ppc we do emory hotplug operations on an LMB size basis.  With my
> > patches this now lets us set each memory_block to span an LMB's worth of
> > memory.  Now we could do emory hotplug in a single operation instead of multiple
> > operations to offline/online all of the memory sections in an LMB.
> > 
> 
> Why per-section memory offlining is provided is for allowing good success-rate of
> memory offlining. Because memory-hotplug has to "migrate or free" all used page
> under a section, possibility of memory unplug depends on usage of memory.
> If a section contains unmovable page(kernel page), we can't offline sectin.
> 
> For example, comparing
>   1. offlining 128MB of memory at once
>   2. offlining 8 chunks of 16MB memory
> "2" can get very good possibility and system-busy time can be much reduced.
> 
> IIUC, ppc's 1st requirement is "resizing" not "hot-removing some memory device",
> "2" is much welcomed. So, some fine-grained interface to section_size is
> appreciated. So, "multiple operations" is much better than single operation.
> 
> As I posted show/hide patch, I'm writing it in configfs. I think it meets IBM's
> requirements.
> _But_, it's IBM's issue not Fujitsu's. So, final decistion will depend on you guys.
> 
> Anyway, I don't like a too fancy interface as "split".
> 

This is a sample configfs for handling memory hotplug.
I wrote this just for my fun and study. code-duplication was not as
big as expected...most of codes are for configfs management.

you can ignore this. but please avoid changing existing interace in fancy way.

==
[root@bluextal kamezawa]# mount -t configfs none /configfs/
[root@bluextal kamezawa]# mkdir /configfs/memory/72
[root@bluextal kamezawa]# cat /configfs/memory/72/phys_index
00000048
[root@bluextal kamezawa]# cat /sys/devices/system/memory/memory72/phys_index
00000048
[root@bluextal kamezawa]# echo offline > /configfs/memory/72/state
[root@bluextal kamezawa]# cat /configfs/memory/72/state
offline
[root@bluextal kamezawa]# cat /sys/devices/system/memory/memory72/state
offline
[root@bluextal kamezawa]# echo online > /configfs/memory/72/state
[root@bluextal kamezawa]# cat /sys/devices/system/memory/memory72/state
online

No sign.

---
 drivers/base/Makefile        |    2 
 drivers/base/memory.c        |   87 +++++++++++++++++--
 drivers/base/memory_config.c |  192 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/memory.h       |   10 ++
 mm/Kconfig                   |    1 
 5 files changed, 280 insertions(+), 12 deletions(-)

Index: mmotm-2.6.35-0701/drivers/base/memory.c
===================================================================
--- mmotm-2.6.35-0701.orig/drivers/base/memory.c
+++ mmotm-2.6.35-0701/drivers/base/memory.c
@@ -23,12 +23,15 @@
 #include <linux/mutex.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
+#include <linux/radix-tree.h>
 
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
 #define MEMORY_CLASS_NAME	"memory"
 
+
+
 static struct sysdev_class memory_sysdev_class = {
 	.name = MEMORY_CLASS_NAME,
 };
@@ -104,17 +107,57 @@ unregister_memory(struct memory_block *m
 	sysdev_unregister(&memory->sysdev);
 }
 
+/* routine for remember memory's status when configs is not used. */
+
+RADIX_TREE(hidden_mems, GFP_KERNEL);
+DEFINE_MUTEX(hidden_mems_mutex);
+int record_memory_state(unsigned long section_nr, int status)
+{
+	int ret = -ENOMEM;
+	long lstat = status << 8; /* for avoid radix'trees special handling */
+	mutex_lock(&hidden_mems_mutex);
+	radix_tree_delete(&hidden_mems, section_nr);
+	if (radix_tree_preload(GFP_KERNEL))
+		goto out;
+	ret = radix_tree_insert(&hidden_mems, section_nr, (void*)lstat);
+	radix_tree_preload_end();
+out:
+	mutex_unlock(&hidden_mems_mutex);
+	return ret;
+}
+
+int lookup_memory_state(unsigned long section_nr)
+{
+	void *ptr;
+	/* we already have big mutex */
+	ptr= radix_tree_lookup(&hidden_mems, section_nr);
+	/* treate not-recorded mems'state as ONLINE...? */
+	return ((long)ptr) >> 8;
+}
+
+void forget_memory_state(unsigned long section_nr)
+{
+	radix_tree_delete(&hidden_mems, section_nr);
+}
+
+
 /*
  * use this as the physical section index that this memsection
  * uses.
  */
 
+ssize_t show_memoryblock_phys_index(struct memory_block *mem,
+	char *buf)
+{
+	return sprintf(buf, "%08lx\n", mem->phys_index);
+}
+
 static ssize_t show_mem_phys_index(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
-	return sprintf(buf, "%08lx\n", mem->phys_index);
+	return show_memoryblock_phys_index(mem, buf);
 }
 
 /*
@@ -136,11 +179,8 @@ static ssize_t show_mem_removable(struct
 /*
  * online, offline, going offline, etc.
  */
-static ssize_t show_mem_state(struct sys_device *dev,
-			struct sysdev_attribute *attr, char *buf)
+ssize_t show_memoryblock_state(struct memory_block *mem, char *buf)
 {
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, sysdev);
 	ssize_t len = 0;
 
 	/*
@@ -167,6 +207,15 @@ static ssize_t show_mem_state(struct sys
 	return len;
 }
 
+ssize_t show_mem_state(struct sys_device *dev,
+		struct sysdev_attribute *attr, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	mem->state = lookup_memory_state(mem->phys_index);
+	return show_memoryblock_state(mem, buf);
+}
+
 int memory_notify(unsigned long val, void *v)
 {
 	return blocking_notifier_call_chain(&memory_chain, val, v);
@@ -218,11 +267,14 @@ memory_block_action(struct memory_block 
 			break;
 		case MEM_OFFLINE:
 			mem->state = MEM_GOING_OFFLINE;
+			record_memory_state(mem->phys_index, mem->state);
 			start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
 			ret = remove_memory(start_paddr,
 					    PAGES_PER_SECTION << PAGE_SHIFT);
 			if (ret) {
 				mem->state = old_state;
+				record_memory_state(mem->phys_index,
+					mem->state);
 				break;
 			}
 			break;
@@ -241,6 +293,8 @@ static int memory_block_change_state(str
 	int ret = 0;
 	mutex_lock(&mem->state_mutex);
 
+	mem->state = lookup_memory_state(mem->phys_index);
+
 	if (mem->state != from_state_req) {
 		ret = -EINVAL;
 		goto out;
@@ -249,21 +303,18 @@ static int memory_block_change_state(str
 	ret = memory_block_action(mem, to_state);
 	if (!ret)
 		mem->state = to_state;
-
+	record_memory_state(mem->phys_index, mem->state);
 out:
 	mutex_unlock(&mem->state_mutex);
 	return ret;
 }
 
-static ssize_t
-store_mem_state(struct sys_device *dev,
-		struct sysdev_attribute *attr, const char *buf, size_t count)
+ssize_t store_memoryblock_state(struct memory_block *mem,
+				const char *buf, size_t count)
 {
-	struct memory_block *mem;
 	unsigned int phys_section_nr;
 	int ret = -EINVAL;
 
-	mem = container_of(dev, struct memory_block, sysdev);
 	phys_section_nr = mem->phys_index;
 
 	if (!present_section_nr(phys_section_nr))
@@ -279,6 +330,16 @@ out:
 	return count;
 }
 
+static ssize_t
+store_mem_state(struct sys_device *dev,
+		struct sysdev_attribute *attr, const char *buf, size_t count)
+{
+	struct memory_block *mem;
+
+	mem = container_of(dev, struct memory_block, sysdev);
+	return store_memoryblock_state(mem, buf, count);
+}
+
 /*
  * phys_device is a bad name for this.  What I really want
  * is a way to differentiate between memory ranges that
@@ -451,6 +512,8 @@ static int add_memory_block(int nid, str
 	start_pfn = section_nr_to_pfn(mem->phys_index);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
+	record_memory_state(mem->phys_index, state);
+
 	ret = register_memory(mem, section);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_index);
@@ -505,6 +568,7 @@ int remove_memory_block(unsigned long no
 	struct memory_block *mem;
 
 	mem = find_memory_block(section);
+	forget_memory_state(mem->phys_index);
 	unregister_mem_sect_under_nodes(mem);
 	mem_remove_simple_file(mem, phys_index);
 	mem_remove_simple_file(mem, state);
@@ -573,3 +637,4 @@ out:
 		printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
 	return ret;
 }
+
Index: mmotm-2.6.35-0701/drivers/base/memory_config.c
===================================================================
--- /dev/null
+++ mmotm-2.6.35-0701/drivers/base/memory_config.c
@@ -0,0 +1,192 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/memory.h>
+#include <linux/slab.h>
+#include <linux/radix-tree.h>
+#include <linux/configfs.h>
+
+
+
+struct memory_hp_block {
+	struct config_group group;
+	struct memory_block mb;
+};
+struct memory_hp_attribute {
+	struct configfs_attribute attr;
+	ssize_t (*show)(struct memory_hp_block *, char *);
+	ssize_t (*store)(struct memory_hp_block *, const char *);
+};
+
+static struct memory_hp_block *to_mhp_block(struct config_item *item)
+{
+	if (!item)
+		return NULL;
+	return container_of(to_config_group(item),
+		struct memory_hp_block, group);
+}
+
+static ssize_t
+memory_hp_phys_index_read(struct memory_hp_block *mhb, char *page)
+{
+        return show_memoryblock_phys_index(&mhb->mb, page);
+}
+
+static struct memory_hp_attribute memory_hp_phys_index = {
+	.attr = { .ca_owner = THIS_MODULE,
+		  .ca_name = "phys_index",
+		  .ca_mode = S_IRUGO },
+	.show = memory_hp_phys_index_read,
+};
+
+static ssize_t
+memory_hp_state_read(struct memory_hp_block *mhb, char *page)
+{
+	/* synchronize */
+	printk("lookup section %ld\n", mhb->mb.phys_index);
+	mhb->mb.state = lookup_memory_state(mhb->mb.phys_index);
+	return show_memoryblock_state(&mhb->mb, page);
+}
+
+static ssize_t
+memory_hp_state_store(struct memory_hp_block *mhb, const char *page)
+{
+	int len = strnlen(page, 8);
+	printk("length %d str %s\n", len, page);
+	if (len > 8) /* online/offline */
+		return -EINVAL;
+	/* synchronize */
+	mhb->mb.state = lookup_memory_state(mhb->mb.phys_index);
+	return store_memoryblock_state(&mhb->mb, page, len);
+}
+
+static struct memory_hp_attribute memory_hp_state = {
+	.attr = { .ca_owner = THIS_MODULE,
+		  .ca_name = "state",
+		  .ca_mode = S_IRUGO|S_IWUSR },
+	.show = memory_hp_state_read,
+	.store = memory_hp_state_store,
+};
+
+static struct configfs_attribute *memory_hp_attrs[] = {
+	&memory_hp_phys_index.attr,
+	&memory_hp_state.attr,
+	NULL,
+};
+
+static ssize_t memory_hp_attr_show(struct config_item *item,
+		struct configfs_attribute *attr,
+		char *page)
+{
+	struct memory_hp_block *mhb = to_mhp_block(item);
+	struct memory_hp_attribute *memhp_attr =
+		container_of(attr, struct memory_hp_attribute, attr);
+	ssize_t ret = 0;
+
+	if (memhp_attr->show)
+		ret = memhp_attr->show(mhb, page);
+	return ret;
+}
+
+static ssize_t memory_hp_attr_store(struct config_item *item,
+		struct configfs_attribute *attr,
+		const char *page, size_t count)
+{
+	struct memory_hp_block *mhb = to_mhp_block(item);
+	struct memory_hp_attribute *memhp_attr =
+		container_of(attr, struct memory_hp_attribute, attr);
+	ssize_t ret = 0;
+
+	if (memhp_attr->store)
+		ret = memhp_attr->store(mhb, page);
+	else
+		ret = -EINVAL;
+	return ret;
+}
+
+static struct configfs_item_operations memory_hp_item_ops = {
+	.show_attribute = memory_hp_attr_show,
+	.store_attribute = memory_hp_attr_store,
+};
+
+static struct  config_item_type memory_hp_type = {
+	.ct_item_ops    = &memory_hp_item_ops,
+	.ct_attrs       = memory_hp_attrs,
+	.ct_owner       = THIS_MODULE,
+};
+
+static struct config_group *
+memory_hp_make_group(struct config_group *group, const char *name)
+{
+	struct memory_hp_block *mhb;
+	unsigned long long section_id;
+
+
+	if (strict_strtoull(name, 10, &section_id))
+		return ERR_PTR(-EINVAL);
+
+	if (!valid_section_nr(section_id))
+		return ERR_PTR(-EINVAL);
+
+	mhb = kzalloc(sizeof(*mhb), GFP_KERNEL);
+	if (!mhb)
+		return NULL;
+
+	config_group_init_type_name(&mhb->group, name, &memory_hp_type);
+
+	mhb->mb.phys_index = section_id;
+	mutex_init(&mhb->mb.state_mutex);
+	mhb->mb.state = lookup_memory_state(section_id);
+
+	return &mhb->group;
+}
+
+static void memory_hp_drop_item(struct config_group *group,
+		struct config_item *item)
+{
+	struct memory_hp_block *mhb;
+
+	mhb = container_of(group, struct memory_hp_block, group);
+	config_item_put(item);
+}
+
+static struct configfs_group_operations memory_hp_group_ops = {
+        .make_group     = memory_hp_make_group,
+	.drop_item	= memory_hp_drop_item,
+};
+
+static struct config_item_type memory_hp_subsys_type = {
+	.ct_group_ops = &memory_hp_group_ops,
+	.ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem memory_hp_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "memory",
+			.ci_type = &memory_hp_subsys_type,
+		},
+	},
+};
+
+static int __init memory_config_init(void)
+{
+	int ret;
+
+	config_group_init(&memory_hp_subsys.su_group);
+	mutex_init(&memory_hp_subsys.su_mutex);
+	ret =  configfs_register_subsystem(&memory_hp_subsys);
+	if (ret) {
+		printk(KERN_ERR "Error %d while registering memory configfs\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+#if 0
+static void __exit memory_config_exit(void)
+{
+	configfs_unregister_subsystem(&memory_hp_subsys);
+}
+#endif
+late_initcall(memory_config_init);
Index: mmotm-2.6.35-0701/drivers/base/Makefile
===================================================================
--- mmotm-2.6.35-0701.orig/drivers/base/Makefile
+++ mmotm-2.6.35-0701/drivers/base/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) 
 obj-$(CONFIG_ISA)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
-obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
+obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o memory_config.o
 obj-$(CONFIG_SMP)	+= topology.o
 obj-$(CONFIG_IOMMU_API) += iommu.o
 ifeq ($(CONFIG_SYSFS),y)
Index: mmotm-2.6.35-0701/mm/Kconfig
===================================================================
--- mmotm-2.6.35-0701.orig/mm/Kconfig
+++ mmotm-2.6.35-0701/mm/Kconfig
@@ -138,6 +138,7 @@ config MEMORY_HOTPLUG
 config MEMORY_HOTPLUG_SPARSE
 	def_bool y
 	depends on SPARSEMEM && MEMORY_HOTPLUG
+	select CONFIGFS_FS
 
 config MEMORY_HOTREMOVE
 	bool "Allow for memory hot remove"
Index: mmotm-2.6.35-0701/include/linux/memory.h
===================================================================
--- mmotm-2.6.35-0701.orig/include/linux/memory.h
+++ mmotm-2.6.35-0701/include/linux/memory.h
@@ -68,6 +68,16 @@ struct memory_isolate_notify {
 struct notifier_block;
 struct mem_section;
 
+
+ssize_t show_memoryblock_phys_index(struct memory_block *mb, char *buf);
+ssize_t show_memoryblock_state(struct memory_block *mb, char *buf);
+ssize_t store_memoryblock_state(struct memory_block *mb,
+			const char *buf, size_t count);
+
+int record_memory_state(unsigned long section, int state);
+int lookup_memory_state(unsigned long section);
+void forget_memory_state(unsigned long section);
+
 /*
  * Priorities for the hotplug memory callback routines (stored in decreasing
  * order in the callback chain)

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox