LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [RFC/PATCH] Change 440GP platform to ppc440
From: Roland Dreier @ 2007-04-24  0:12 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070424000153.GD23995@crusty.rchland.ibm.com>

> > I recall dimly that there was some user-visible difference between the
> > 440GP and the other 440 processors, and that's why we made the
> > platform string different.  I don't recall what the difference was.

FWIW, I've run the same userspace (binaries) on 405GPr, 440GP and
440SPe without any problems.  Not that I'm a 4xx expert by any
stretch, but I don't know of anything special about the 440GP.

 - R.

^ permalink raw reply

* Re: [PATCH] [2/5] pasemi: enable one more hid bit
From: Benjamin Herrenschmidt @ 2007-04-24  0:27 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, paulus
In-Reply-To: <20070416062745.GD20196@lixom.net>

On Mon, 2007-04-16 at 01:27 -0500, Olof Johansson wrote:
> Minor HID change. Firmware can't know that we want this set so we have
> to set it in the kernel.

Care to document/name these bits ?
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>
> 
> Index: linux-2.6/arch/powerpc/kernel/cpu_setup_pa6t.S
> ===================================================================
> --- linux-2.6.orig/arch/powerpc/kernel/cpu_setup_pa6t.S
> +++ linux-2.6/arch/powerpc/kernel/cpu_setup_pa6t.S
> @@ -34,7 +34,7 @@ _GLOBAL(__setup_cpu_pa6t)
>  	beqlr
>  
>  	mfspr	r0,SPRN_HID5
> -	ori	r0,r0,0x30
> +	ori	r0,r0,0x38
>  	mtspr	SPRN_HID5,r0
>  
>  	mfspr	r0,SPRN_LPCR
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [RFC 2/3] PowerPC: lazy altivec enabling in kernel
From: Paul Mackerras @ 2007-04-24  0:52 UTC (permalink / raw)
  To: Sebastian Siewior; +Cc: linuxppc-dev
In-Reply-To: <20070417120925.263638000@linux.vnet.ibm.com>

Sebastian Siewior writes:

>  void enable_kernel_altivec(void)
>  {
> -	WARN_ON(preemptible());
> +	BUG_ON(preemptible());
> +	/*
> +	 * enable_kernel_altivec() will just save current AltiVec registers (if needed) and
> +	 * return to caller (with MSR_VEC unchanged (probably not set)). The first AltiVec
> +	 * instruction will raise an exception and the exception will enable the AltiVec for
> +	 * the kernel. This is done to avoid the expensive "enable altivec" operation if it
> +	 * is allready enabled. However, you have to disable preemtion while you are using
> +	 * AltiVec.
> +	 */

It would be better to put a test and conditional branch in
giveup_altivec to skip the mtmsrd if MSR_VEC is already set.  That
would avoid adding the overhead of the trap in the case when MSR_VEC
isn't already set, besides being much less code.

Paul.

^ permalink raw reply

* Re: [PATCH] generic check_legacy_ioport
From: Benjamin Herrenschmidt @ 2007-04-24  0:53 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev
In-Reply-To: <20070423081540.GA28244@aepfle.de>

On Mon, 2007-04-23 at 10:15 +0200, Olaf Hering wrote:
> check_legacy_ioport makes only sense on PREP, CHRP and pSeries.
> They may have an isa node with PS/2, parport, floppy and serial ports.
> Cell has IPMI, check for that too.
> 
> Remove the check_legacy_ioport call from ppc_md, its not needed anymore.
> Hardware capabilities come from the device-tree.
> 
> Signed-off-by: Olaf Hering <olaf@aepfle.de>

Ok, I like the aproach, but why the heck those ifdef's ? Can't you just
remove them ?

Also, doing ifdef on xxxx_MODULE is always BAD because that means the
module can't be built afterward.

> +	if (np) {
> +		of_node_put(np);
>  		return 0;

And also check now if the parent is "isa". Just to be sure. If a
platform won't match that, then it will need it's own
check_legacy_ioport which is fine with me.

To be totally correct, we should -also- check if the port number fits in
the the actual "reg" property but I'm not sure I can be bothered :-)
It's legacy stuff after all...

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] [2/5] pasemi: enable one more hid bit
From: Olof Johansson @ 2007-04-24  1:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, paulus
In-Reply-To: <1177374440.14873.33.camel@localhost.localdomain>

On Tue, Apr 24, 2007 at 10:27:20AM +1000, Benjamin Herrenschmidt wrote:
> On Mon, 2007-04-16 at 01:27 -0500, Olof Johansson wrote:
> > Minor HID change. Firmware can't know that we want this set so we have
> > to set it in the kernel.
> 
> Care to document/name these bits ?

Not at this time, sorry.


-Olof

^ permalink raw reply

* Re: PTE entries
From: Benjamin Herrenschmidt @ 2007-04-24  1:05 UTC (permalink / raw)
  To: Siva Prasad; +Cc: linuxppc-dev, linuxppc-embedded
In-Reply-To: <D83235F0F3C86D4D889D8B9A0DA8C6D762C6C3@corpexc01.corp.networkrobots.com>

On Thu, 2007-04-19 at 21:34 -0700, Siva Prasad wrote:
> Hi,
> 
>  
> 
> Where exactly the PTE are setup for any given new user program?
> 
>  
> 
> In other words, if you are trying to execute a user level program,
> kernel needs to load it and setup PTEs for that program. Where does
> kernel do it?

They are faulted in.

See do_page_fault

Ben.

^ permalink raw reply

* Re: [PATCH 2/2] POWERPC: Remove global CPM mappings
From: Dan Malek @ 2007-04-24  1:26 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070423223910.4955.18106.stgit@localhost.localdomain>


On Apr 23, 2007, at 6:39 PM, Vitaly Bordug wrote:

>
> Gets rid or direct IMMR accesses/dereferences for PQ SoC targets and
> relevant drivers.

Can we find a way to do this without the constant
ioremapping and unmapping?  It's a quick and
dirty hack, but it would be nice if we could map once
during an initialization, keep the pointer around
and at least use it within the file context.  I know it
doesn't cost much, but all of these cycles add up,
and someday ioremap could grow into something
more complex.  Please?

The whole of the CPM supporting functions need this,
it could be mapped once and shared at least among
them.  Any drivers that use the IMMR should also be
cleaner about managing this space as they would
any other mapped resource that is typically done
only once for the life of the driver.

There are also many different methods used that
I don't understand the reason.  Sometimes the
mappings are hidden in macros, sometimes done
in a function that is called, other times ioremap()
is called explicitly.  It just looks, well....  icky.  :-)


Thanks.

	-- Dan

^ permalink raw reply

* Re: [PATCH 6/7] MPIC MSI allocator
From: Benjamin Herrenschmidt @ 2007-04-24  1:29 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, linux-pci
In-Reply-To: <20070423035025.GA29839@lixom.net>


> It's time to rename BROKEN_U3. It used to be the config option to enable
> a few workarounds, but now it's used to select whenever there's a U3 in
> the system. Care to do it in the scope of this patch set?

Not really.... first gen G5s don't use that :-) It's wether the MPIC is
part of U3/U4 -and- is used as a primary HT PIC.

Ben.

^ permalink raw reply

* Re: [PATCH 07/10] add of_iomap function
From: Benjamin Herrenschmidt @ 2007-04-24  1:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linuxppc-dev, Paul Mackerras, Arnd Bergmann, Christian Krafft
In-Reply-To: <20070423193913.119032752@arndb.de>

On Mon, 2007-04-23 at 21:35 +0200, Arnd Bergmann wrote:
> plain text document attachment (powerpc-add-of_remap.diff)
> From: Christian Krafft <krafft@de.ibm.com>
> 
> The of_iomap function maps memory for a given
> device_node and returns a pointer to that memory.
> This is used at some places, so it makes sense to
> a seperate function.

No point in inlining it imho.

Ben.

> Signed-off-by: Christian Krafft <krafft@de.ibm.com>
> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
> 
> Index: linux-2.6/arch/powerpc/sysdev/pmi.c
> ===================================================================
> --- linux-2.6.orig/arch/powerpc/sysdev/pmi.c
> +++ linux-2.6/arch/powerpc/sysdev/pmi.c
> @@ -33,7 +33,7 @@
>  #include <asm/of_platform.h>
>  #include <asm/io.h>
>  #include <asm/pmi.h>
> -
> +#include <asm/prom.h>
>  
>  struct pmi_data {
>  	struct list_head	handler;
> @@ -49,21 +49,6 @@ struct pmi_data {
>  };
>  
> 
> -
> -static void __iomem *of_iomap(struct device_node *np)
> -{
> -	struct resource res;
> -
> -	if (of_address_to_resource(np, 0, &res))
> -		return NULL;
> -
> -	pr_debug("Resource start: 0x%lx\n", res.start);
> -	pr_debug("Resource end: 0x%lx\n", res.end);
> -
> -	return ioremap(res.start, 1 + res.end - res.start);
> -}
> -
> -
>  static int pmi_irq_handler(int irq, void *dev_id)
>  {
>  	struct pmi_data *data;
> @@ -154,7 +139,7 @@ static int pmi_of_probe(struct of_device
>  		goto out;
>  	}
>  
> -	data->pmi_reg = of_iomap(np);
> +	data->pmi_reg = of_iomap(np, 0);
>  	if (!data->pmi_reg) {
>  		printk(KERN_ERR "pmi: invalid register address.\n");
>  		rc = -EFAULT;
> Index: linux-2.6/include/asm-powerpc/prom.h
> ===================================================================
> --- linux-2.6.orig/include/asm-powerpc/prom.h
> +++ linux-2.6/include/asm-powerpc/prom.h
> @@ -20,6 +20,7 @@
>  #include <linux/platform_device.h>
>  #include <asm/irq.h>
>  #include <asm/atomic.h>
> +#include <asm/io.h>
>  
>  /* Definitions used by the flattened device tree */
>  #define OF_DT_HEADER		0xd00dfeed	/* marker */
> @@ -355,6 +356,16 @@ static inline int of_irq_to_resource(str
>  	return irq;
>  }
>  
> +static inline void __iomem *of_iomap(struct device_node *np, int index)
> +{
> +	struct resource res;
> +
> +	if (of_address_to_resource(np, index, &res))
> +		return NULL;
> +
> +	return ioremap(res.start, 1 + res.end - res.start);
> +}
> +
>  
>  #endif /* __KERNEL__ */
>  #endif /* _POWERPC_PROM_H */
> 
> --
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH] powerpc pseries eeh: Convert to kthread API
From: Benjamin Herrenschmidt @ 2007-04-24  1:38 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: <Andrew Morton, linux-s390, linux-kernel, Christoph Hellwig,
	linuxppc-dev, Paul Mackerras, Eric W. Biederman, containers,
	Oleg Nesterov
In-Reply-To: <20070423205020.GR31947@austin.ibm.com>


> The only reason for using threads here is to get the error recovery
> out of an interrupt context (where errors may be detected), and then,
> an hour later, decrement a counter (which is how we limit these to 
> 6 per hour). Thread reaping is "trivial", the thread just exits
> after an hour.

In addition, it should be a thread and not done from within keventd
because :

 - It can take a long time (well, relatively but still too long for a
work queue)

 - The driver callbacks might need to use keventd or do flush_workqueue
to synchronize with their own workqueues when doing an internal
recovery.

> Since these are events rare, I've no particular concern about
> performance or resource consumption. The current code seems 
> to work just fine. :-)

I think moving to kthread's is cleaner (just a wrapper around kernel
threads that simplify dealing with reaping them out mostly) and I agree
with Christoph that it would be nice to be able to "fire off" kthreads
from interrupt context.. in many cases, we abuse work queues for things
that should really done from kthreads instead (basically anything that
takes more than a couple hundred microsecs or so).

Ben.

^ permalink raw reply

* Re: [PATCH 08/10] cell: add support for proper device-tree
From: Benjamin Herrenschmidt @ 2007-04-24  1:48 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: linuxppc-dev, paulus, David Woodhouse, Christian Krafft
In-Reply-To: <200704240116.58364.arnd@arndb.de>

On Tue, 2007-04-24 at 01:16 +0200, Arnd Bergmann wrote:
> On Monday 23 April 2007, Arnd Bergmann wrote:
> > From: Christian Krafft <krafft@de.ibm.com>
> > 
> > This patch adds support for a proper device-tree.
> > A porper device-tree on cell contains be nodes
> > for each CBE containg nodes for SPEs and all the
> > other special devices on it.
> > Ofcourse oldschool devicetree is still supported.
> > 
> > Signed-off-by: Christian Krafft <krafft@de.ibm.com>
> > Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
> 
> Christian, I only now saw that there is this rather important
> patch left, it never stood out as something for 2.6.21 and now
> it's too late for that.
> This might explain why people could not boot some hardware
> with Fedora 7.
> 
> Should we try to get this in as a hotfix?

Please do.

Ben.

^ permalink raw reply

* Re: [PATCH] powerpc pseries eeh: Convert to kthread API
From: Eric W. Biederman @ 2007-04-24  2:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: <Andrew Morton, linux-s390, linux-kernel, Christoph Hellwig,
	linuxppc-dev, Paul Mackerras, containers, Oleg Nesterov
In-Reply-To: <1177378733.14873.52.camel@localhost.localdomain>

Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:

>> The only reason for using threads here is to get the error recovery
>> out of an interrupt context (where errors may be detected), and then,
>> an hour later, decrement a counter (which is how we limit these to 
>> 6 per hour). Thread reaping is "trivial", the thread just exits
>> after an hour.
>
> In addition, it should be a thread and not done from within keventd
> because :
>
>  - It can take a long time (well, relatively but still too long for a
> work queue)
>
>  - The driver callbacks might need to use keventd or do flush_workqueue
> to synchronize with their own workqueues when doing an internal
> recovery.
>
>> Since these are events rare, I've no particular concern about
>> performance or resource consumption. The current code seems 
>> to work just fine. :-)
>
> I think moving to kthread's is cleaner (just a wrapper around kernel
> threads that simplify dealing with reaping them out mostly) and I agree
> with Christoph that it would be nice to be able to "fire off" kthreads
> from interrupt context.. in many cases, we abuse work queues for things
> that should really done from kthreads instead (basically anything that
> takes more than a couple hundred microsecs or so).

On that note does anyone have a problem is we manage the irq spawning
safe kthreads the same way that we manage the work queue entries.

i.e. by a structure allocated by the caller?

Eric

^ permalink raw reply

* Re: [PATCH] powerpc pseries eeh: Convert to kthread API
From: Benjamin Herrenschmidt @ 2007-04-24  2:42 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: <Andrew Morton, linux-s390, linux-kernel, Christoph Hellwig,
	linuxppc-dev, Paul Mackerras, containers, Oleg Nesterov
In-Reply-To: <m1ejmav80l.fsf@ebiederm.dsl.xmission.com>

On Mon, 2007-04-23 at 20:08 -0600, Eric W. Biederman wrote:
> Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
> 
> >> The only reason for using threads here is to get the error recovery
> >> out of an interrupt context (where errors may be detected), and then,
> >> an hour later, decrement a counter (which is how we limit these to 
> >> 6 per hour). Thread reaping is "trivial", the thread just exits
> >> after an hour.
> >
> > In addition, it should be a thread and not done from within keventd
> > because :
> >
> >  - It can take a long time (well, relatively but still too long for a
> > work queue)
> >
> >  - The driver callbacks might need to use keventd or do flush_workqueue
> > to synchronize with their own workqueues when doing an internal
> > recovery.
> >
> >> Since these are events rare, I've no particular concern about
> >> performance or resource consumption. The current code seems 
> >> to work just fine. :-)
> >
> > I think moving to kthread's is cleaner (just a wrapper around kernel
> > threads that simplify dealing with reaping them out mostly) and I agree
> > with Christoph that it would be nice to be able to "fire off" kthreads
> > from interrupt context.. in many cases, we abuse work queues for things
> > that should really done from kthreads instead (basically anything that
> > takes more than a couple hundred microsecs or so).
> 
> On that note does anyone have a problem is we manage the irq spawning
> safe kthreads the same way that we manage the work queue entries.
> 
> i.e. by a structure allocated by the caller?

Not sure... I can see places where I might want to spawn an arbitrary
number of these without having to preallocate structures... and if I
allocate on the fly, then I need a way to free that structure when the
kthread is reaped which I don't think we have currently, do we ? (In
fact, I could use that for other things too now that I'm thinking of
it ... I might have a go at providing optional kthread destructors).

Ben.

^ permalink raw reply

* Re: [PATCH] DMA 4GB boundary protection
From: Olof Johansson @ 2007-04-24  3:07 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17964.42216.839568.476369@cargo.ozlabs.ibm.com>

On Mon, Apr 23, 2007 at 10:22:00PM +1000, Paul Mackerras wrote:
> Jake,
> 
> It looks like I have applied both the final version of this patch
> (569975591c5530fdc9c7a3c45122e5e46f075a74) and the original version
> (618d3adc351a24c4c48437c767befb88ca2d199d) that modified
> iommu_range_alloc().
> 
> Should I revert the original version?

(Since I didn't see a reply from Jake today):

Yes, please do. It's redundant given the better patch that went in later.


Thanks,

-Olof

^ permalink raw reply

* powerpc: Cleanup and fix breakage in tlbflush.h
From: David Gibson @ 2007-04-24  3:09 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

BenH's commit a741e67969577163a4cfc78d7fd2753219087ef1 in powerpc.git,
although (AFAICT) only intended to affect ppc64, also has side-effects
which break 44x.  I think 40x, 8xx and Freescale Book E are also
affected, though I haven't tested them.

The problem lies in unconditionally removing flush_tlb_pending() from
the versions of flush_tlb_mm(), flush_tlb_range() and
flush_tlb_kernel_range() used on ppc64 - which are also used the
embedded platforms mentioned above.


The patch below cleans up the convoluted #ifdef logic in tlbflush.h,
in the process restoring the necessary flushes for the software TLB
platforms.  There are three sets of definitions for the flushing
hooks: the software TLB versions (revised to avoid using names which
appear to related to TLB batching), the 32-bit hash based versions
(external functions) amd the 64-bit hash based versions (which
implement batching).

It also moves the declaration of update_mmu_cache() to always be in
tlbflush.h (previously it was in tlbflush.h except for PPC64, where it
was in pgtable.h).

Booted on Ebony (440GP) and compiled for 64-bit and 32-bit
multiplatform.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

---

Paul, I think this is ok to apply.  This obsoletes my earlier hackier
patch for restoring the necessary TLB flushes on 44x et al.

Index: working-2.6/include/asm-powerpc/pgtable.h
===================================================================
--- working-2.6.orig/include/asm-powerpc/pgtable.h	2007-04-24 12:47:01.000000000 +1000
+++ working-2.6/include/asm-powerpc/pgtable.h	2007-04-24 12:47:04.000000000 +1000
@@ -448,16 +448,6 @@ extern pgd_t swapper_pg_dir[];
 
 extern void paging_init(void);
 
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to put a corresponding HPTE into the hash table
- * ahead of time, instead of waiting for the inevitable extra
- * hash-table miss exception.
- */
-struct vm_area_struct;
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-
 /* Encode and de-code a swap entry */
 #define __swp_type(entry)	(((entry).val >> 1) & 0x3f)
 #define __swp_offset(entry)	((entry).val >> 8)
Index: working-2.6/include/asm-powerpc/tlbflush.h
===================================================================
--- working-2.6.orig/include/asm-powerpc/tlbflush.h	2007-04-24 12:47:01.000000000 +1000
+++ working-2.6/include/asm-powerpc/tlbflush.h	2007-04-24 12:53:31.000000000 +1000
@@ -17,10 +17,73 @@
  */
 #ifdef __KERNEL__
 
-
 struct mm_struct;
+struct vm_area_struct;
+
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE)
+/*
+ * TLB flushing for software loaded TLB chips
+ *
+ * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range &
+ * flush_tlb_kernel_range are best implemented as tlbia vs
+ * specific tlbie's
+ */
 
-#ifdef CONFIG_PPC64
+extern void _tlbie(unsigned long address);
+
+#if defined(CONFIG_40x) || defined(CONFIG_8xx)
+#define _tlbia()	asm volatile ("tlbia; sync" : : : "memory")
+#else /* CONFIG_44x || CONFIG_FSL_BOOKE */
+extern void _tlbia(void);
+#endif
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	_tlbia();
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long vmaddr)
+{
+	_tlbie(vmaddr);
+}
+
+static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
+					 unsigned long vmaddr)
+{
+	_tlbie(vmaddr);
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	_tlbia();
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	_tlbia();
+}
+
+#elif defined(CONFIG_PPC32)
+/*
+ * TLB flushing for "classic" hash-MMMU 32-bit CPUs, 6xx, 7xx, 7xxx
+ */
+extern void _tlbie(unsigned long address);
+extern void _tlbia(void);
+
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			    unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#else
+/*
+ * TLB flushing for 64-bit has-MMU CPUs
+ */
 
 #include <linux/percpu.h>
 #include <asm/page.h>
@@ -67,89 +130,51 @@ extern void flush_hash_page(unsigned lon
 			    int local);
 extern void flush_hash_range(unsigned long number, int local);
 
-#else /* CONFIG_PPC64 */
-
-#include <linux/mm.h>
-
-extern void _tlbie(unsigned long address);
-extern void _tlbia(void);
-
-/*
- * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range &
- * flush_tlb_kernel_range are best implemented as tlbia vs
- * specific tlbie's
- */
-
-#if (defined(CONFIG_4xx) && !defined(CONFIG_44x)) || defined(CONFIG_8xx)
-#define flush_tlb_pending()	asm volatile ("tlbia; sync" : : : "memory")
-#elif defined(CONFIG_4xx) || defined(CONFIG_FSL_BOOKE)
-#define flush_tlb_pending()	_tlbia()
-#endif
-
-/*
- * This gets called at the end of handling a page fault, when
- * the kernel has put a new PTE into the page table for the process.
- * We use it to ensure coherency between the i-cache and d-cache
- * for the page which has just been mapped in.
- * On machines which use an MMU hash table, we use this to put a
- * corresponding HPTE into the hash table ahead of time, instead of
- * waiting for the inevitable extra hash-table miss exception.
- */
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-
-#endif /* CONFIG_PPC64 */
-
-#if defined(CONFIG_PPC64) || defined(CONFIG_4xx) || \
-	defined(CONFIG_FSL_BOOKE) || defined(CONFIG_8xx)
 
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 }
 
 static inline void flush_tlb_page(struct vm_area_struct *vma,
-				unsigned long vmaddr)
+				  unsigned long vmaddr)
 {
-#ifndef CONFIG_PPC64
-	_tlbie(vmaddr);
-#endif
 }
 
 static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
 					 unsigned long vmaddr)
 {
-#ifndef CONFIG_PPC64
-	_tlbie(vmaddr);
-#endif
 }
 
 static inline void flush_tlb_range(struct vm_area_struct *vma,
-		unsigned long start, unsigned long end)
+				   unsigned long start, unsigned long end)
 {
 }
 
 static inline void flush_tlb_kernel_range(unsigned long start,
-		unsigned long end)
+					  unsigned long end)
 {
 }
 
-#else	/* 6xx, 7xx, 7xxx cpus */
-
-extern void flush_tlb_mm(struct mm_struct *mm);
-extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr);
-extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
-			    unsigned long end);
-extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
-
 #endif
 
 /*
+ * This gets called at the end of handling a page fault, when
+ * the kernel has put a new PTE into the page table for the process.
+ * We use it to ensure coherency between the i-cache and d-cache
+ * for the page which has just been mapped in.
+ * On machines which use an MMU hash table, we use this to put a
+ * corresponding HPTE into the hash table ahead of time, instead of
+ * waiting for the inevitable extra hash-table miss exception.
+ */
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
+/*
  * This is called in munmap when we have freed up some page-table
  * pages.  We don't need to do anything here, there's nothing special
  * about our page-table pages.  -- paulus
  */
 static inline void flush_tlb_pgtables(struct mm_struct *mm,
-		unsigned long start, unsigned long end)
+				      unsigned long start, unsigned long end)
 {
 }
 
Index: working-2.6/arch/powerpc/mm/mmu_decl.h
===================================================================
--- working-2.6.orig/arch/powerpc/mm/mmu_decl.h	2007-04-24 12:54:50.000000000 +1000
+++ working-2.6/arch/powerpc/mm/mmu_decl.h	2007-04-24 12:54:59.000000000 +1000
@@ -19,6 +19,7 @@
  *  2 of the License, or (at your option) any later version.
  *
  */
+#include <linux/mm.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu.h>
 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: powerpc: Cleanup and fix breakage in tlbflush.h
From: Benjamin Herrenschmidt @ 2007-04-24  3:14 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20070424030912.GA30007@localhost.localdomain>

On Tue, 2007-04-24 at 13:09 +1000, David Gibson wrote:
> BenH's commit a741e67969577163a4cfc78d7fd2753219087ef1 in powerpc.git,
> although (AFAICT) only intended to affect ppc64, also has side-effects
> which break 44x.  I think 40x, 8xx and Freescale Book E are also
> affected, though I haven't tested them.
> 
> The problem lies in unconditionally removing flush_tlb_pending() from
> the versions of flush_tlb_mm(), flush_tlb_range() and
> flush_tlb_kernel_range() used on ppc64 - which are also used the
> embedded platforms mentioned above.
> 
> 
> The patch below cleans up the convoluted #ifdef logic in tlbflush.h,
> in the process restoring the necessary flushes for the software TLB
> platforms.  There are three sets of definitions for the flushing
> hooks: the software TLB versions (revised to avoid using names which
> appear to related to TLB batching), the 32-bit hash based versions
> (external functions) amd the 64-bit hash based versions (which
> implement batching).
> 
> It also moves the declaration of update_mmu_cache() to always be in
> tlbflush.h (previously it was in tlbflush.h except for PPC64, where it
> was in pgtable.h).
> 
> Booted on Ebony (440GP) and compiled for 64-bit and 32-bit
> multiplatform.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
> 
> Paul, I think this is ok to apply.  This obsoletes my earlier hackier
> patch for restoring the necessary TLB flushes on 44x et al.
> 
> Index: working-2.6/include/asm-powerpc/pgtable.h
> ===================================================================
> --- working-2.6.orig/include/asm-powerpc/pgtable.h	2007-04-24 12:47:01.000000000 +1000
> +++ working-2.6/include/asm-powerpc/pgtable.h	2007-04-24 12:47:04.000000000 +1000
> @@ -448,16 +448,6 @@ extern pgd_t swapper_pg_dir[];
>  
>  extern void paging_init(void);
>  
> -/*
> - * This gets called at the end of handling a page fault, when
> - * the kernel has put a new PTE into the page table for the process.
> - * We use it to put a corresponding HPTE into the hash table
> - * ahead of time, instead of waiting for the inevitable extra
> - * hash-table miss exception.
> - */
> -struct vm_area_struct;
> -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
> -
>  /* Encode and de-code a swap entry */
>  #define __swp_type(entry)	(((entry).val >> 1) & 0x3f)
>  #define __swp_offset(entry)	((entry).val >> 8)
> Index: working-2.6/include/asm-powerpc/tlbflush.h
> ===================================================================
> --- working-2.6.orig/include/asm-powerpc/tlbflush.h	2007-04-24 12:47:01.000000000 +1000
> +++ working-2.6/include/asm-powerpc/tlbflush.h	2007-04-24 12:53:31.000000000 +1000
> @@ -17,10 +17,73 @@
>   */
>  #ifdef __KERNEL__
>  
> -
>  struct mm_struct;
> +struct vm_area_struct;
> +
> +#if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE)
> +/*
> + * TLB flushing for software loaded TLB chips
> + *
> + * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range &
> + * flush_tlb_kernel_range are best implemented as tlbia vs
> + * specific tlbie's
> + */
>  
> -#ifdef CONFIG_PPC64
> +extern void _tlbie(unsigned long address);
> +
> +#if defined(CONFIG_40x) || defined(CONFIG_8xx)
> +#define _tlbia()	asm volatile ("tlbia; sync" : : : "memory")
> +#else /* CONFIG_44x || CONFIG_FSL_BOOKE */
> +extern void _tlbia(void);
> +#endif
> +
> +static inline void flush_tlb_mm(struct mm_struct *mm)
> +{
> +	_tlbia();
> +}
> +
> +static inline void flush_tlb_page(struct vm_area_struct *vma,
> +				  unsigned long vmaddr)
> +{
> +	_tlbie(vmaddr);
> +}
> +
> +static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
> +					 unsigned long vmaddr)
> +{
> +	_tlbie(vmaddr);
> +}
> +
> +static inline void flush_tlb_range(struct vm_area_struct *vma,
> +				   unsigned long start, unsigned long end)
> +{
> +	_tlbia();
> +}
> +
> +static inline void flush_tlb_kernel_range(unsigned long start,
> +					  unsigned long end)
> +{
> +	_tlbia();
> +}
> +
> +#elif defined(CONFIG_PPC32)
> +/*
> + * TLB flushing for "classic" hash-MMMU 32-bit CPUs, 6xx, 7xx, 7xxx
> + */
> +extern void _tlbie(unsigned long address);
> +extern void _tlbia(void);
> +
> +extern void flush_tlb_mm(struct mm_struct *mm);
> +extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
> +extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr);
> +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
> +			    unsigned long end);
> +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
> +
> +#else
> +/*
> + * TLB flushing for 64-bit has-MMU CPUs
> + */
>  
>  #include <linux/percpu.h>
>  #include <asm/page.h>
> @@ -67,89 +130,51 @@ extern void flush_hash_page(unsigned lon
>  			    int local);
>  extern void flush_hash_range(unsigned long number, int local);
>  
> -#else /* CONFIG_PPC64 */
> -
> -#include <linux/mm.h>
> -
> -extern void _tlbie(unsigned long address);
> -extern void _tlbia(void);
> -
> -/*
> - * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range &
> - * flush_tlb_kernel_range are best implemented as tlbia vs
> - * specific tlbie's
> - */
> -
> -#if (defined(CONFIG_4xx) && !defined(CONFIG_44x)) || defined(CONFIG_8xx)
> -#define flush_tlb_pending()	asm volatile ("tlbia; sync" : : : "memory")
> -#elif defined(CONFIG_4xx) || defined(CONFIG_FSL_BOOKE)
> -#define flush_tlb_pending()	_tlbia()
> -#endif
> -
> -/*
> - * This gets called at the end of handling a page fault, when
> - * the kernel has put a new PTE into the page table for the process.
> - * We use it to ensure coherency between the i-cache and d-cache
> - * for the page which has just been mapped in.
> - * On machines which use an MMU hash table, we use this to put a
> - * corresponding HPTE into the hash table ahead of time, instead of
> - * waiting for the inevitable extra hash-table miss exception.
> - */
> -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
> -
> -#endif /* CONFIG_PPC64 */
> -
> -#if defined(CONFIG_PPC64) || defined(CONFIG_4xx) || \
> -	defined(CONFIG_FSL_BOOKE) || defined(CONFIG_8xx)
>  
>  static inline void flush_tlb_mm(struct mm_struct *mm)
>  {
>  }
>  
>  static inline void flush_tlb_page(struct vm_area_struct *vma,
> -				unsigned long vmaddr)
> +				  unsigned long vmaddr)
>  {
> -#ifndef CONFIG_PPC64
> -	_tlbie(vmaddr);
> -#endif
>  }
>  
>  static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
>  					 unsigned long vmaddr)
>  {
> -#ifndef CONFIG_PPC64
> -	_tlbie(vmaddr);
> -#endif
>  }
>  
>  static inline void flush_tlb_range(struct vm_area_struct *vma,
> -		unsigned long start, unsigned long end)
> +				   unsigned long start, unsigned long end)
>  {
>  }
>  
>  static inline void flush_tlb_kernel_range(unsigned long start,
> -		unsigned long end)
> +					  unsigned long end)
>  {
>  }
>  
> -#else	/* 6xx, 7xx, 7xxx cpus */
> -
> -extern void flush_tlb_mm(struct mm_struct *mm);
> -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
> -extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr);
> -extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
> -			    unsigned long end);
> -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
> -
>  #endif
>  
>  /*
> + * This gets called at the end of handling a page fault, when
> + * the kernel has put a new PTE into the page table for the process.
> + * We use it to ensure coherency between the i-cache and d-cache
> + * for the page which has just been mapped in.
> + * On machines which use an MMU hash table, we use this to put a
> + * corresponding HPTE into the hash table ahead of time, instead of
> + * waiting for the inevitable extra hash-table miss exception.
> + */
> +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
> +
> +/*
>   * This is called in munmap when we have freed up some page-table
>   * pages.  We don't need to do anything here, there's nothing special
>   * about our page-table pages.  -- paulus
>   */
>  static inline void flush_tlb_pgtables(struct mm_struct *mm,
> -		unsigned long start, unsigned long end)
> +				      unsigned long start, unsigned long end)
>  {
>  }
>  
> Index: working-2.6/arch/powerpc/mm/mmu_decl.h
> ===================================================================
> --- working-2.6.orig/arch/powerpc/mm/mmu_decl.h	2007-04-24 12:54:50.000000000 +1000
> +++ working-2.6/arch/powerpc/mm/mmu_decl.h	2007-04-24 12:54:59.000000000 +1000
> @@ -19,6 +19,7 @@
>   *  2 of the License, or (at your option) any later version.
>   *
>   */
> +#include <linux/mm.h>
>  #include <asm/tlbflush.h>
>  #include <asm/mmu.h>
>  
> 

^ permalink raw reply

* Re: [PATCH] powerpc pseries eeh: Convert to kthread API
From: Eric W. Biederman @ 2007-04-24  3:20 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: <Andrew Morton, linux-s390, linux-kernel, Christoph Hellwig,
	linuxppc-dev, Paul Mackerras, containers, Oleg Nesterov
In-Reply-To: <1177382544.14873.57.camel@localhost.localdomain>

Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:

> Not sure... I can see places where I might want to spawn an arbitrary
> number of these without having to preallocate structures... and if I
> allocate on the fly, then I need a way to free that structure when the
> kthread is reaped which I don't think we have currently, do we ? (In
> fact, I could use that for other things too now that I'm thinking of
> it ... I might have a go at providing optional kthread destructors).

Well the basic problem is that for any piece of code that can be modular
we need a way to ensure all threads it has running are shutdown when we
remove the module.

Which means a fire and forget model however simple is unfortunately
the wrong thing.

Now we might be able to wrap this in some kind of manager construct,
so you don't have to manage each thread individually, but we still
have the problem of ensuring all of the threads exit when we terminate
the module.

Further in general it doesn't make sense to grab a module reference
and call that sufficient because we would like to request that the
module exits.

Eric

^ permalink raw reply

* [PATCH 1/5] [POWERPC] Remove find_compatible_devices
From: Stephen Rothwell @ 2007-04-24  3:48 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20070413171422.c19353e2.sfr@canb.auug.org.au>

This is an old interface and is replaced by of_find_compatible_node.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/prom.c         |   24 ------------------------
 arch/powerpc/platforms/chrp/time.c |   13 +++++++++----
 drivers/macintosh/macio-adb.c      |   16 +++++++++++++---
 include/asm-powerpc/prom.h         |    2 --
 4 files changed, 22 insertions(+), 33 deletions(-)

This series of patches has been compile tested for a ppc64 allmodconfig.
They are on top of the for-2.6.22 tree plus my patch entitled "Rename
last get_property calls"

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index ec6921c..2f7e6ec 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1171,30 +1171,6 @@ int machine_is_compatible(const char *compat)
 EXPORT_SYMBOL(machine_is_compatible);
 
 /**
- * Construct and return a list of the device_nodes with a given type
- * and compatible property.
- */
-struct device_node *find_compatible_devices(const char *type,
-					    const char *compat)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		if (type != NULL
-		    && !(np->type != 0 && strcasecmp(np->type, type) == 0))
-			continue;
-		if (of_device_is_compatible(np, compat)) {
-			*prevp = np;
-			prevp = &np->next;
-		}
-	}
-	*prevp = NULL;
-	return head;
-}
-EXPORT_SYMBOL(find_compatible_devices);
-
-/**
  * Find the device_node with a given full_name.
  */
 struct device_node *find_path_device(const char *path)
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 7d78890..96d1e4b 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -39,12 +39,17 @@ long __init chrp_time_init(void)
 	struct resource r;
 	int base;
 
-	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+	rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");
 	if (rtcs == NULL)
-		rtcs = find_compatible_devices("rtc", "ds1385-rtc");
-	if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r))
+		rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc");
+	if (rtcs == NULL)
+		return 0;
+	if (of_address_to_resource(rtcs, 0, &r)) {
+		of_node_put(rtcs);
 		return 0;
-	
+	}
+	of_node_put(rtcs);
+
 	base = r.start;
 	nvram_as1 = 0;
 	nvram_as0 = base;
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index 026b67f..79119f5 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -82,7 +82,14 @@ struct adb_driver macio_adb_driver = {
 
 int macio_probe(void)
 {
-	return find_compatible_devices("adb", "chrp,adb0")? 0: -ENODEV;
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, "adb", "chrp,adb0");
+	if (np) {
+		of_node_put(np);
+		return 0;
+	}
+	return -ENODEV;
 }
 
 int macio_init(void)
@@ -91,12 +98,14 @@ int macio_init(void)
 	struct resource r;
 	unsigned int irq;
 
-	adbs = find_compatible_devices("adb", "chrp,adb0");
+	adbs = of_find_compatible_node(NULL, "adb", "chrp,adb0");
 	if (adbs == 0)
 		return -ENXIO;
 
-	if (of_address_to_resource(adbs, 0, &r))
+	if (of_address_to_resource(adbs, 0, &r)) {
+		of_node_put(adbs);
 		return -ENXIO;
+	}
 	adb = ioremap(r.start, sizeof(struct adb_regs));
 
 	out_8(&adb->ctrl.r, 0);
@@ -107,6 +116,7 @@ int macio_init(void)
 	out_8(&adb->autopoll.r, APE);
 
 	irq = irq_of_parse_and_map(adbs, 0);
+	of_node_put(adbs);
 	if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) {
 		printk(KERN_ERR "ADB: can't get irq %d\n", irq);
 		return -EAGAIN;
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index e73a2b4..c2bb8b5 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -115,8 +115,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
 extern struct device_node *find_devices(const char *name);
 extern struct device_node *find_type_devices(const char *type);
 extern struct device_node *find_path_device(const char *path);
-extern struct device_node *find_compatible_devices(const char *type,
-						   const char *compat);
 extern struct device_node *find_all_nodes(void);
 
 /* New style node lookup */
-- 
1.5.1.1

^ permalink raw reply related

* [PATCH 2/5] [POWERPC] remove find_all_nodes
From: Stephen Rothwell @ 2007-04-24  3:49 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20070424134841.cee3ff4e.sfr@canb.auug.org.au>

This old interface has no more users.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/prom.c |   17 -----------------
 include/asm-powerpc/prom.h |    1 -
 2 files changed, 0 insertions(+), 18 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 2f7e6ec..911ec77 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1110,23 +1110,6 @@ struct device_node *find_type_devices(const char *type)
 }
 EXPORT_SYMBOL(find_type_devices);
 
-/**
- * Returns all nodes linked together
- */
-struct device_node *find_all_nodes(void)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		*prevp = np;
-		prevp = &np->next;
-	}
-	*prevp = NULL;
-	return head;
-}
-EXPORT_SYMBOL(find_all_nodes);
-
 /** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index c2bb8b5..38f7c3e 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -115,7 +115,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
 extern struct device_node *find_devices(const char *name);
 extern struct device_node *find_type_devices(const char *type);
 extern struct device_node *find_path_device(const char *path);
-extern struct device_node *find_all_nodes(void);
 
 /* New style node lookup */
 extern struct device_node *of_find_node_by_name(struct device_node *from,
-- 
1.5.1.1

^ permalink raw reply related

* [PATCH 3/5] [POWERPC] Remove old interface find_path_device
From: Stephen Rothwell @ 2007-04-24  3:50 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20070424134841.cee3ff4e.sfr@canb.auug.org.au>

Replaced by of_find_node_by_path.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/lparcfg.c             |    6 +++-
 arch/powerpc/kernel/pci_32.c              |   17 ++++++++++----
 arch/powerpc/kernel/prom.c                |   14 ------------
 arch/powerpc/kernel/rtas.c                |    3 +-
 arch/powerpc/kernel/sysfs.c               |    3 +-
 arch/powerpc/platforms/chrp/pci.c         |    7 +++--
 arch/powerpc/platforms/chrp/setup.c       |    9 +++++--
 arch/powerpc/platforms/powermac/feature.c |   34 +++++++++++++++++++---------
 drivers/char/briq_panel.c                 |    7 ++++-
 drivers/scsi/ibmvscsi/ibmvstgt.c          |    3 +-
 drivers/scsi/ibmvscsi/rpa_vscsi.c         |    3 +-
 include/asm-powerpc/prom.h                |    1 -
 12 files changed, 62 insertions(+), 45 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index b8dc1ee..fc1f7a9 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -321,7 +321,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
 	struct device_node *rtas_node;
 	const int *lrdrp = NULL;
 
-	rtas_node = find_path_device("/rtas");
+	rtas_node = of_find_node_by_path("/rtas");
 	if (rtas_node)
 		lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL);
 
@@ -330,6 +330,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
 	} else {
 		partition_potential_processors = *(lrdrp + 4);
 	}
+	of_node_put(rtas_node);
 
 	partition_active_processors = lparcfg_count_active_processors();
 
@@ -537,7 +538,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
 
 	seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
 
-	rootdn = find_path_device("/");
+	rootdn = of_find_node_by_path("/");
 	if (rootdn) {
 		tmp = of_get_property(rootdn, "model", NULL);
 		if (tmp) {
@@ -557,6 +558,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
 					NULL);
 		if (lp_index_ptr)
 			lp_index = *lp_index_ptr;
+		of_node_put(rootdn);
 	}
 	seq_printf(m, "serial_number=%s\n", system_id);
 	seq_printf(m, "system_type=%s\n", model);
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index ae04f94..5b05a09 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -669,6 +669,7 @@ pcibios_make_OF_bus_map(void)
 	int i;
 	struct pci_controller* hose;
 	struct property *map_prop;
+	struct device_node *dn;
 
 	pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL);
 	if (!pci_to_OF_bus_map) {
@@ -690,12 +691,13 @@ pcibios_make_OF_bus_map(void)
 			continue;
 		make_one_node_map(node, hose->first_busno);
 	}
-	map_prop = of_find_property(find_path_device("/"),
-			"pci-OF-bus-map", NULL);
+	dn = of_find_node_by_path("/");
+	map_prop = of_find_property(dn, "pci-OF-bus-map", NULL);
 	if (map_prop) {
 		BUG_ON(pci_bus_count > map_prop->length);
 		memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
 	}
+	of_node_put(dn);
 #ifdef DEBUG
 	printk("PCI->OF bus map:\n");
 	for (i=0; i<pci_bus_count; i++) {
@@ -1006,14 +1008,19 @@ void __init
 pci_create_OF_bus_map(void)
 {
 	struct property* of_prop;
-	
+	struct device_node *dn;
+
 	of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
-	if (of_prop && find_path_device("/")) {
+	if (!of_prop)
+		return;
+	dn = of_find_node_by_path("/");
+	if (dn) {
 		memset(of_prop, -1, sizeof(struct property) + 256);
 		of_prop->name = "pci-OF-bus-map";
 		of_prop->length = 256;
 		of_prop->value = &of_prop[1];
-		prom_add_property(find_path_device("/"), of_prop);
+		prom_add_property(dn, of_prop);
+		of_node_put(dn);
 	}
 }
 
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 911ec77..17c41fe 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1153,20 +1153,6 @@ int machine_is_compatible(const char *compat)
 }
 EXPORT_SYMBOL(machine_is_compatible);
 
-/**
- * Find the device_node with a given full_name.
- */
-struct device_node *find_path_device(const char *path)
-{
-	struct device_node *np;
-
-	for (np = allnodes; np != 0; np = np->allnext)
-		if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
-			return np;
-	return NULL;
-}
-EXPORT_SYMBOL(find_path_device);
-
 /*******
  *
  * New implementation of the OF "find" APIs, return a refcounted
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 702fecc..2147807 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -192,7 +192,7 @@ void rtas_progress(char *s, unsigned short hex)
 
 	if (display_width == 0) {
 		display_width = 0x10;
-		if ((root = find_path_device("/rtas"))) {
+		if ((root = of_find_node_by_path("/rtas"))) {
 			if ((p = of_get_property(root,
 					"ibm,display-line-length", NULL)))
 				display_width = *p;
@@ -204,6 +204,7 @@ void rtas_progress(char *s, unsigned short hex)
 				display_lines = *p;
 			row_width = of_get_property(root,
 					"ibm,display-truncation-length", NULL);
+			of_node_put(root);
 		}
 		display_character = rtas_token("display-character");
 		set_indicator = rtas_token("set-indicator");
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 476f1d5..fe329d6 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -66,7 +66,7 @@ static int __init smt_setup(void)
 	if (!cpu_has_feature(CPU_FTR_SMT))
 		return -ENODEV;
 
-	options = find_path_device("/options");
+	options = of_find_node_by_path("/options");
 	if (!options)
 		return -ENODEV;
 
@@ -76,6 +76,7 @@ static int __init smt_setup(void)
 			per_cpu(smt_snooze_delay, cpu) = *val;
 	}
 
+	of_node_put(options);
 	return 0;
 }
 __initcall(smt_setup);
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index b23e397..de776e3 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -185,10 +185,9 @@ setup_python(struct pci_controller *hose, struct device_node *dev)
 /* Marvell Discovery II based Pegasos 2 */
 static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev)
 {
-	struct device_node *root = find_path_device("/");
+	struct device_node *root = of_find_node_by_path("/");
 	struct device_node *rtas;
 
-	of_node_get(root);
 	rtas = of_find_node_by_name (root, "rtas");
 	if (rtas) {
 		hose->ops = &rtas_pci_ops;
@@ -198,6 +197,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
 			" your firmware\n");
 	}
 	pci_assign_all_buses = 1;
+	/* keep the reference to the root node */
 }
 
 void __init
@@ -210,7 +210,7 @@ chrp_find_bridges(void)
 	const unsigned int *dma;
 	const char *model, *machine;
 	int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
-	struct device_node *root = find_path_device("/");
+	struct device_node *root = of_find_node_by_path("/");
 	struct resource r;
 	/*
 	 * The PCI host bridge nodes on some machines don't have
@@ -309,6 +309,7 @@ chrp_find_bridges(void)
 			printk("pci_dram_offset = %lx\n", pci_dram_offset);
 		}
 	}
+	of_node_put(root);
 }
 
 /* SL82C105 IDE Control/Status Register */
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 05d1bc0..e46c4d4 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -110,7 +110,7 @@ void chrp_show_cpuinfo(struct seq_file *m)
 	struct device_node *root;
 	const char *model = "";
 
-	root = find_path_device("/");
+	root = of_find_node_by_path("/");
 	if (root)
 		model = of_get_property(root, "model", NULL);
 	seq_printf(m, "machine\t\t: CHRP %s\n", model);
@@ -160,6 +160,7 @@ void chrp_show_cpuinfo(struct seq_file *m)
 			   gg2_cachetypes[(t>>2) & 3],
 			   gg2_cachemodes[t & 3]);
 	}
+	of_node_put(root);
 }
 
 /*
@@ -204,7 +205,7 @@ static void __init sio_init(void)
 {
 	struct device_node *root;
 
-	if ((root = find_path_device("/")) &&
+	if ((root = of_find_node_by_path("/")) &&
 	    !strncmp(of_get_property(root, "model", NULL),
 			"IBM,LongTrail", 13)) {
 		/* logical device 0 (KBC/Keyboard) */
@@ -212,6 +213,7 @@ static void __init sio_init(void)
 		/* select logical device 1 (KBC/Mouse) */
 		sio_fixup_irq("mouse", 1, 12, 2);
 	}
+	of_node_put(root);
 }
 
 
@@ -250,7 +252,7 @@ static void briq_restart(char *cmd)
 
 void __init chrp_setup_arch(void)
 {
-	struct device_node *root = find_path_device ("/");
+	struct device_node *root = of_find_node_by_path("/");
 	const char *machine = NULL;
 
 	/* init to some ~sane value until calibrate_delay() runs */
@@ -273,6 +275,7 @@ void __init chrp_setup_arch(void)
 		/* Let's assume it is an IBM chrp if all else fails */
 		_chrp_type = _CHRP_IBM;
 	}
+	of_node_put(root);
 	printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]);
 
 	rtas_initialize();
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 103fcc4..44f8550 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -1044,6 +1044,7 @@ core99_reset_cpu(struct device_node *node, long param, long value)
 	unsigned long flags;
 	struct macio_chip *macio;
 	struct device_node *np;
+	struct device_node *cpus;
 	const int dflt_reset_lines[] = {	KL_GPIO_RESET_CPU0,
 						KL_GPIO_RESET_CPU1,
 						KL_GPIO_RESET_CPU2,
@@ -1053,10 +1054,10 @@ core99_reset_cpu(struct device_node *node, long param, long value)
 	if (macio->type != macio_keylargo)
 		return -ENODEV;
 
-	np = find_path_device("/cpus");
-	if (np == NULL)
+	cpus = of_find_node_by_path("/cpus");
+	if (cpus == NULL)
 		return -ENODEV;
-	for (np = np->child; np != NULL; np = np->sibling) {
+	for (np = cpus->child; np != NULL; np = np->sibling) {
 		const u32 *num = of_get_property(np, "reg", NULL);
 		const u32 *rst = of_get_property(np, "soft-reset", NULL);
 		if (num == NULL || rst == NULL)
@@ -1066,6 +1067,7 @@ core99_reset_cpu(struct device_node *node, long param, long value)
 			break;
 		}
 	}
+	of_node_put(cpus);
 	if (np == NULL || reset_io == 0)
 		reset_io = dflt_reset_lines[param];
 
@@ -1497,15 +1499,16 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
 	unsigned long flags;
 	struct macio_chip *macio;
 	struct device_node *np;
+	struct device_node *cpus;
 
 	macio = &macio_chips[0];
 	if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
 		return -ENODEV;
 
-	np = find_path_device("/cpus");
-	if (np == NULL)
+	cpus = of_find_node_by_path("/cpus");
+	if (cpus == NULL)
 		return -ENODEV;
-	for (np = np->child; np != NULL; np = np->sibling) {
+	for (np = cpus->child; np != NULL; np = np->sibling) {
 		const u32 *num = of_get_property(np, "reg", NULL);
 		const u32 *rst = of_get_property(np, "soft-reset", NULL);
 		if (num == NULL || rst == NULL)
@@ -1515,6 +1518,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
 			break;
 		}
 	}
+	of_node_put(cpus);
 	if (np == NULL || reset_io == 0)
 		return -ENODEV;
 
@@ -2499,18 +2503,26 @@ found:
 	 * that all Apple OF revs did it properly, I do it the paranoid way.
 	 */
 	while (uninorth_base && uninorth_rev > 3) {
-		struct device_node *np = find_path_device("/cpus");
-		if (!np || !np->child) {
+		struct device_node *cpus = of_find_node_by_path("/cpus");
+		struct device_node *np;
+
+		if (!cpus || !cpus->child) {
 			printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
+			of_node_put(cpus);
 			break;
 		}
-		np = np->child;
+		np = cpus->child;
 		/* Nap mode not supported on SMP */
-		if (np->sibling)
+		if (np->sibling) {
+			of_node_put(cpus);
 			break;
+		}
 		/* Nap mode not supported if flush-on-lock property is present */
-		if (of_get_property(np, "flush-on-lock", NULL))
+		if (of_get_property(np, "flush-on-lock", NULL)) {
+			of_node_put(cpus);
 			break;
+		}
+		of_node_put(cpus);
 		powersave_nap = 1;
 		printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
 		break;
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index 669965a..ed53f54 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -202,13 +202,16 @@ static struct miscdevice briq_panel_miscdev = {
 
 static int __init briq_panel_init(void)
 {
-	struct device_node *root = find_path_device("/");
+	struct device_node *root = of_find_node_by_path("/");
 	const char *machine;
 	int i;
 
 	machine = of_get_property(root, "model", NULL);
-	if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0)
+	if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) {
+		of_node_put(root);
 		return -ENODEV;
+	}
+	of_node_put(root);
 
 	printk(KERN_INFO
 		"briq_panel: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n",
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index 3fe831c..140dd97 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -899,7 +899,7 @@ static int get_system_info(void)
 	const char *id, *model, *name;
 	const unsigned int *num;
 
-	rootdn = find_path_device("/");
+	rootdn = of_find_node_by_path("/");
 	if (!rootdn)
 		return -ENOENT;
 
@@ -916,6 +916,7 @@ static int get_system_info(void)
 	if (num)
 		partition_number = *num;
 
+	of_node_put(rootdn);
 	return 0;
 }
 
diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
index 9bbb69c..d8700aa 100644
--- a/drivers/scsi/ibmvscsi/rpa_vscsi.c
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c
@@ -157,7 +157,7 @@ static void gather_partition_info(void)
 	const unsigned int *p_number_ptr;
 
 	/* Retrieve information about this partition */
-	rootdn = find_path_device("/");
+	rootdn = of_find_node_by_path("/");
 	if (!rootdn) {
 		return;
 	}
@@ -169,6 +169,7 @@ static void gather_partition_info(void)
 	p_number_ptr = of_get_property(rootdn, "ibm,partition-no", NULL);
 	if (p_number_ptr)
 		partition_number = *p_number_ptr;
+	of_node_put(rootdn);
 }
 
 static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 38f7c3e..7c510a7 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -114,7 +114,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
 /* OBSOLETE: Old style node lookup */
 extern struct device_node *find_devices(const char *name);
 extern struct device_node *find_type_devices(const char *type);
-extern struct device_node *find_path_device(const char *path);
 
 /* New style node lookup */
 extern struct device_node *of_find_node_by_name(struct device_node *from,
-- 
1.5.1.1

^ permalink raw reply related

* [PATCH 4/5] [POWERPC] Remove old interface find_type_devices
From: Stephen Rothwell @ 2007-04-24  3:51 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20070424134841.cee3ff4e.sfr@canb.auug.org.au>

Replaced by of_find_node_by_type.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/prom.c                   |   19 -------------------
 arch/powerpc/platforms/chrp/setup.c          |    6 ++++--
 arch/powerpc/platforms/powermac/cpufreq_32.c |    3 ++-
 arch/powerpc/platforms/powermac/setup.c      |    5 +++--
 drivers/macintosh/via-pmu.c                  |    5 ++++-
 include/asm-powerpc/prom.h                   |    1 -
 6 files changed, 13 insertions(+), 26 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 17c41fe..860c88b 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1091,25 +1091,6 @@ struct device_node *find_devices(const char *name)
 }
 EXPORT_SYMBOL(find_devices);
 
-/**
- * Construct and return a list of the device_nodes with a given type.
- */
-struct device_node *find_type_devices(const char *type)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		if (np->type != 0 && strcasecmp(np->type, type) == 0) {
-			*prevp = np;
-			prevp = &np->next;
-		}
-	}
-	*prevp = NULL;
-	return head;
-}
-EXPORT_SYMBOL(find_type_devices);
-
 /** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index e46c4d4..9c1b231 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -226,12 +226,12 @@ static void __init pegasos_set_l2cr(void)
 		return;
 
 	/* Enable L2 cache if needed */
-	np = find_type_devices("cpu");
+	np = of_find_node_by_type(NULL, "cpu");
 	if (np != NULL) {
 		const unsigned int *l2cr = of_get_property(np, "l2cr", NULL);
 		if (l2cr == NULL) {
 			printk ("Pegasos l2cr : no cpu l2cr property found\n");
-			return;
+			goto out;
 		}
 		if (!((*l2cr) & 0x80000000)) {
 			printk ("Pegasos l2cr : L2 cache was not active, "
@@ -240,6 +240,8 @@ static void __init pegasos_set_l2cr(void)
 			_set_L2CR((*l2cr) | 0x80000000);
 		}
 	}
+out:
+	of_node_put(np);
 }
 
 static void briq_restart(char *cmd)
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 76eda9f..8943a94 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -658,7 +658,7 @@ static int __init pmac_cpufreq_setup(void)
 		return 0;
 
 	/* Assume only one CPU */
-	cpunode = find_type_devices("cpu");
+	cpunode = of_find_node_by_type(NULL, "cpu");
 	if (!cpunode)
 		goto out;
 
@@ -708,6 +708,7 @@ static int __init pmac_cpufreq_setup(void)
 	else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
 		pmac_cpufreq_init_750FX(cpunode);
 out:
+	of_node_put(cpunode);
 	if (set_speed_proc == NULL)
 		return -ENODEV;
 
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 8c96f24..ae37d3e 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -250,9 +250,9 @@ static void __init l2cr_init(void)
 {
 	/* Checks "l2cr-value" property in the registry */
 	if (cpu_has_feature(CPU_FTR_L2CR)) {
-		struct device_node *np = find_devices("cpus");
+		struct device_node *np = of_find_node_by_name(NULL, "cpus");
 		if (np == 0)
-			np = find_type_devices("cpu");
+			np = of_find_node_by_type(NULL, "cpu");
 		if (np != 0) {
 			const unsigned int *l2cr =
 				of_get_property(np, "l2cr-value", NULL);
@@ -262,6 +262,7 @@ static void __init l2cr_init(void)
 				_set_L2CR(0);
 				_set_L2CR(ppc_override_l2cr_value);
 			}
+			of_node_put(np);
 		}
 	}
 
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 75623fd..7b7db5d 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -319,10 +319,13 @@ int __init find_via_pmu(void)
 	else if (device_is_compatible(vias->parent, "Keylargo")
 		 || device_is_compatible(vias->parent, "K2-Keylargo")) {
 		struct device_node *gpiop;
+		struct device_node *adbp;
 		u64 gaddr = OF_BAD_ADDR;
 
 		pmu_kind = PMU_KEYLARGO_BASED;
-		pmu_has_adb = (find_type_devices("adb") != NULL);
+		adbp = of_find_node_by_type(NULL, "adb");
+		pmu_has_adb = (adbp != NULL);
+		of_node_put(adbp);
 		pmu_intr_mask =	PMU_INT_PCEJECT |
 				PMU_INT_SNDBRT |
 				PMU_INT_ADB |
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 7c510a7..052b613 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -113,7 +113,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
 
 /* OBSOLETE: Old style node lookup */
 extern struct device_node *find_devices(const char *name);
-extern struct device_node *find_type_devices(const char *type);
 
 /* New style node lookup */
 extern struct device_node *of_find_node_by_name(struct device_node *from,
-- 
1.5.1.1

^ permalink raw reply related

* [PATCH 5/5] [POWERPC] Remove old interface find_devices
From: Stephen Rothwell @ 2007-04-24  3:53 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20070424134841.cee3ff4e.sfr@canb.auug.org.au>

Replace uses with of_find_node_by_name and for_each_node_by_name.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/prom.c                  |   19 ------
 arch/powerpc/kernel/vio.c                   |    3 +-
 arch/powerpc/platforms/chrp/pci.c           |    6 +-
 arch/powerpc/platforms/chrp/setup.c         |    9 ++-
 arch/powerpc/platforms/powermac/backlight.c |    7 ++-
 arch/powerpc/platforms/powermac/feature.c   |   45 +++++++------
 arch/powerpc/platforms/powermac/pci.c       |   23 ++++---
 arch/powerpc/platforms/powermac/setup.c     |   25 ++++++-
 arch/powerpc/platforms/powermac/smp.c       |    5 +-
 drivers/macintosh/ans-lcd.c                 |    9 ++-
 drivers/macintosh/via-pmu.c                 |    4 +-
 drivers/media/video/planb.c                 |    5 +-
 drivers/serial/pmac_zilog.c                 |    4 +-
 drivers/video/controlfb.c                   |   16 +++--
 include/asm-powerpc/prom.h                  |    3 -
 sound/oss/dmasound/dmasound_awacs.c         |   90 +++++++++++++++++---------
 sound/oss/dmasound/tas_common.c             |    5 +-
 sound/ppc/pmac.c                            |   27 +++++---
 sound/ppc/tumbler.c                         |   35 +++++++---
 19 files changed, 206 insertions(+), 134 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 860c88b..caef555 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1072,25 +1072,6 @@ int of_n_size_cells(struct device_node* np)
 }
 EXPORT_SYMBOL(of_n_size_cells);
 
-/**
- * Construct and return a list of the device_nodes with a given name.
- */
-struct device_node *find_devices(const char *name)
-{
-	struct device_node *head, **prevp, *np;
-
-	prevp = &head;
-	for (np = allnodes; np != 0; np = np->allnext) {
-		if (np->name != 0 && strcasecmp(np->name, name) == 0) {
-			*prevp = np;
-			prevp = &np->next;
-		}
-	}
-	*prevp = NULL;
-	return head;
-}
-EXPORT_SYMBOL(find_devices);
-
 /** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
  */
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index a09277a..9eaefac 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -308,7 +308,7 @@ static int __init vio_bus_init(void)
 		return err;
 	}
 
-	node_vroot = find_devices("vdevice");
+	node_vroot = of_find_node_by_name(NULL, "vdevice");
 	if (node_vroot) {
 		struct device_node *of_node;
 
@@ -322,6 +322,7 @@ static int __init vio_bus_init(void)
 					__FUNCTION__, of_node);
 			vio_register_device_node(of_node);
 		}
+		of_node_put(node_vroot);
 	}
 
 	return 0;
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index de776e3..1469d64 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -136,9 +136,11 @@ hydra_init(void)
 	struct device_node *np;
 	struct resource r;
 
-	np = find_devices("mac-io");
-	if (np == NULL || of_address_to_resource(np, 0, &r))
+	np = of_find_node_by_name(NULL, "mac-io");
+	if (np == NULL || of_address_to_resource(np, 0, &r)) {
+		of_node_put(np);
 		return 0;
+	}
 	Hydra = ioremap(r.start, r.end-r.start);
 	printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start);
 	printk("Hydra Feature_Control was %x",
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 9c1b231..1870038 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -468,7 +468,7 @@ static void __init chrp_find_8259(void)
 	 * Also, Pegasos-type platforms don't have a proper node to start
 	 * from anyway
 	 */
-	for (np = find_devices("pci"); np != NULL; np = np->next) {
+	for_each_node_by_name(np, "pci") {
 		const unsigned int *addrp = of_get_property(np,
 				"8259-interrupt-acknowledge", NULL);
 
@@ -477,6 +477,7 @@ static void __init chrp_find_8259(void)
 		chrp_int_ack = addrp[of_n_addr_cells(np)-1];
 		break;
 	}
+	of_node_put(np);
 	if (np == NULL)
 		printk(KERN_WARNING "Cannot find PCI interrupt acknowledge"
 		       " address, polling\n");
@@ -518,10 +519,11 @@ void __init chrp_init_IRQ(void)
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON)
 	/* see if there is a keyboard in the device tree
 	   with a parent of type "adb" */
-	for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+	for_each_node_by_name(kbd, "keyboard")
 		if (kbd->parent && kbd->parent->type
 		    && strcmp(kbd->parent->type, "adb") == 0)
 			break;
+	of_node_put(kbd);
 	if (kbd)
 		setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction);
 #endif
@@ -547,7 +549,7 @@ chrp_init2(void)
 	/* Get the event scan rate for the rtas so we know how
 	 * often it expects a heartbeat. -- Cort
 	 */
-	device = find_devices("rtas");
+	device = of_find_node_by_name(NULL, "rtas");
 	if (device)
 		p = of_get_property(device, "rtas-event-scan-rate", NULL);
 	if (p && *p) {
@@ -576,6 +578,7 @@ chrp_init2(void)
 		printk("RTAS Event Scan Rate: %u (%lu jiffies)\n",
 		       *p, interval);
 	}
+	of_node_put(device);
 
 	if (ppc_md.progress)
 		ppc_md.progress("  Have fun!    ", 0x7777);
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index 0dc8a45..d679964 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -56,13 +56,16 @@ struct backlight_device *pmac_backlight;
 
 int pmac_has_backlight_type(const char *type)
 {
-	struct device_node* bk_node = find_devices("backlight");
+	struct device_node* bk_node = of_find_node_by_name(NULL, "backlight");
 
 	if (bk_node) {
 		const char *prop = of_get_property(bk_node,
 				"backlight-control", NULL);
-		if (prop && strncmp(prop, type, strlen(type)) == 0)
+		if (prop && strncmp(prop, type, strlen(type)) == 0) {
+			of_node_put(bk_node);
 			return 1;
+		}
+		of_node_put(bk_node);
 	}
 
 	return 0;
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index 44f8550..52cfdd8 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2408,12 +2408,13 @@ static int __init probe_motherboard(void)
 	struct macio_chip *macio = &macio_chips[0];
 	const char *model = NULL;
 	struct device_node *dt;
+	int ret = 0;
 
 	/* Lookup known motherboard type in device-tree. First try an
 	 * exact match on the "model" property, then try a "compatible"
 	 * match is none is found.
 	 */
-	dt = find_devices("device-tree");
+	dt = of_find_node_by_name(NULL, "device-tree");
 	if (dt != NULL)
 		model = of_get_property(dt, "model", NULL);
 	for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
@@ -2478,15 +2479,18 @@ static int __init probe_motherboard(void)
 		break;
 #endif /* CONFIG_POWER4 */
 	default:
-		return -ENODEV;
+		ret = -ENODEV;
+		goto done;
 	}
 found:
 #ifndef CONFIG_POWER4
 	/* Fixup Hooper vs. Comet */
 	if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
 		u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
-		if (!mach_id_ptr)
-			return -ENODEV;
+		if (!mach_id_ptr) {
+			ret = -ENODEV;
+			goto done;
+		}
 		/* Here, I used to disable the media-bay on comet. It
 		 * appears this is wrong, the floppy connector is actually
 		 * a kind of media-bay and works with the current driver.
@@ -2544,7 +2548,9 @@ found:
 
 
 	printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
-	return 0;
+done:
+	of_node_put(dt);
+	return ret;
 }
 
 /* Initialize the Core99 UniNorth host bridge and memory controller
@@ -2747,12 +2753,14 @@ set_initial_features(void)
 	 * differenciate them all and since that hack was there for a long
 	 * time, I'll keep it around
 	 */
-	if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
-		struct macio_chip *macio = &macio_chips[0];
-		MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
-	} else if (macio_chips[0].type == macio_ohare) {
+	if (macio_chips[0].type == macio_ohare) {
 		struct macio_chip *macio = &macio_chips[0];
-		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+		np = of_find_node_by_name(NULL, "via-pmu");
+		if (np)
+			MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+		else
+			MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
+		of_node_put(np);
 	} else if (macio_chips[1].type == macio_ohare) {
 		struct macio_chip *macio = &macio_chips[1];
 		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
@@ -2845,14 +2853,13 @@ set_initial_features(void)
 		}
 
 		/* Switch airport off */
-		np = find_devices("radio");
-		while(np) {
+		for_each_node_by_name(np, "radio") {
 			if (np && np->parent == macio_chips[0].of_node) {
 				macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
 				core99_airport_enable(np, 0, 0);
 			}
-			np = np->next;
 		}
+		of_node_put(np);
 	}
 
 	/* On all machines that support sound PM, switch sound off */
@@ -2872,16 +2879,12 @@ set_initial_features(void)
 #endif /* CONFIG_POWER4 */
 
 	/* On all machines, switch modem & serial ports off */
-	np = find_devices("ch-a");
-	while(np) {
+	for_each_node_by_name(np, "ch-a")
 		initial_serial_shutdown(np);
-		np = np->next;
-	}
-	np = find_devices("ch-b");
-	while(np) {
+	of_node_put(np);
+	for_each_node_by_name(np, "ch-b")
 		initial_serial_shutdown(np);
-		np = np->next;
-	}
+	of_node_put(np);
 }
 
 void __init
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 092cef4..22c4ae4 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -622,13 +622,14 @@ static void __init init_p2pbridge(void)
 
 	/* XXX it would be better here to identify the specific
 	   PCI-PCI bridge chip we have. */
-	if ((p2pbridge = find_devices("pci-bridge")) == 0
+	p2pbridge = of_find_node_by_name(NULL, "pci-bridge");
+	if (p2pbridge == NULL
 	    || p2pbridge->parent == NULL
 	    || strcmp(p2pbridge->parent->name, "pci") != 0)
-		return;
+		goto done;
 	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
 		DBG("Can't find PCI infos for PCI<->PCI bridge\n");
-		return;
+		goto done;
 	}
 	/* Warning: At this point, we have not yet renumbered all busses.
 	 * So we must use OF walking to find out hose
@@ -636,16 +637,18 @@ static void __init init_p2pbridge(void)
 	hose = pci_find_hose_for_OF_device(p2pbridge);
 	if (!hose) {
 		DBG("Can't find hose for PCI<->PCI bridge\n");
-		return;
+		goto done;
 	}
 	if (early_read_config_word(hose, bus, devfn,
 				   PCI_BRIDGE_CONTROL, &val) < 0) {
 		printk(KERN_ERR "init_p2pbridge: couldn't read bridge"
 		       " control\n");
-		return;
+		goto done;
 	}
 	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
 	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
+done:
+	of_node_put(p2pbridge);
 }
 
 static void __init init_second_ohare(void)
@@ -1199,8 +1202,7 @@ void __init pmac_pcibios_after_init(void)
 	}
 #endif /* CONFIG_BLK_DEV_IDE */
 
-	nd = find_devices("firewire");
-	while (nd) {
+	for_each_node_by_name(nd, "firewire") {
 		if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
 				   device_is_compatible(nd, "pci106b,30") ||
 				   device_is_compatible(nd, "pci11c1,5811"))
@@ -1208,15 +1210,14 @@ void __init pmac_pcibios_after_init(void)
 			pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
 			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
 		}
-		nd = nd->next;
 	}
-	nd = find_devices("ethernet");
-	while (nd) {
+	of_node_put(nd);
+	for_each_node_by_name(nd, "ethernet") {
 		if (nd->parent && device_is_compatible(nd, "gmac")
 		    && device_is_compatible(nd->parent, "uni-north"))
 			pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
-		nd = nd->next;
 	}
+	of_node_put(nd);
 }
 
 #ifdef CONFIG_PPC32
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index ae37d3e..0444e07 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -193,8 +193,11 @@ static void pmac_show_cpuinfo(struct seq_file *m)
 #ifndef CONFIG_ADB_CUDA
 int find_via_cuda(void)
 {
-	if (!find_devices("via-cuda"))
+	struct device_node *dn = of_find_node_by_name(NULL, "via-cuda");
+
+	if (!dn)
 		return 0;
+	of_node_put(dn);
 	printk("WARNING ! Your machine is CUDA-based but your kernel\n");
 	printk("          wasn't compiled with CONFIG_ADB_CUDA option !\n");
 	return 0;
@@ -204,8 +207,11 @@ int find_via_cuda(void)
 #ifndef CONFIG_ADB_PMU
 int find_via_pmu(void)
 {
-	if (!find_devices("via-pmu"))
+	struct device_node *dn = of_find_node_by_name(NULL, "via-pmu");
+
+	if (!dn)
 		return 0;
+	of_node_put(dn);
 	printk("WARNING ! Your machine is PMU-based but your kernel\n");
 	printk("          wasn't compiled with CONFIG_ADB_PMU option !\n");
 	return 0;
@@ -225,6 +231,8 @@ static volatile u32 *sysctrl_regs;
 
 static void __init ohare_init(void)
 {
+	struct device_node *dn;
+
 	/* this area has the CPU identification register
 	   and some registers used by smp boards */
 	sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
@@ -234,7 +242,9 @@ static void __init ohare_init(void)
 	 * We assume that we have a PSX memory controller iff
 	 * we have an ohare I/O controller.
 	 */
-	if (find_devices("ohare") != NULL) {
+	dn = of_find_node_by_name(NULL, "ohare");
+	if (dn) {
+		of_node_put(dn);
 		if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
 			if (sysctrl_regs[4] & 0x10)
 				sysctrl_regs[4] |= 0x04000020;
@@ -343,8 +353,15 @@ static void __init pmac_setup_arch(void)
 
 #ifdef CONFIG_SMP
 	/* Check for Core99 */
-	if (find_devices("uni-n") || find_devices("u3") || find_devices("u4"))
+	ic = of_find_node_by_name(NULL, "uni-n");
+	if (!ic)
+		ic = of_find_node_by_name(NULL, "u3");
+	if (!ic)
+		ic = of_find_node_by_name(NULL, "u4");
+	if (ic) {
+		of_node_put(ic);
 		smp_ops = &core99_smp_ops;
+	}
 #ifdef CONFIG_PPC32
 	else
 		smp_ops = &psurge_smp_ops;
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 20f3286..6f32c4e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -264,6 +264,7 @@ static void __init psurge_quad_init(void)
 static int __init smp_psurge_probe(void)
 {
 	int i, ncpus;
+	struct device_node *dn;
 
 	/* We don't do SMP on the PPC601 -- paulus */
 	if (PVR_VER(mfspr(SPRN_PVR)) == 1)
@@ -279,8 +280,10 @@ static int __init smp_psurge_probe(void)
 	 * in the hammerhead memory controller in the case of the
 	 * dual-cpu powersurge board.  -- paulus.
 	 */
-	if (find_devices("hammerhead") == NULL)
+	dn = of_find_node_by_name(NULL, "hammerhead");
+	if (dn == NULL)
 		return 1;
+	of_node_put(dn);
 
 	hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
 	quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index cdd5a0f..e54c4d9 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -145,11 +145,12 @@ anslcd_init(void)
 	int retval;
 	struct device_node* node;
 
-	node = find_devices("lcd");
-	if (!node || !node->parent)
-		return -ENODEV;
-	if (strcmp(node->parent->name, "gc"))
+	node = of_find_node_by_name(NULL, "lcd");
+	if (!node || !node->parent || strcmp(node->parent->name, "gc")) {
+		of_node_put(node);
 		return -ENODEV;
+	}
+	of_node_put(node);
 
 	anslcd_ptr = ioremap(ANSLCD_ADDR, 0x20);
 	
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 7b7db5d..e31cb1e 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -487,7 +487,8 @@ static int __init via_pmu_dev_init(void)
 		pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART;
 		pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
 	} else {
-		struct device_node* prim = find_devices("power-mgt");
+		struct device_node* prim =
+			of_find_node_by_name(NULL, "power-mgt");
 		const u32 *prim_info = NULL;
 		if (prim)
 			prim_info = of_get_property(prim, "prim-info", NULL);
@@ -498,6 +499,7 @@ static int __init via_pmu_dev_init(void)
 			if (pmu_battery_count > 1)
 				pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
 		}
+		of_node_put(prim);
 	}
 #endif /* CONFIG_PPC32 */
 
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 86d2884..e6e61df 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -2160,7 +2160,7 @@ static int find_planb(void)
 	if (!machine_is(powermac))
 		return 0;
 
-	planb_devices = find_devices("planb");
+	planb_devices = of_find_node_by_name(NULL, "planb");
 	if (planb_devices == 0) {
 		planb_num=0;
 		printk(KERN_WARNING "PlanB: no device found!\n");
@@ -2175,12 +2175,14 @@ static int find_planb(void)
 	if (planb_devices->n_addrs != 1) {
 		printk (KERN_WARNING "PlanB: expecting 1 address for planb "
 			"(got %d)", planb_devices->n_addrs);
+		of_node_put(planb_devices);
 		return 0;
 	}
 
 	if (planb_devices->n_intrs == 0) {
 		printk(KERN_WARNING "PlanB: no intrs for device %s\n",
 		       planb_devices->full_name);
+		of_node_put(planb_devices);
 		return 0;
 	} else {
 		irq = planb_devices->intrs[0].line;
@@ -2202,6 +2204,7 @@ static int find_planb(void)
 	confreg = planb_devices->addrs[0].space & 0xff;
 	old_base = planb_devices->addrs[0].address;
 	new_base = 0xf1000000;
+	of_node_put(planb_devices);
 
 	DEBUG("PlanB: Found on bus %d, dev %d, func %d, "
 		"membase 0x%x (base reg. 0x%x)\n",
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 2b163c5..cd92a39 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -1467,7 +1467,8 @@ no_dma:
 	if (ZS_IS_IRDA(uap))
 		uap->port_type = PMAC_SCC_IRDA;
 	if (ZS_IS_INTMODEM(uap)) {
-		struct device_node* i2c_modem = find_devices("i2c-modem");
+		struct device_node* i2c_modem =
+			of_find_node_by_name(NULL, "i2c-modem");
 		if (i2c_modem) {
 			const char* mid =
 				of_get_property(i2c_modem, "modem-id", NULL);
@@ -1482,6 +1483,7 @@ no_dma:
 			}
 			printk(KERN_INFO "pmac_zilog: i2c-modem detected, id: %d\n",
 				mid ? (*mid) : 0);
+			of_node_put(i2c_modem);
 		} else {
 			printk(KERN_INFO "pmac_zilog: serial modem detected\n");
 		}
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index fd60dba..8b76273 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -179,12 +179,14 @@ MODULE_LICENSE("GPL");
 int init_module(void)
 {
 	struct device_node *dp;
+	int ret = -ENXIO;
 
-	dp = find_devices("control");
+	dp = of_find_node_by_name(NULL, "control");
 	if (dp != 0 && !control_of_init(dp))
-		return 0;
+		ret = 0;
+	of_node_put(dp);
 
-	return -ENXIO;
+	return ret;
 }
 
 void cleanup_module(void)
@@ -589,16 +591,18 @@ static int __init control_init(void)
 {
 	struct device_node *dp;
 	char *option = NULL;
+	int ret = -ENXIO;
 
 	if (fb_get_options("controlfb", &option))
 		return -ENODEV;
 	control_setup(option);
 
-	dp = find_devices("control");
+	dp = of_find_node_by_name(NULL, "control");
 	if (dp != 0 && !control_of_init(dp))
-		return 0;
+		ret = 0;
+	of_node_put(dp);
 
-	return -ENXIO;
+	return ret;
 }
 
 module_init(control_init);
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 052b613..73ceade 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -111,9 +111,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
 }
 
 
-/* OBSOLETE: Old style node lookup */
-extern struct device_node *find_devices(const char *name);
-
 /* New style node lookup */
 extern struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name);
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 977b91c..730fa1d 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -346,14 +346,16 @@ int gpio_headphone_irq;
 int
 setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* gpio_pol)
 {
+	struct device_node *gpiop;
 	struct device_node *np;
 	const u32* pp;
+	int ret = -ENODEV;
 
-	np = find_devices("gpio");
-	if (!np)
-		return -ENODEV;
+	gpiop = of_find_node_by_name(NULL, "gpio");
+	if (!gpiop)
+		goto done;
 
-	np = np->child;
+	np = of_get_next_child(gpiop, NULL);
 	while(np != 0) {
 		if (name) {
 			const char *property =
@@ -362,20 +364,24 @@ setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int*
 				break;
 		} else if (compatible && device_is_compatible(np, compatible))
 			break;
-		np = np->sibling;
+		np = of_get_next_child(gpiop, np);
 	}
 	if (!np)
-		return -ENODEV;
+		goto done;
 	pp = of_get_property(np, "AAPL,address", NULL);
 	if (!pp)
-		return -ENODEV;
+		goto done;
 	*gpio_addr = (*pp) & 0x0000ffff;
 	pp = of_get_property(np, "audio-gpio-active-state", NULL);
 	if (pp)
 		*gpio_pol = *pp;
 	else
 		*gpio_pol = 1;
-	return irq_of_parse_and_map(np, 0);
+	ret = irq_of_parse_and_map(np, 0);
+done:
+	of_node_put(np);
+	of_node_put(gpiop);
+	return ret;
 }
 
 static inline void
@@ -2552,32 +2558,33 @@ set_model(void)
 static struct device_node* __init
 get_snd_io_node(void)
 {
-	struct device_node *np = NULL;
+	struct device_node *np;
 
 	/* set up awacs_node for early OF which doesn't have a full set of
 	 * properties on davbus
-	*/
-
-	awacs_node = find_devices("awacs");
+	 */
+	awacs_node = of_find_node_by_name(NULL, "awacs");
 	if (awacs_node)
 		awacs_revision = AWACS_AWACS;
 
 	/* powermac models after 9500 (other than those which use DACA or
 	 * Tumbler) have a node called "davbus".
 	 */
-	np = find_devices("davbus");
+	np = of_find_node_by_name(NULL, "davbus");
 	/*
 	 * if we didn't find a davbus device, try 'i2s-a' since
 	 * this seems to be what iBooks (& Tumbler) have.
 	 */
-	if (np == NULL)
-		np = i2s_node = find_devices("i2s-a");
+	if (np == NULL) {
+		i2s_node = of_find_node_by_name(NULL, "i2s-a");
+		np = of_node_get(i2s_node);
+	}
 
 	/* if we didn't find this - perhaps we are on an early model
 	 * which _only_ has an 'awacs' node
 	*/
 	if (np == NULL && awacs_node)
-		np = awacs_node ;
+		np = of_node_get(awacs_node);
 
 	/* if we failed all these return null - this will cause the
 	 * driver to give up...
@@ -2596,9 +2603,9 @@ get_snd_info_node(struct device_node *io)
 {
 	struct device_node *info;
 
-	info = find_devices("sound");
-	while (info && info->parent != io)
-		info = info->next;
+	for_each_node_by_name(info, "sound")
+		if (info->parent == io)
+			break;
 	return info;
 }
 
@@ -2634,11 +2641,17 @@ get_codec_type(struct device_node *info)
 static void __init
 get_expansion_type(void)
 {
-	if (find_devices("perch") != NULL)
+	struct device_node *dn;
+
+	dn = of_find_node_by_name(NULL, "perch");
+	if (dn != NULL)
 		has_perch = 1;
+	of_node_put(dn);
 
-	if (find_devices("pb-ziva-pc") != NULL)
+	dn = of_find_node_by_name(NULL, "pb-ziva-pc");
+	if (dn != NULL)
 		has_ziva = 1;
+	of_node_put(dn);
 	/* need to work out how we deal with iMac SRS module */
 }
 
@@ -2827,7 +2840,7 @@ int __init dmasound_awacs_init(void)
 #ifdef DEBUG_DMASOUND
 printk("dmasound_pmac: couldn't find sound io OF node\n");
 #endif
-		return -ENODEV ;
+		goto no_device;
 	}
 
 	/* find the OF node that tells us about the sound sub-system
@@ -2839,7 +2852,7 @@ printk("dmasound_pmac: couldn't find sound io OF node\n");
 #ifdef DEBUG_DMASOUND
 printk("dmasound_pmac: couldn't find 'sound' OF node\n");
 #endif
-			return -ENODEV ;
+			goto no_device;
 		}
 	}
 
@@ -2848,7 +2861,7 @@ printk("dmasound_pmac: couldn't find 'sound' OF node\n");
 #ifdef DEBUG_DMASOUND
 printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 #endif
-		return -ENODEV ; /* we don't know this type of h/w */
+		goto no_device; /* we don't know this type of h/w */
 	}
 
 	/* set up perch, ziva, SRS or whatever else we have as sound
@@ -2866,11 +2879,12 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 		 * machines).
 		 */
 		if (awacs_node) {
-			io = awacs_node ;
+			of_node_put(io);
+			io = of_node_get(awacs_node);
 			if (of_get_address(io, 2, NULL, NULL) == NULL) {
 				printk("dmasound_pmac: can't use %s\n",
 				       io->full_name);
-				return -ENODEV;
+				goto no_device;
 			}
 		} else
 			printk("dmasound_pmac: can't use %s\n", io->full_name);
@@ -2881,7 +2895,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 			       awacs_rsrc[0].end - awacs_rsrc[0].start + 1,
 			       " (IO)") == NULL) {
 		printk(KERN_ERR "dmasound: can't request IO resource !\n");
-		return -ENODEV;
+		goto no_device;
 	}
 	if (of_address_to_resource(io, 1, &awacs_rsrc[1]) ||
 	    request_mem_region(awacs_rsrc[1].start,
@@ -2890,7 +2904,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 		release_mem_region(awacs_rsrc[0].start,
 				   awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
 		printk(KERN_ERR "dmasound: can't request Tx DMA resource !\n");
-		return -ENODEV;
+		goto no_device;
 	}
 	if (of_address_to_resource(io, 2, &awacs_rsrc[2]) ||
 	    request_mem_region(awacs_rsrc[2].start,
@@ -2901,7 +2915,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 		release_mem_region(awacs_rsrc[1].start,
 				   awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
 		printk(KERN_ERR "dmasound: can't request Rx DMA resource !\n");
-		return -ENODEV;
+		goto no_device;
 	}
 
 	awacs_beep_dev = input_allocate_device();
@@ -2913,7 +2927,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 		release_mem_region(awacs_rsrc[2].start,
 				   awacs_rsrc[2].end - awacs_rsrc[2].start + 1);
 		printk(KERN_ERR "dmasound: can't allocate input device !\n");
-		return -ENOMEM;
+		goto no_device;
 	}
 
 	awacs_beep_dev->name = "dmasound beeper";
@@ -2941,7 +2955,8 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
 	awacs_rx_irq = irq_of_parse_and_map(io, 2);
 
 	/* Hack for legacy crap that will be killed someday */
-	awacs_node = io;
+	of_node_put(awacs_node);
+	awacs_node = of_node_get(io);
 
 	/* if we have an awacs or screamer - probe the chip to make
 	 * sure we have the right revision.
@@ -2990,6 +3005,8 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
 
 		/* if it's there use it to set up frame rates */
 		init_frame_rates(prop, l) ;
+		of_node_put(info);
+		info = NULL;
 	}
 
 	if (awacs)
@@ -3159,7 +3176,16 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
 	 */
 	input_register_device(awacs_beep_dev);
 
+	of_node_put(io);
+
 	return dmasound_init();
+
+no_device:
+	of_node_put(info);
+	of_node_put(awacs_node);
+	of_node_put(i2s_node);
+	of_node_put(io);
+	return -ENODEV ;
 }
 
 static void __exit dmasound_awacs_cleanup(void)
@@ -3178,6 +3204,8 @@ static void __exit dmasound_awacs_cleanup(void)
 	}
 	dmasound_deinit();
 
+	of_node_put(awacs_node);
+	of_node_put(i2s_node);
 }
 
 MODULE_DESCRIPTION("PowerMac built-in audio driver.");
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index 1125760..b295ef6 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -41,7 +41,6 @@
 
 static u8 tas_i2c_address = 0x34;
 static struct i2c_client *tas_client;
-static struct device_node* tas_node;
 
 static int tas_attach_adapter(struct i2c_adapter *);
 static int tas_detach_client(struct i2c_client *);
@@ -191,13 +190,14 @@ int __init
 tas_init(int driver_id, const char *driver_name)
 {
 	const u32* paddr;
+	struct device_node *tas_node;
 
 	printk(KERN_INFO "tas driver [%s])\n", driver_name);
 
 #ifndef CONFIG_I2C_POWERMAC
 	request_module("i2c-powermac");
 #endif
-	tas_node = find_devices("deq");
+	tas_node = of_find_node_by_name("deq");
 	if (tas_node == NULL)
 		return -ENODEV;
 	paddr = of_get_property(tas_node, "i2c-address", NULL);
@@ -208,6 +208,7 @@ tas_init(int driver_id, const char *driver_name)
 	} else    
 		printk(KERN_INFO "using i2c address: 0x%x (default)\n",
 				tas_i2c_address);
+	of_node_put(tas_node);
 
 	return i2c_add_driver(&tas_driver);
 }
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 5e82968..2bae9c1 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -816,6 +816,7 @@ static int snd_pmac_free(struct snd_pmac *chip)
 
 	if (chip->pdev)
 		pci_dev_put(chip->pdev);
+	of_node_put(chip->node);
 	kfree(chip);
 	return 0;
 }
@@ -863,7 +864,8 @@ static void __init detect_byte_swap(struct snd_pmac *chip)
  */
 static int __init snd_pmac_detect(struct snd_pmac *chip)
 {
-	struct device_node *sound = NULL;
+	struct device_node *sound;
+	struct device_node *dn;
 	const unsigned int *prop;
 	unsigned int l;
 	struct macio_chip* macio;
@@ -891,22 +893,21 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
 	else if (machine_is_compatible("PowerBook1,1")
 		 || machine_is_compatible("AAPL,PowerBook1998"))
 		chip->is_pbook_G3 = 1;
-	chip->node = find_devices("awacs");
-	if (chip->node)
-		sound = chip->node;
+	chip->node = of_find_node_by_name(NULL, "awacs");
+	sound = of_node_get(chip->node);
 
 	/*
 	 * powermac G3 models have a node called "davbus"
 	 * with a child called "sound".
 	 */
 	if (!chip->node)
-		chip->node = find_devices("davbus");
+		chip->node = of_find_node_by_name(NULL, "davbus");
 	/*
 	 * if we didn't find a davbus device, try 'i2s-a' since
 	 * this seems to be what iBooks have
 	 */
 	if (! chip->node) {
-		chip->node = find_devices("i2s-a");
+		chip->node = of_find_node_by_name(NULL, "i2s-a");
 		if (chip->node && chip->node->parent &&
 		    chip->node->parent->parent) {
 			if (device_is_compatible(chip->node->parent->parent,
@@ -918,12 +919,14 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
 		return -ENODEV;
 
 	if (!sound) {
-		sound = find_devices("sound");
+		sound = of_find_node_by_name(NULL, "sound");
 		while (sound && sound->parent != chip->node)
-			sound = sound->next;
+			sound = of_find_node_by_name(sound, "sound");
 	}
-	if (! sound)
+	if (! sound) {
+		of_node_put(chip->node);
 		return -ENODEV;
+	}
 	prop = of_get_property(sound, "sub-frame", NULL);
 	if (prop && *prop < 16)
 		chip->subframe = *prop;
@@ -934,6 +937,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
 		printk(KERN_INFO "snd-powermac no longer handles any "
 				 "machines with a layout-id property "
 				 "in the device-tree, use snd-aoa.\n");
+		of_node_put(chip->node);
 		return -ENODEV;
 	}
 	/* This should be verified on older screamers */
@@ -971,7 +975,9 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
 	prop = of_get_property(sound, "device-id", NULL);
 	if (prop)
 		chip->device_id = *prop;
-	chip->has_iic = (find_devices("perch") != NULL);
+	dn = of_find_node_by_name(NULL, "perch");
+	chip->has_iic = (dn != NULL);
+	of_node_put(dn);
 
 	/* We need the PCI device for DMA allocations, let's use a crude method
 	 * for now ...
@@ -1021,6 +1027,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
 		chip->freqs_ok = 1;
 	}
 
+	of_node_put(sound);
 	return 0;
 }
 
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 8e01b55..54e333f 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1031,32 +1031,40 @@ static irqreturn_t headphone_intr(int irq, void *devid)
 /* look for audio-gpio device */
 static struct device_node *find_audio_device(const char *name)
 {
+	struct device_node *gpiop;
 	struct device_node *np;
   
-	if (! (np = find_devices("gpio")))
+	gpiop = of_find_node_by_name(NULL, "gpio");
+	if (! gpiop)
 		return NULL;
   
-	for (np = np->child; np; np = np->sibling) {
+	for (np = of_get_next_child(gpiop, NULL); np;
+			np = of_get_next_child(gpiop, np)) {
 		const char *property = of_get_property(np, "audio-gpio", NULL);
 		if (property && strcmp(property, name) == 0)
-			return np;
+			break;
 	}  
-	return NULL;
+	of_node_put(gpiop);
+	return np;
 }
 
 /* look for audio-gpio device */
 static struct device_node *find_compatible_audio_device(const char *name)
 {
+	struct device_node *gpiop;
 	struct device_node *np;
   
-	if (! (np = find_devices("gpio")))
+	gpiop = of_find_node_by_name(NULL, "gpio");
+	if (!gpiop)
 		return NULL;
   
-	for (np = np->child; np; np = np->sibling) {
+	for (np = of_get_next_child(gpiop, NULL); np;
+			np = of_get_next_child(gpiop, np)) {
 		if (device_is_compatible(np, name))
-			return np;
+			break;
 	}  
-	return NULL;
+	of_node_put(gpiop);
+	return np;
 }
 
 /* find an audio device and get its address */
@@ -1066,6 +1074,7 @@ static long tumbler_find_device(const char *device, const char *platform,
 	struct device_node *node;
 	const u32 *base;
 	u32 addr;
+	long ret;
 
 	if (is_compatible)
 		node = find_compatible_audio_device(device);
@@ -1083,6 +1092,7 @@ static long tumbler_find_device(const char *device, const char *platform,
 		if (!base) {
 			DBG("(E) cannot find address for device %s !\n", device);
 			snd_printd("cannot find address for device %s\n", device);
+			of_node_put(node);
 			return -ENODEV;
 		}
 		addr = *base;
@@ -1124,7 +1134,9 @@ static long tumbler_find_device(const char *device, const char *platform,
 	DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",
 	    device, gp->addr, gp->active_state);
 
-	return irq_of_parse_and_map(node, 0);
+	ret = irq_of_parse_and_map(node, 0);
+	of_node_put(node);
+	return ret;
 }
 
 /* reset audio */
@@ -1342,9 +1354,9 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
 		return err;
 
 	/* set up TAS */
-	tas_node = find_devices("deq");
+	tas_node = of_find_node_by_name(NULL, "deq");
 	if (tas_node == NULL)
-		tas_node = find_devices("codec");
+		tas_node = of_find_node_by_name(NULL, "codec");
 	if (tas_node == NULL)
 		return -ENODEV;
 
@@ -1355,6 +1367,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
 		mix->i2c.addr = (*paddr) >> 1;
 	else
 		mix->i2c.addr = TAS_I2C_ADDR;
+	of_node_put(tas_node);
 
 	DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr);
 
-- 
1.5.1.1

^ permalink raw reply related

* Re: [PATCH] add reg and stack dump to booke WD handler
From: Paul Mackerras @ 2007-04-24  4:01 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linuxppc-dev
In-Reply-To: <20070413221657.GA23624@blade.az.mvista.com>

Dave Jiang writes:

> Have the booke watchdog dump some useful information when triggered.
> Hopefully that'll give the user some hint of what happened rather than just a
> mysterious reboot.

Why not call either die() or panic()?  Won't they do what you want?

Paul.

^ permalink raw reply

* Re: [PATCH] powerpc pseries eeh: Convert to kthread API
From: Paul Mackerras @ 2007-04-24  4:34 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: <Andrew Morton, linux-s390, linux-kernel, Christoph Hellwig,
	linuxppc-dev, containers, Oleg Nesterov
In-Reply-To: <m1abwyv4oq.fsf@ebiederm.dsl.xmission.com>

Eric W. Biederman writes:

> Well the basic problem is that for any piece of code that can be modular
> we need a way to ensure all threads it has running are shutdown when we
> remove the module.

The EEH code can't be modular, and wouldn't make any sense to be
modular, since it's part of the infrastructure for accessing PCI
devices.

Paul.

^ permalink raw reply

* powerpc: Prepare for splitting up mmu.h by MMU type
From: David Gibson @ 2007-04-24  4:48 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

Currently asm-powerpc/mmu.h has definitions for the 64-bit hash based
MMU.  If CONFIG_PPC64 is not set, it instead includes asm-ppc/mmu.h
which contains a particularly horrible mess of #ifdefs giving the
definitions for all the various 32-bit MMUs.

It would be nice to have the low level definitions for each MMU type
neatly in their own separate files.  It would also be good to wean
arch/powerpc off dependence on the old asm-ppc/mmu.h.

This patch makes a start on such a cleanup bu moving the definitions
for the 64-bit hash MMU to their own file, asm-powerpc/mmu_hash64.h.
Definitions for the other MMUs still all come from asm-ppc/mmu.h,
however each MMU type can now be one-by-one moved over to their own
file, in the process cleaning them up stripping them of cruft no
longer necessary in arch/powerpc.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

Index: working-2.6/include/asm-powerpc/mmu.h
===================================================================
--- working-2.6.orig/include/asm-powerpc/mmu.h	2007-04-24 13:51:01.000000000 +1000
+++ working-2.6/include/asm-powerpc/mmu.h	2007-04-24 13:59:05.000000000 +1000
@@ -2,407 +2,14 @@
 #define _ASM_POWERPC_MMU_H_
 #ifdef __KERNEL__
 
-#ifndef CONFIG_PPC64
-#include <asm-ppc/mmu.h>
+#if defined(CONFIG_PPC64)
+/* 64-bit classic hash table MMU */
+#  include <asm/mmu_hash64.h>
 #else
-
-/*
- * PowerPC memory management structures
- *
- * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
- *   PPC64 rework.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/asm-compat.h>
-#include <asm/page.h>
-
-/*
- * Segment table
- */
-
-#define STE_ESID_V	0x80
-#define STE_ESID_KS	0x20
-#define STE_ESID_KP	0x10
-#define STE_ESID_N	0x08
-
-#define STE_VSID_SHIFT	12
-
-/* Location of cpu0's segment table */
-#define STAB0_PAGE	0x6
-#define STAB0_OFFSET	(STAB0_PAGE << 12)
-#define STAB0_PHYS_ADDR	(STAB0_OFFSET + PHYSICAL_START)
-
-#ifndef __ASSEMBLY__
-extern char initial_stab[];
-#endif /* ! __ASSEMBLY */
-
-/*
- * SLB
- */
-
-#define SLB_NUM_BOLTED		3
-#define SLB_CACHE_ENTRIES	8
-
-/* Bits in the SLB ESID word */
-#define SLB_ESID_V		ASM_CONST(0x0000000008000000) /* valid */
-
-/* Bits in the SLB VSID word */
-#define SLB_VSID_SHIFT		12
-#define SLB_VSID_B		ASM_CONST(0xc000000000000000)
-#define SLB_VSID_B_256M		ASM_CONST(0x0000000000000000)
-#define SLB_VSID_B_1T		ASM_CONST(0x4000000000000000)
-#define SLB_VSID_KS		ASM_CONST(0x0000000000000800)
-#define SLB_VSID_KP		ASM_CONST(0x0000000000000400)
-#define SLB_VSID_N		ASM_CONST(0x0000000000000200) /* no-execute */
-#define SLB_VSID_L		ASM_CONST(0x0000000000000100)
-#define SLB_VSID_C		ASM_CONST(0x0000000000000080) /* class */
-#define SLB_VSID_LP		ASM_CONST(0x0000000000000030)
-#define SLB_VSID_LP_00		ASM_CONST(0x0000000000000000)
-#define SLB_VSID_LP_01		ASM_CONST(0x0000000000000010)
-#define SLB_VSID_LP_10		ASM_CONST(0x0000000000000020)
-#define SLB_VSID_LP_11		ASM_CONST(0x0000000000000030)
-#define SLB_VSID_LLP		(SLB_VSID_L|SLB_VSID_LP)
-
-#define SLB_VSID_KERNEL		(SLB_VSID_KP)
-#define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
-
-#define SLBIE_C			(0x08000000)
-
-/*
- * Hash table
- */
-
-#define HPTES_PER_GROUP 8
-
-#define HPTE_V_AVPN_SHIFT	7
-#define HPTE_V_AVPN		ASM_CONST(0xffffffffffffff80)
-#define HPTE_V_AVPN_VAL(x)	(((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
-#define HPTE_V_COMPARE(x,y)	(!(((x) ^ (y)) & HPTE_V_AVPN))
-#define HPTE_V_BOLTED		ASM_CONST(0x0000000000000010)
-#define HPTE_V_LOCK		ASM_CONST(0x0000000000000008)
-#define HPTE_V_LARGE		ASM_CONST(0x0000000000000004)
-#define HPTE_V_SECONDARY	ASM_CONST(0x0000000000000002)
-#define HPTE_V_VALID		ASM_CONST(0x0000000000000001)
-
-#define HPTE_R_PP0		ASM_CONST(0x8000000000000000)
-#define HPTE_R_TS		ASM_CONST(0x4000000000000000)
-#define HPTE_R_RPN_SHIFT	12
-#define HPTE_R_RPN		ASM_CONST(0x3ffffffffffff000)
-#define HPTE_R_FLAGS		ASM_CONST(0x00000000000003ff)
-#define HPTE_R_PP		ASM_CONST(0x0000000000000003)
-#define HPTE_R_N		ASM_CONST(0x0000000000000004)
-#define HPTE_R_C		ASM_CONST(0x0000000000000080)
-#define HPTE_R_R		ASM_CONST(0x0000000000000100)
-
-/* Values for PP (assumes Ks=0, Kp=1) */
-/* pp0 will always be 0 for linux     */
-#define PP_RWXX	0	/* Supervisor read/write, User none */
-#define PP_RWRX 1	/* Supervisor read/write, User read */
-#define PP_RWRW 2	/* Supervisor read/write, User read/write */
-#define PP_RXRX 3	/* Supervisor read,       User read */
-
-#ifndef __ASSEMBLY__
-
-typedef struct {
-	unsigned long v;
-	unsigned long r;
-} hpte_t;
-
-extern hpte_t *htab_address;
-extern unsigned long htab_size_bytes;
-extern unsigned long htab_hash_mask;
-
-/*
- * Page size definition
- *
- *    shift : is the "PAGE_SHIFT" value for that page size
- *    sllp  : is a bit mask with the value of SLB L || LP to be or'ed
- *            directly to a slbmte "vsid" value
- *    penc  : is the HPTE encoding mask for the "LP" field:
- *
- */
-struct mmu_psize_def
-{
-	unsigned int	shift;	/* number of bits */
-	unsigned int	penc;	/* HPTE encoding */
-	unsigned int	tlbiel;	/* tlbiel supported for that page size */
-	unsigned long	avpnm;	/* bits to mask out in AVPN in the HPTE */
-	unsigned long	sllp;	/* SLB L||LP (exact mask to use in slbmte) */
-};
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * The kernel use the constants below to index in the page sizes array.
- * The use of fixed constants for this purpose is better for performances
- * of the low level hash refill handlers.
- *
- * A non supported page size has a "shift" field set to 0
- *
- * Any new page size being implemented can get a new entry in here. Whether
- * the kernel will use it or not is a different matter though. The actual page
- * size used by hugetlbfs is not defined here and may be made variable
- */
-
-#define MMU_PAGE_4K		0	/* 4K */
-#define MMU_PAGE_64K		1	/* 64K */
-#define MMU_PAGE_64K_AP		2	/* 64K Admixed (in a 4K segment) */
-#define MMU_PAGE_1M		3	/* 1M */
-#define MMU_PAGE_16M		4	/* 16M */
-#define MMU_PAGE_16G		5	/* 16G */
-#define MMU_PAGE_COUNT		6
-
-#ifndef __ASSEMBLY__
-
-/*
- * The current system page sizes
- */
-extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
-extern int mmu_linear_psize;
-extern int mmu_virtual_psize;
-extern int mmu_vmalloc_psize;
-extern int mmu_io_psize;
-
-/*
- * If the processor supports 64k normal pages but not 64k cache
- * inhibited pages, we have to be prepared to switch processes
- * to use 4k pages when they create cache-inhibited mappings.
- * If this is the case, mmu_ci_restrictions will be set to 1.
- */
-extern int mmu_ci_restrictions;
-
-#ifdef CONFIG_HUGETLB_PAGE
-/*
- * The page size index of the huge pages for use by hugetlbfs
- */
-extern int mmu_huge_psize;
-
-#endif /* CONFIG_HUGETLB_PAGE */
-
-/*
- * This function sets the AVPN and L fields of the HPTE  appropriately
- * for the page size
- */
-static inline unsigned long hpte_encode_v(unsigned long va, int psize)
-{
-	unsigned long v =
-	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-	v <<= HPTE_V_AVPN_SHIFT;
-	if (psize != MMU_PAGE_4K)
-		v |= HPTE_V_LARGE;
-	return v;
-}
-
-/*
- * This function sets the ARPN, and LP fields of the HPTE appropriately
- * for the page size. We assume the pa is already "clean" that is properly
- * aligned for the requested page size
- */
-static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
-{
-	unsigned long r;
-
-	/* A 4K page needs no special encoding */
-	if (psize == MMU_PAGE_4K)
-		return pa & HPTE_R_RPN;
-	else {
-		unsigned int penc = mmu_psize_defs[psize].penc;
-		unsigned int shift = mmu_psize_defs[psize].shift;
-		return (pa & ~((1ul << shift) - 1)) | (penc << 12);
-	}
-	return r;
-}
-
-/*
- * This hashes a virtual address for a 256Mb segment only for now
- */
-
-static inline unsigned long hpt_hash(unsigned long va, unsigned int shift)
-{
-	return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift);
-}
-
-extern int __hash_page_4K(unsigned long ea, unsigned long access,
-			  unsigned long vsid, pte_t *ptep, unsigned long trap,
-			  unsigned int local);
-extern int __hash_page_64K(unsigned long ea, unsigned long access,
-			   unsigned long vsid, pte_t *ptep, unsigned long trap,
-			   unsigned int local);
-struct mm_struct;
-extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
-			  unsigned long ea, unsigned long vsid, int local,
-			  unsigned long trap);
-
-extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
-			     unsigned long pstart, unsigned long mode,
-			     int psize);
-
-extern void htab_initialize(void);
-extern void htab_initialize_secondary(void);
-extern void hpte_init_native(void);
-extern void hpte_init_lpar(void);
-extern void hpte_init_iSeries(void);
-extern void hpte_init_beat(void);
-
-extern void stabs_alloc(void);
-extern void slb_initialize(void);
-extern void slb_flush_and_rebolt(void);
-extern void stab_initialize(unsigned long stab);
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * VSID allocation
- *
- * We first generate a 36-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID, for user addresses it is:
- *	(context << 15) | (esid & 0x7fff)
- *
- * The two forms are distinguishable because the top bit is 0 for user
- * addresses, whereas the top two bits are 1 for kernel addresses.
- * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
- * now.
- *
- * The proto-VSIDs are then scrambled into real VSIDs with the
- * multiplicative hash:
- *
- *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
- *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
- *
- * This scramble is only well defined for proto-VSIDs below
- * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
- * reserved.  VSID_MULTIPLIER is prime, so in particular it is
- * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
- * Because the modulus is 2^n-1 we can compute it efficiently without
- * a divide or extra multiply (see below).
- *
- * This scheme has several advantages over older methods:
- *
- * 	- We have VSIDs allocated for every kernel address
- * (i.e. everything above 0xC000000000000000), except the very top
- * segment, which simplifies several things.
- *
- * 	- We allow for 15 significant bits of ESID and 20 bits of
- * context for user addresses.  i.e. 8T (43 bits) of address space for
- * up to 1M contexts (although the page table structure and context
- * allocation will need changes to take advantage of this).
- *
- * 	- The scramble function gives robust scattering in the hash
- * table (at least based on some initial results).  The previous
- * method was more susceptible to pathological cases giving excessive
- * hash collisions.
- */
-/*
- * WARNING - If you change these you must make sure the asm
- * implementations in slb_allocate (slb_low.S), do_stab_bolted
- * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
- *
- * You'll also need to change the precomputed VSID values in head.S
- * which are used by the iSeries firmware.
- */
-
-#define VSID_MULTIPLIER	ASM_CONST(200730139)	/* 28-bit prime */
-#define VSID_BITS	36
-#define VSID_MODULUS	((1UL<<VSID_BITS)-1)
-
-#define CONTEXT_BITS	19
-#define USER_ESID_BITS	16
-
-#define USER_VSID_RANGE	(1UL << (USER_ESID_BITS + SID_SHIFT))
-
-/*
- * This macro generates asm code to compute the VSID scramble
- * function.  Used in slb_allocate() and do_stab_bolted.  The function
- * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
- *
- *	rt = register continaing the proto-VSID and into which the
- *		VSID will be stored
- *	rx = scratch register (clobbered)
- *
- * 	- rt and rx must be different registers
- * 	- The answer will end up in the low 36 bits of rt.  The higher
- * 	  bits may contain other garbage, so you may need to mask the
- * 	  result.
- */
-#define ASM_VSID_SCRAMBLE(rt, rx)	\
-	lis	rx,VSID_MULTIPLIER@h;					\
-	ori	rx,rx,VSID_MULTIPLIER@l;				\
-	mulld	rt,rt,rx;		/* rt = rt * MULTIPLIER */	\
-									\
-	srdi	rx,rt,VSID_BITS;					\
-	clrldi	rt,rt,(64-VSID_BITS);					\
-	add	rt,rt,rx;		/* add high and low bits */	\
-	/* Now, r3 == VSID (mod 2^36-1), and lies between 0 and		\
-	 * 2^36-1+2^28-1.  That in particular means that if r3 >=	\
-	 * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has	\
-	 * the bit clear, r3 already has the answer we want, if it	\
-	 * doesn't, the answer is the low 36 bits of r3+1.  So in all	\
-	 * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
-	addi	rx,rt,1;						\
-	srdi	rx,rx,VSID_BITS;	/* extract 2^36 bit */		\
-	add	rt,rt,rx
-
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long mm_context_id_t;
-
-typedef struct {
-	mm_context_id_t id;
-	u16 user_psize;			/* page size index */
-	u16 sllp;			/* SLB entry page size encoding */
-#ifdef CONFIG_HUGETLB_PAGE
-	u16 low_htlb_areas, high_htlb_areas;
+/* 32-bit.  FIXME: split up the 32-bit MMU types, and revise for
+ * arch/powerpc */
+#  include <asm-ppc/mmu.h>
 #endif
-	unsigned long vdso_base;
-} mm_context_t;
-
-
-static inline unsigned long vsid_scramble(unsigned long protovsid)
-{
-#if 0
-	/* The code below is equivalent to this function for arguments
-	 * < 2^VSID_BITS, which is all this should ever be called
-	 * with.  However gcc is not clever enough to compute the
-	 * modulus (2^n-1) without a second multiply. */
-	return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
-#else /* 1 */
-	unsigned long x;
-
-	x = protovsid * VSID_MULTIPLIER;
-	x = (x >> VSID_BITS) + (x & VSID_MODULUS);
-	return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
-#endif /* 1 */
-}
-
-/* This is only valid for addresses >= KERNELBASE */
-static inline unsigned long get_kernel_vsid(unsigned long ea)
-{
-	return vsid_scramble(ea >> SID_SHIFT);
-}
-
-/* This is only valid for user addresses (which are below 2^41) */
-static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
-{
-	return vsid_scramble((context << USER_ESID_BITS)
-			     | (ea >> SID_SHIFT));
-}
-
-#define VSID_SCRAMBLE(pvsid)	(((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS)
-#define KERNEL_VSID(ea)		VSID_SCRAMBLE(GET_ESID(ea))
-
-/* Physical address used by some IO functions */
-typedef unsigned long phys_addr_t;
-
-
-#endif /* __ASSEMBLY */
 
-#endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MMU_H_ */
Index: working-2.6/include/asm-powerpc/mmu_hash64.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ working-2.6/include/asm-powerpc/mmu_hash64.h	2007-04-24 13:58:35.000000000 +1000
@@ -0,0 +1,399 @@
+#ifndef _ASM_POWERPC_MMU_HASH64_H_
+#define _ASM_POWERPC_MMU_HASH64_H_
+/*
+ * PowerPC64 memory management structures
+ *
+ * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com>
+ *   PPC64 rework.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/asm-compat.h>
+#include <asm/page.h>
+
+/*
+ * Segment table
+ */
+
+#define STE_ESID_V	0x80
+#define STE_ESID_KS	0x20
+#define STE_ESID_KP	0x10
+#define STE_ESID_N	0x08
+
+#define STE_VSID_SHIFT	12
+
+/* Location of cpu0's segment table */
+#define STAB0_PAGE	0x6
+#define STAB0_OFFSET	(STAB0_PAGE << 12)
+#define STAB0_PHYS_ADDR	(STAB0_OFFSET + PHYSICAL_START)
+
+#ifndef __ASSEMBLY__
+extern char initial_stab[];
+#endif /* ! __ASSEMBLY */
+
+/*
+ * SLB
+ */
+
+#define SLB_NUM_BOLTED		3
+#define SLB_CACHE_ENTRIES	8
+
+/* Bits in the SLB ESID word */
+#define SLB_ESID_V		ASM_CONST(0x0000000008000000) /* valid */
+
+/* Bits in the SLB VSID word */
+#define SLB_VSID_SHIFT		12
+#define SLB_VSID_B		ASM_CONST(0xc000000000000000)
+#define SLB_VSID_B_256M		ASM_CONST(0x0000000000000000)
+#define SLB_VSID_B_1T		ASM_CONST(0x4000000000000000)
+#define SLB_VSID_KS		ASM_CONST(0x0000000000000800)
+#define SLB_VSID_KP		ASM_CONST(0x0000000000000400)
+#define SLB_VSID_N		ASM_CONST(0x0000000000000200) /* no-execute */
+#define SLB_VSID_L		ASM_CONST(0x0000000000000100)
+#define SLB_VSID_C		ASM_CONST(0x0000000000000080) /* class */
+#define SLB_VSID_LP		ASM_CONST(0x0000000000000030)
+#define SLB_VSID_LP_00		ASM_CONST(0x0000000000000000)
+#define SLB_VSID_LP_01		ASM_CONST(0x0000000000000010)
+#define SLB_VSID_LP_10		ASM_CONST(0x0000000000000020)
+#define SLB_VSID_LP_11		ASM_CONST(0x0000000000000030)
+#define SLB_VSID_LLP		(SLB_VSID_L|SLB_VSID_LP)
+
+#define SLB_VSID_KERNEL		(SLB_VSID_KP)
+#define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C)
+
+#define SLBIE_C			(0x08000000)
+
+/*
+ * Hash table
+ */
+
+#define HPTES_PER_GROUP 8
+
+#define HPTE_V_AVPN_SHIFT	7
+#define HPTE_V_AVPN		ASM_CONST(0xffffffffffffff80)
+#define HPTE_V_AVPN_VAL(x)	(((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
+#define HPTE_V_COMPARE(x,y)	(!(((x) ^ (y)) & HPTE_V_AVPN))
+#define HPTE_V_BOLTED		ASM_CONST(0x0000000000000010)
+#define HPTE_V_LOCK		ASM_CONST(0x0000000000000008)
+#define HPTE_V_LARGE		ASM_CONST(0x0000000000000004)
+#define HPTE_V_SECONDARY	ASM_CONST(0x0000000000000002)
+#define HPTE_V_VALID		ASM_CONST(0x0000000000000001)
+
+#define HPTE_R_PP0		ASM_CONST(0x8000000000000000)
+#define HPTE_R_TS		ASM_CONST(0x4000000000000000)
+#define HPTE_R_RPN_SHIFT	12
+#define HPTE_R_RPN		ASM_CONST(0x3ffffffffffff000)
+#define HPTE_R_FLAGS		ASM_CONST(0x00000000000003ff)
+#define HPTE_R_PP		ASM_CONST(0x0000000000000003)
+#define HPTE_R_N		ASM_CONST(0x0000000000000004)
+#define HPTE_R_C		ASM_CONST(0x0000000000000080)
+#define HPTE_R_R		ASM_CONST(0x0000000000000100)
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+/* pp0 will always be 0 for linux     */
+#define PP_RWXX	0	/* Supervisor read/write, User none */
+#define PP_RWRX 1	/* Supervisor read/write, User read */
+#define PP_RWRW 2	/* Supervisor read/write, User read/write */
+#define PP_RXRX 3	/* Supervisor read,       User read */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned long v;
+	unsigned long r;
+} hpte_t;
+
+extern hpte_t *htab_address;
+extern unsigned long htab_size_bytes;
+extern unsigned long htab_hash_mask;
+
+/*
+ * Page size definition
+ *
+ *    shift : is the "PAGE_SHIFT" value for that page size
+ *    sllp  : is a bit mask with the value of SLB L || LP to be or'ed
+ *            directly to a slbmte "vsid" value
+ *    penc  : is the HPTE encoding mask for the "LP" field:
+ *
+ */
+struct mmu_psize_def
+{
+	unsigned int	shift;	/* number of bits */
+	unsigned int	penc;	/* HPTE encoding */
+	unsigned int	tlbiel;	/* tlbiel supported for that page size */
+	unsigned long	avpnm;	/* bits to mask out in AVPN in the HPTE */
+	unsigned long	sllp;	/* SLB L||LP (exact mask to use in slbmte) */
+};
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The kernel use the constants below to index in the page sizes array.
+ * The use of fixed constants for this purpose is better for performances
+ * of the low level hash refill handlers.
+ *
+ * A non supported page size has a "shift" field set to 0
+ *
+ * Any new page size being implemented can get a new entry in here. Whether
+ * the kernel will use it or not is a different matter though. The actual page
+ * size used by hugetlbfs is not defined here and may be made variable
+ */
+
+#define MMU_PAGE_4K		0	/* 4K */
+#define MMU_PAGE_64K		1	/* 64K */
+#define MMU_PAGE_64K_AP		2	/* 64K Admixed (in a 4K segment) */
+#define MMU_PAGE_1M		3	/* 1M */
+#define MMU_PAGE_16M		4	/* 16M */
+#define MMU_PAGE_16G		5	/* 16G */
+#define MMU_PAGE_COUNT		6
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The current system page sizes
+ */
+extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+extern int mmu_linear_psize;
+extern int mmu_virtual_psize;
+extern int mmu_vmalloc_psize;
+extern int mmu_io_psize;
+
+/*
+ * If the processor supports 64k normal pages but not 64k cache
+ * inhibited pages, we have to be prepared to switch processes
+ * to use 4k pages when they create cache-inhibited mappings.
+ * If this is the case, mmu_ci_restrictions will be set to 1.
+ */
+extern int mmu_ci_restrictions;
+
+#ifdef CONFIG_HUGETLB_PAGE
+/*
+ * The page size index of the huge pages for use by hugetlbfs
+ */
+extern int mmu_huge_psize;
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
+/*
+ * This function sets the AVPN and L fields of the HPTE  appropriately
+ * for the page size
+ */
+static inline unsigned long hpte_encode_v(unsigned long va, int psize)
+{
+	unsigned long v =
+	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
+	v <<= HPTE_V_AVPN_SHIFT;
+	if (psize != MMU_PAGE_4K)
+		v |= HPTE_V_LARGE;
+	return v;
+}
+
+/*
+ * This function sets the ARPN, and LP fields of the HPTE appropriately
+ * for the page size. We assume the pa is already "clean" that is properly
+ * aligned for the requested page size
+ */
+static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
+{
+	unsigned long r;
+
+	/* A 4K page needs no special encoding */
+	if (psize == MMU_PAGE_4K)
+		return pa & HPTE_R_RPN;
+	else {
+		unsigned int penc = mmu_psize_defs[psize].penc;
+		unsigned int shift = mmu_psize_defs[psize].shift;
+		return (pa & ~((1ul << shift) - 1)) | (penc << 12);
+	}
+	return r;
+}
+
+/*
+ * This hashes a virtual address for a 256Mb segment only for now
+ */
+
+static inline unsigned long hpt_hash(unsigned long va, unsigned int shift)
+{
+	return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift);
+}
+
+extern int __hash_page_4K(unsigned long ea, unsigned long access,
+			  unsigned long vsid, pte_t *ptep, unsigned long trap,
+			  unsigned int local);
+extern int __hash_page_64K(unsigned long ea, unsigned long access,
+			   unsigned long vsid, pte_t *ptep, unsigned long trap,
+			   unsigned int local);
+struct mm_struct;
+extern int hash_huge_page(struct mm_struct *mm, unsigned long access,
+			  unsigned long ea, unsigned long vsid, int local,
+			  unsigned long trap);
+
+extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
+			     unsigned long pstart, unsigned long mode,
+			     int psize);
+
+extern void htab_initialize(void);
+extern void htab_initialize_secondary(void);
+extern void hpte_init_native(void);
+extern void hpte_init_lpar(void);
+extern void hpte_init_iSeries(void);
+extern void hpte_init_beat(void);
+
+extern void stabs_alloc(void);
+extern void slb_initialize(void);
+extern void slb_flush_and_rebolt(void);
+extern void stab_initialize(unsigned long stab);
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * VSID allocation
+ *
+ * We first generate a 36-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID, for user addresses it is:
+ *	(context << 15) | (esid & 0x7fff)
+ *
+ * The two forms are distinguishable because the top bit is 0 for user
+ * addresses, whereas the top two bits are 1 for kernel addresses.
+ * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
+ * now.
+ *
+ * The proto-VSIDs are then scrambled into real VSIDs with the
+ * multiplicative hash:
+ *
+ *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
+ *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
+ *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
+ *
+ * This scramble is only well defined for proto-VSIDs below
+ * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
+ * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
+ * Because the modulus is 2^n-1 we can compute it efficiently without
+ * a divide or extra multiply (see below).
+ *
+ * This scheme has several advantages over older methods:
+ *
+ * 	- We have VSIDs allocated for every kernel address
+ * (i.e. everything above 0xC000000000000000), except the very top
+ * segment, which simplifies several things.
+ *
+ * 	- We allow for 15 significant bits of ESID and 20 bits of
+ * context for user addresses.  i.e. 8T (43 bits) of address space for
+ * up to 1M contexts (although the page table structure and context
+ * allocation will need changes to take advantage of this).
+ *
+ * 	- The scramble function gives robust scattering in the hash
+ * table (at least based on some initial results).  The previous
+ * method was more susceptible to pathological cases giving excessive
+ * hash collisions.
+ */
+/*
+ * WARNING - If you change these you must make sure the asm
+ * implementations in slb_allocate (slb_low.S), do_stab_bolted
+ * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
+ *
+ * You'll also need to change the precomputed VSID values in head.S
+ * which are used by the iSeries firmware.
+ */
+
+#define VSID_MULTIPLIER	ASM_CONST(200730139)	/* 28-bit prime */
+#define VSID_BITS	36
+#define VSID_MODULUS	((1UL<<VSID_BITS)-1)
+
+#define CONTEXT_BITS	19
+#define USER_ESID_BITS	16
+
+#define USER_VSID_RANGE	(1UL << (USER_ESID_BITS + SID_SHIFT))
+
+/*
+ * This macro generates asm code to compute the VSID scramble
+ * function.  Used in slb_allocate() and do_stab_bolted.  The function
+ * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ *	rt = register continaing the proto-VSID and into which the
+ *		VSID will be stored
+ *	rx = scratch register (clobbered)
+ *
+ * 	- rt and rx must be different registers
+ * 	- The answer will end up in the low 36 bits of rt.  The higher
+ * 	  bits may contain other garbage, so you may need to mask the
+ * 	  result.
+ */
+#define ASM_VSID_SCRAMBLE(rt, rx)	\
+	lis	rx,VSID_MULTIPLIER@h;					\
+	ori	rx,rx,VSID_MULTIPLIER@l;				\
+	mulld	rt,rt,rx;		/* rt = rt * MULTIPLIER */	\
+									\
+	srdi	rx,rt,VSID_BITS;					\
+	clrldi	rt,rt,(64-VSID_BITS);					\
+	add	rt,rt,rx;		/* add high and low bits */	\
+	/* Now, r3 == VSID (mod 2^36-1), and lies between 0 and		\
+	 * 2^36-1+2^28-1.  That in particular means that if r3 >=	\
+	 * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has	\
+	 * the bit clear, r3 already has the answer we want, if it	\
+	 * doesn't, the answer is the low 36 bits of r3+1.  So in all	\
+	 * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
+	addi	rx,rt,1;						\
+	srdi	rx,rx,VSID_BITS;	/* extract 2^36 bit */		\
+	add	rt,rt,rx
+
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_context_id_t;
+
+typedef struct {
+	mm_context_id_t id;
+	u16 user_psize;			/* page size index */
+	u16 sllp;			/* SLB entry page size encoding */
+#ifdef CONFIG_HUGETLB_PAGE
+	u16 low_htlb_areas, high_htlb_areas;
+#endif
+	unsigned long vdso_base;
+} mm_context_t;
+
+
+static inline unsigned long vsid_scramble(unsigned long protovsid)
+{
+#if 0
+	/* The code below is equivalent to this function for arguments
+	 * < 2^VSID_BITS, which is all this should ever be called
+	 * with.  However gcc is not clever enough to compute the
+	 * modulus (2^n-1) without a second multiply. */
+	return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
+#else /* 1 */
+	unsigned long x;
+
+	x = protovsid * VSID_MULTIPLIER;
+	x = (x >> VSID_BITS) + (x & VSID_MODULUS);
+	return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
+#endif /* 1 */
+}
+
+/* This is only valid for addresses >= KERNELBASE */
+static inline unsigned long get_kernel_vsid(unsigned long ea)
+{
+	return vsid_scramble(ea >> SID_SHIFT);
+}
+
+/* This is only valid for user addresses (which are below 2^41) */
+static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
+{
+	return vsid_scramble((context << USER_ESID_BITS)
+			     | (ea >> SID_SHIFT));
+}
+
+#define VSID_SCRAMBLE(pvsid)	(((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS)
+#define KERNEL_VSID(ea)		VSID_SCRAMBLE(GET_ESID(ea))
+
+/* Physical address used by some IO functions */
+typedef unsigned long phys_addr_t;
+
+#endif /* __ASSEMBLY */
+
+#endif /* _ASM_POWERPC_MMU_HASH64_H_ */

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ 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