LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Fastboot] [PATCH] Reserve crashkernel memory region
From: Michael Neuling @ 2006-04-28  7:06 UTC (permalink / raw)
  To: mohan; +Cc: fastboot, linuxppc-dev
In-Reply-To: <20060424061015.GA31320@in.ibm.com>

> Now kexec'ed kernel in a PPC64 machine does not reserve memory for
> crashkernel region. So kexec'ed kernel can not load kdump kernel
> reliably.

Owww 3 boots... scary :-)

> Attached kexec-tools patch reserves memory for kdump kernel by adding
> an entry in the reserve memory table. So while kexec'ed kernel is
> booting, it reserves memory for crashkernel region.

This logic is duplicated in prom_init.c.  

It'd be cool if the kernel parsed the command line early on (after
prom_init.c) and did the memory reserves there.  Then we wouldn't need
this logic in both the kexec tools and prom_init.c.

Mikey

^ permalink raw reply

* Re: [openib-general] Re: [PATCH 04/16] ehca: userspace support
From: Michael Ellerman @ 2006-04-28  7:11 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: linux-kernel, openib-general, linuxppc-dev, Christoph Raisch,
	Hoang-Nam Nguyen, Marcus Eder, Jörn Engel
In-Reply-To: <84144f020604272332s6101032cy6936096230f3637c@mail.gmail.com>

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

On Fri, 2006-04-28 at 09:32 +0300, Pekka Enberg wrote:
> Hi Heiko,
> 
> On 4/28/06, Heiko J Schick <info@schihei.de> wrote:
> > The problem I see with pr_debug() is that it could only activated via
> > a compile flag. To use the debug outputs you have to re-compile /
> > compile your own kernel.
> 
> Do you really need this heavy debug logging in the first place? You
> can use kprobes for arbitrary run-time inspection anyway, so logging
> everything seems wasteful.

Yeah, I really don't think you want to be running with that kind of
debugging gunk in a production kernel. Is someone who can't build their
own kernel really going to be able to make sense of the output?

cheers

-- 
Michael Ellerman
IBM OzLabs

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 191 bytes --]

^ permalink raw reply

* Re: [PATCH] Wire up *at syscalls
From: Paul Mackerras @ 2006-04-28  7:31 UTC (permalink / raw)
  To: David Woodhouse; +Cc: linuxppc-dev
In-Reply-To: <1145924011.16166.465.camel@shinybook.infradead.org>

David Woodhouse writes:

> Hm, do we really need that? How about something based on this instead...
> note that I used CONFIG_PPC_CELL because dependencies on CONFIG_*_MODULE
> in the static kernel are evil.

Nice idea, but you didn't change the syscall entry path to multiply
the syscall number by 24 instead of 16.  It would be nice to have a
way to do something like that but generate two separate tables instead
of a single table with 3 entries per syscall.

Paul.

^ permalink raw reply

* Re: 2.6.17-rc2-mm1
From: Andrew Morton @ 2006-04-28  8:20 UTC (permalink / raw)
  To: Martin Bligh; +Cc: linuxppc64-dev, linux-kernel
In-Reply-To: <4450F5AD.9030200@google.com>


(I did s/linux-kernel@google.com/linux-kernel@vger.kernel.org/)

Martin Bligh <mbligh@google.com> wrote:
>
> Still crashes in LTP on x86_64:
> (introduced in previous release)
> 
> http://test.kernel.org/abat/29674/debug/console.log

What a mess.  A doublefault inside an NMI watchdog timeout.  I think.  It's
hard to see.  Some CPUs are stuck on a CPU scheduler lock, others seem to
be stuck in flush_tlb_others.  One of these could be a consequence of the
other, or both could be a consequence of something else.

> Different panic on 2-way ppp64  blade, again during LTP.
> 
> http://test.kernel.org/abat/29675/debug/console.log
> 
>   Oops: Kernel access of bad area, sig: 11 [#1]
> SMP NR_CPUS=128 NUMA
> Modules linked in: evdev joydev st sr_mod ipv6 usbcore sg dm_mod
> NIP: C000000000048F0C LR: C0000000000AF854 CTR: 800000000000A984
> REGS: c0000000074af560 TRAP: 0300   Not tainted  (2.6.17-rc2-mm1-autokern1)
> MSR: 8000000000001032 <ME,IR,DR>  CR: 24002024  XER: 00000010
> DAR: C00001800056B0B0, DSISR: 0000000040010000
> TASK = c000000007460800[84] 'kswapd0' THREAD: c0000000074ac000 CPU: 1
> GPR00: 8000000000001032 C0000000074AF7E0 C000000000691420 C0000000007586A8
> GPR04: 000000000000000F 0000000000000000 0000000000000000 0000000000000000
> GPR08: C0000000FE80AAD8 C00001800056B080 0000000000000001 C0000000007586A8
> GPR12: 0000000024002024 C00000000056B280 0000000000000020 0000000000000020
> GPR16: 0000000000000020 0000000000000000 0000000000000000 000000000000000F
> GPR20: C0000000074AF860 0000000000000000 C0000000FFFF3098 0000000000000001
> GPR24: C0000000074AFE00 C00000000059FCC0 0000000000000001 C0000000007586A8
> GPR28: C000000000545680 0000000000000022 C0000000005A4DA8 C00000000056B080
> NIP [C000000000048F0C] .try_to_wake_up+0x98/0x598
> LR [C0000000000AF854] .add_to_swapped_list+0x23c/0x264
> Call Trace:
> [C0000000074AF7E0] [C0000000005A4DA8] 0xc0000000005a4da8 (unreliable)
> [C0000000074AF8F0] [C0000000000AF854] .add_to_swapped_list+0x23c/0x264
> [C0000000074AF990] [C000000000098290] .remove_mapping+0x88/0x174
> [C0000000074AFA20] [C000000000099340] .shrink_zone+0xc74/0xf9c
> [C0000000074AFD30] [C00000000009A008] .kswapd+0x3e4/0x54c
> [C0000000074AFED0] [C0000000000705C8] .kthread+0x174/0x1c4
> [C0000000074AFF90] [C000000000024AB0] .kernel_thread+0x4c/0x68
> Instruction dump:
> 3a810080 7d2000a6 79208042 f9340000 78008000 7c010164 e97b0008 ebfe8008
> eb9e8000 812b0010 79294da4 7d29fa14 <e8090030> 7fbc0214 7fa3eb78 4841f615
> -- 0:conmux-control -- time-stamp -- Apr/27/06  5:10:48 --

Well that's silly.  kswapd died trying to wake up kprefetchd.  That code's
bog-simple, so I'd assume something's gone wrong with a CPU scheduler data
structure.  So if there's a common strand here, it's breakage of sched data
structures by mtest01.   Let me see if I can provoke it here.

^ permalink raw reply

* patches for 2.6.18
From: Paul Mackerras @ 2006-04-28 10:17 UTC (permalink / raw)
  To: linuxppc-dev

If you have patches that aren't 2.6.17 material, but you would like to
see them in 2.6.18, now is the time to be posting them to the list, so
that I can put them in the powerpc.git tree, and they can get some
testing before 2.6.17 comes out.  Please don't wait for the 2-week
merge window to send them.  That 2-week merge window is the window for
me to send stuff to Linus, not the window for you to send stuff to me.

Paul.

^ permalink raw reply

* Re: [PATCH] Wire up *at syscalls
From: David Woodhouse @ 2006-04-28 10:24 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17489.50396.320494.589703@cargo.ozlabs.ibm.com>

On Fri, 2006-04-28 at 17:31 +1000, Paul Mackerras wrote:
> Nice idea, but you didn't change the syscall entry path to multiply
> the syscall number by 24 instead of 16. 

Indeed. Neither did I wire up the spu callbacks. It wasn't meant to be
applied as-is.

>  It would be nice to have a way to do something like that but generate
> two separate tables instead of a single table with 3 entries per
> syscall. 

Arnd apparently tried that once and it was icky. Perhaps we could do
something like this though...

.macro SPU adr
	.section .spu_callbacks,"a"
	.llong \adr		
	.previous
.endm

-- 
dwmw2

^ permalink raw reply

* Re: alignment exceptionhandler sleeps in invalid context
From: Paul Mackerras @ 2006-04-28 11:02 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev
In-Reply-To: <20060424173246.GA22318@suse.de>

Olaf Hering writes:

> I'm not sure where the bug is. Does it mean the network stack does
> something nasty, or is the exception handler itself broken? (probably the latter)
> This is 2.6.16.9 on a p270.

This patch should fix it, I hope.  If you can verify that it fixes it
I'll send it to Linus.

Paul.

diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h
index 3872e92..b02d858 100644
--- a/include/asm-powerpc/uaccess.h
+++ b/include/asm-powerpc/uaccess.h
@@ -179,7 +179,8 @@ do {								\
 #define __put_user_nocheck(x, ptr, size)			\
 ({								\
 	long __pu_err;						\
-	might_sleep();						\
+	if ((unsigned long)ptr < PAGE_OFFSET)			\
+		might_sleep();					\
 	__chk_user_ptr(ptr);					\
 	__put_user_size((x), (ptr), (size), __pu_err);		\
 	__pu_err;						\
@@ -259,7 +260,8 @@ ({								\
 	long __gu_err;						\
 	unsigned long __gu_val;					\
 	__chk_user_ptr(ptr);					\
-	might_sleep();						\
+	if ((unsigned long)ptr < PAGE_OFFSET)			\
+		might_sleep();					\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
 	(x) = (__typeof__(*(ptr)))__gu_val;			\
 	__gu_err;						\
@@ -271,7 +273,8 @@ ({								\
 	long __gu_err;						\
 	long long __gu_val;					\
 	__chk_user_ptr(ptr);					\
-	might_sleep();						\
+	if ((unsigned long)ptr < PAGE_OFFSET)			\
+		might_sleep();					\
 	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
 	(x) = (__typeof__(*(ptr)))__gu_val;			\
 	__gu_err;						\

^ permalink raw reply related

* Re: alignment exceptionhandler sleeps in invalid context
From: Olaf Hering @ 2006-04-28 11:19 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17489.63055.968862.256370@cargo.ozlabs.ibm.com>

 On Fri, Apr 28, Paul Mackeras wrote:

> Olaf Hering writes:
> 
> > I'm not sure where the bug is. Does it mean the network stack does
> > something nasty, or is the exception handler itself broken? (probably the latter)
> > This is 2.6.16.9 on a p270.
> 
> This patch should fix it, I hope.  If you can verify that it fixes it
> I'll send it to Linus.

I dont have a testcase, it just happend once on the p270.

^ permalink raw reply

* Re: FT u-boot shim
From: Paul Mackerras @ 2006-04-28 11:28 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1448E56E-1327-40D5-BE44-0DC103AC3E8A@kernel.crashing.org>

Kumar Gala writes:

> If we have a u-boot shim there are some questions that need answering:
> * where should the .dts live (hate duplicating the file both in u- 
> boot and kernel source tree)
> * how does build system find .dts
> * a Kconfig option to enable shim
> * assume done as a boot wrapper of sorts

What I think would be useful is a stand-alone tool that would take a
kernel and a dts and construct an image that is bootable on a given
board by its existing firmware.  That means there would either need to
be a version of the tool for each firmware, or alternatively a set of
command-line options to tell it what sort of firmware you have.

This wouldn't have to be done at kernel build time; it could be
potentially be done much later.  Hopefully then the board vendors
could take on the job of generating the dts.  In fact for some boards
the board-support package could be just the dts.

This tool would need to insert a suitable shim, which might actually
need to contain code to pull stuff out of a firmware-specific
structure such as a bd_t, and stuff it into the dts.  That should be
doable provided there is a convention about labels in the dts for
things such as memory size, ethernet mac address, etc.

Clearly it is neater if the firmware can supply the device-tree blob
directly, and just boot a raw kernel.  However, there will always be
situations where we don't get to choose the firmware, so I think we
need this tool.

Paul.

^ permalink raw reply

* sign extension for 32bit syscalls on ppc64
From: Christoph Hellwig @ 2006-04-28 13:12 UTC (permalink / raw)
  To: linuxppc-dev

For 32bit syscalls implemented in arch/powerpc/ we're doing our own
sign-extension where an int argument is passed as u32 in the prototype
and then casted to int later on:

asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t
__user * offset, u32 count)

{
	...
	ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
	..
}

OTOH various syscalls in the generic code don't do that and it seems to
still work fine.  I have patches for various new generic compat
routines, and they all seem to work fine without this sign extension.

What's the exact sign extention rules for ppc64?

^ permalink raw reply

* [PATCH] [2.6.18] powerpc iommu: minor cleanup
From: Olof Johansson @ 2006-04-28 13:57 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

A couple of minor renames:

* The iommu_table is no longer a part of the device node structure,
  so devnode_table is misleading
* Rename struct device *-variables to hwdev

Signed-off-by: Olof Johansson <olof@lixom.net>


Index: powerpc/arch/powerpc/kernel/pci_iommu.c
===================================================================
--- powerpc.orig/arch/powerpc/kernel/pci_iommu.c
+++ powerpc/arch/powerpc/kernel/pci_iommu.c
@@ -44,16 +44,16 @@
  */
 #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
 
-static inline struct iommu_table *devnode_table(struct device *dev)
+static inline struct iommu_table *device_to_table(struct device *hwdev)
 {
 	struct pci_dev *pdev;
 
-	if (!dev) {
+	if (!hwdev) {
 		pdev = ppc64_isabridge_dev;
 		if (!pdev)
 			return NULL;
 	} else
-		pdev = to_pci_dev(dev);
+		pdev = to_pci_dev(hwdev);
 
 	return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
 }
@@ -85,14 +85,14 @@ static inline unsigned long device_to_ma
 static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
-	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
+	return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
 			device_to_mask(hwdev), flag);
 }
 
 static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
+	iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
 }
 
 /* Creates TCEs for a user provided buffer.  The user buffer must be 
@@ -104,7 +104,7 @@ static void pci_iommu_free_coherent(stru
 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 		size_t size, enum dma_data_direction direction)
 {
-	return iommu_map_single(devnode_table(hwdev), vaddr, size,
+	return iommu_map_single(device_to_table(hwdev), vaddr, size,
 			        device_to_mask(hwdev), direction);
 }
 
@@ -112,27 +112,27 @@ static dma_addr_t pci_iommu_map_single(s
 static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
 		size_t size, enum dma_data_direction direction)
 {
-	iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
+	iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
 }
 
 
 static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
+	return iommu_map_sg(pdev, device_to_table(pdev), sglist,
 			nelems, device_to_mask(pdev), direction);
 }
 
 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
+	iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
 }
 
 /* We support DMA to/from any memory page via the iommu */
 static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	struct iommu_table *tbl = devnode_table(dev);
+	struct iommu_table *tbl = device_to_table(dev);
 
 	if (!tbl || tbl->it_offset > mask) {
 		printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");

^ permalink raw reply

* [PATCH] [2.6.18] powerpc: kill union tce_entry
From: Olof Johansson @ 2006-04-28 14:08 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, sfr

It's been long overdue to kill the union tce_entry in the pSeries/iSeries
TCE code, especially since I asked the Summit guys to do it on the code
they copied from us.

Also, while I was at it, I cleaned up some whitespace.

Built and booted on pSeries, built on iSeries.


Signed-off-by: Olof Johansson <olof@lixom.net>


Index: powerpc/arch/powerpc/platforms/iseries/iommu.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/iseries/iommu.c
+++ powerpc/arch/powerpc/platforms/iseries/iommu.c
@@ -4,6 +4,7 @@
  * Rewrite, cleanup:
  *
  * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
  *
  * Dynamic DMA mapping support, iSeries-specific parts.
  *
@@ -43,30 +44,28 @@ static void tce_build_iSeries(struct iom
 		unsigned long uaddr, enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce;
+	u64 tce, rpn;
 
 	index <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
 	while (npages--) {
-		tce.te_word = 0;
-		tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
+		rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
+		tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		if (tbl->it_type == TCE_VB) {
 			/* Virtual Bus */
-			tce.te_bits.tb_valid = 1;
-			tce.te_bits.tb_allio = 1;
+			tce |= TCE_VALID|TCE_ALLIO;
 			if (direction != DMA_TO_DEVICE)
-				tce.te_bits.tb_rdwr = 1;
+				tce |= TCE_VB_WRITE;
 		} else {
 			/* PCI Bus */
-			tce.te_bits.tb_rdwr = 1; /* Read allowed */
+			tce |= TCE_PCI_READ; /* Read allowed */
 			if (direction != DMA_TO_DEVICE)
-				tce.te_bits.tb_pciwr = 1;
+				tce |= TCE_PCI_WRITE;
 		}
 
-		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
-				tce.te_word);
+		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
 		if (rc)
 			panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
 					rc);
@@ -124,7 +123,7 @@ void iommu_table_getparms_iSeries(unsign
 
 	/* itc_size is in pages worth of table, it_size is in # of entries */
 	tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) /
-			sizeof(union tce_entry)) >> TCE_PAGE_FACTOR;
+			TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR;
 	tbl->it_busno = parms->itc_busno;
 	tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR;
 	tbl->it_index = parms->itc_index;
Index: powerpc/arch/powerpc/platforms/pseries/iommu.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pseries/iommu.c
+++ powerpc/arch/powerpc/platforms/pseries/iommu.c
@@ -1,23 +1,24 @@
 /*
  * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
  *
- * Rewrite, cleanup: 
+ * Rewrite, cleanup:
  *
  * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
  *
  * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
  *
- * 
+ *
  * 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.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
@@ -49,52 +50,46 @@
 
 #define DBG(fmt...)
 
-static void tce_build_pSeries(struct iommu_table *tbl, long index, 
-			      long npages, unsigned long uaddr, 
+static void tce_build_pSeries(struct iommu_table *tbl, long index,
+			      long npages, unsigned long uaddr,
 			      enum dma_data_direction direction)
 {
-	union tce_entry t;
-	union tce_entry *tp;
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
 
 	index <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	t.te_word = 0;
-	t.te_rdwr = 1; // Read allowed 
+	proto_tce = TCE_PCI_READ; // Read allowed
 
 	if (direction != DMA_TO_DEVICE)
-		t.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
-	tp = ((union tce_entry *)tbl->it_base) + index;
+	tcep = ((u64 *)tbl->it_base) + index;
 
 	while (npages--) {
 		/* can't move this out since we might cross LMB boundary */
-		t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	
-		tp->te_word = t.te_word;
+		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		uaddr += TCE_PAGE_SIZE;
-		tp++;
+		tcep++;
 	}
 }
 
 
 static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 {
-	union tce_entry t;
-	union tce_entry *tp;
+	u64 *tcep;
 
 	npages <<= TCE_PAGE_FACTOR;
 	index <<= TCE_PAGE_FACTOR;
 
-	t.te_word = 0;
-	tp  = ((union tce_entry *)tbl->it_base) + index;
-		
-	while (npages--) {
-		tp->te_word = t.te_word;
-		
-		tp++;
-	}
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--)
+		*(tcep++) = 0;
 }
 
 
@@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct i
 				enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce;
+	u64 proto_tce, tce;
+	u64 rpn;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	tce.te_rdwr = 1;
+	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12, 
-				   tce.te_word );
-		
+		tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
+
 		if (rc && printk_ratelimit()) {
 			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
+			printk("\ttce val = 0x%lx\n", tce );
 			show_stack(current, (unsigned long *)__get_SP());
 		}
-			
+
 		tcenum++;
-		tce.te_rpn++;
+		rpn++;
 	}
 }
 
-static DEFINE_PER_CPU(void *, tce_page) = NULL;
+static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
 
 static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				     long npages, unsigned long uaddr,
 				     enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce, *tcep;
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
 	long l, limit;
 
 	if (TCE_PAGE_FACTOR == 0 && npages == 1)
@@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(str
 	 * from iommu_alloc{,_sg}()
 	 */
 	if (!tcep) {
-		tcep = (void *)__get_free_page(GFP_ATOMIC);
+		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
 		/* If allocation fails, fall back to the loop implementation */
 		if (!tcep)
 			return tce_build_pSeriesLP(tbl, tcenum, npages,
@@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(str
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	tce.te_rdwr = 1;
+	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
 	/* We can map max one pageful of TCEs at a time */
 	do {
@@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(str
 		 * Set up the page with TCE data, looping through and setting
 		 * the values.
 		 */
-		limit = min_t(long, npages, 4096/sizeof(union tce_entry));
+		limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
 
 		for (l = 0; l < limit; l++) {
-			tcep[l] = tce;
-			tce.te_rpn++;
+			tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+			rpn++;
 		}
 
 		rc = plpar_tce_put_indirect((u64)tbl->it_index,
@@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(str
 		printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 		printk("\tnpages  = 0x%lx\n", (u64)npages);
-		printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+		printk("\ttce[0] val = 0x%lx\n", tcep[0]);
 		show_stack(current, (unsigned long *)__get_SP());
 	}
 }
@@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(str
 static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
 	u64 rc;
-	union tce_entry tce;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index,
-				   (u64)tcenum << 12,
-				   tce.te_word);
+		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
 
 		if (rc && printk_ratelimit()) {
 			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
 			show_stack(current, (unsigned long *)__get_SP());
 		}
 
@@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct io
 static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
 	u64 rc;
-	union tce_entry tce;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-
-	rc = plpar_tce_stuff((u64)tbl->it_index,
-			   (u64)tcenum << 12,
-			   tce.te_word,
-			   npages);
+	rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
 
 	if (rc && printk_ratelimit()) {
 		printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
 		printk("\trc      = %ld\n", rc);
 		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 		printk("\tnpages  = 0x%lx\n", (u64)npages);
-		printk("\ttce val = 0x%lx\n", tce.te_word );
 		show_stack(current, (unsigned long *)__get_SP());
 	}
 }
 
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
-				 struct iommu_table *tbl) 
+				 struct iommu_table *tbl)
 {
 	struct device_node *node;
 	unsigned long *basep;
@@ -275,16 +257,16 @@ static void iommu_table_setparms(struct 
 	memset((void *)tbl->it_base, 0, *sizep);
 
 	tbl->it_busno = phb->bus->number;
-	
+
 	/* Units of tce entries */
 	tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
-	
+
 	/* Test if we are going over 2GB of DMA space */
 	if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
 		udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
-		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
+		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
 	}
-	
+
 	phb->dma_window_base_cur += phb->dma_window_size;
 
 	/* Set the tce table size - measured in entries */
@@ -442,7 +424,7 @@ static void iommu_bus_setup_pSeriesLP(st
 
 		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
 						    GFP_KERNEL);
-	
+
 		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
 
 		ppci->iommu_table = iommu_init_table(tbl);
Index: powerpc/include/asm-powerpc/tce.h
===================================================================
--- powerpc.orig/include/asm-powerpc/tce.h
+++ powerpc/include/asm-powerpc/tce.h
@@ -35,32 +35,15 @@
 #define TCE_PAGE_SIZE	(1 << TCE_SHIFT)
 #define TCE_PAGE_FACTOR	(PAGE_SHIFT - TCE_SHIFT)
 
+#define TCE_ENTRY_SIZE		8		/* each TCE is 64 bits */
 
-/* tce_entry
- * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
- * abstracted so layout is irrelevant.
- */
-union tce_entry {
-   	unsigned long te_word;
-	struct {
-		unsigned int  tb_cacheBits :6;	/* Cache hash bits - not used */
-		unsigned int  tb_rsvd      :6;
-		unsigned long tb_rpn       :40;	/* Real page number */
-		unsigned int  tb_valid     :1;	/* Tce is valid (vb only) */
-		unsigned int  tb_allio     :1;	/* Tce is valid for all lps (vb only) */
-		unsigned int  tb_lpindex   :8;	/* LpIndex for user of TCE (vb only) */
-		unsigned int  tb_pciwr     :1;	/* Write allowed (pci only) */
-		unsigned int  tb_rdwr      :1;	/* Read allowed  (pci), Write allowed (vb) */
-	} te_bits;
-#define te_cacheBits te_bits.tb_cacheBits
-#define te_rpn       te_bits.tb_rpn
-#define te_valid     te_bits.tb_valid
-#define te_allio     te_bits.tb_allio
-#define te_lpindex   te_bits.tb_lpindex
-#define te_pciwr     te_bits.tb_pciwr
-#define te_rdwr      te_bits.tb_rdwr
-};
-
+#define TCE_RPN_MASK		0xfffffffffful  /* 40-bit RPN (4K pages) */
+#define TCE_RPN_SHIFT		12
+#define TCE_VALID		0x200		/* TCE valid */
+#define TCE_ALLIO		0x100		/* TCE valid for all lpars */
+#define TCE_PCI_WRITE		0x2		/* write from PCI allowed */
+#define TCE_PCI_READ		0x1		/* read from PCI allowed */
+#define TCE_VB_WRITE		0x1		/* write from VB allowed */
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_TCE_H */

^ permalink raw reply

* Re: alignment exceptionhandler sleeps in invalid context
From: Kumar Gala @ 2006-04-28 14:22 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20060428111942.GA15646@suse.de>


On Apr 28, 2006, at 6:19 AM, Olaf Hering wrote:

>  On Fri, Apr 28, Paul Mackeras wrote:
>
>> Olaf Hering writes:
>>
>>> I'm not sure where the bug is. Does it mean the network stack does
>>> something nasty, or is the exception handler itself broken?  
>>> (probably the latter)
>>> This is 2.6.16.9 on a p270.
>>
>> This patch should fix it, I hope.  If you can verify that it fixes it
>> I'll send it to Linus.
>
> I dont have a testcase, it just happend once on the p270.

I was going to ask how this was actually hit.  It seems odd that we  
would have an alignment error in the network stack.  From the oops  
can we determine what the instruction was that faulted and what  
address it was trying to access.

- k

^ permalink raw reply

* Re: [PATCH] Wire up *at syscalls
From: Andreas Schwab @ 2006-04-28 14:42 UTC (permalink / raw)
  To: David Woodhouse; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <1146219867.10561.39.camel@shinybook.infradead.org>

David Woodhouse <dwmw2@infradead.org> writes:

> On Fri, 2006-04-28 at 17:31 +1000, Paul Mackerras wrote:
>> Nice idea, but you didn't change the syscall entry path to multiply
>> the syscall number by 24 instead of 16. 
>
> Indeed. Neither did I wire up the spu callbacks. It wasn't meant to be
> applied as-is.
>
>>  It would be nice to have a way to do something like that but generate
>> two separate tables instead of a single table with 3 entries per
>> syscall. 
>
> Arnd apparently tried that once and it was icky.

void *spu_syscall_table[] = {
#define SYSCALL(func)		sys_ni_syscall
#define SYSCALL_SPU(func)       sys_##func
#define COMPAT_SYS(func)	sys_ni_syscall
#define COMPAT_SYS_SPU(func)	sys_##func
#define PPC_SYS(func)		sys_ni_syscall
#define PPC_SYS_SPU(func)	ppc_##func
#define OLDSYS(func)		sys_ni_syscall
#define SYS32ONLY(func)		sys_ni_syscall
#define SYSX(f, f3264, f32)	f
#include <asm/systbl.h>
}

where <asm/systbl.h> contains the bopy of arch/powerpc/kernel/systbl.S
after _GLOBAL(sys_call_table), and the latter is changed to include the
former.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* Re: [PATCH] convert powermac ide blink to new led infrastructure
From: Johannes Berg @ 2006-04-28 15:15 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, debian-powerpc
In-Reply-To: <1146235779.19164.109.camel@localhost>

[resent slightly different patch that adds a comment over the original
version]

This patch removes the old pmac ide led blink code and
adds generic LED subsystem support for the LED.

Ben: I removed the retry code that was present in the original. I guess
LEDs aren't really too important but if it really is necessary please
tell me and I'll add it back.

Also, I don't have any suspend handling things. It doesn't appear to be
necessary, how do I find out?

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- linux-2.6.orig/drivers/ide/Kconfig	2006-04-28 13:13:38.777288704 +0200
+++ linux-2.6/drivers/ide/Kconfig	2006-04-28 13:13:48.797288704 +0200
@@ -773,13 +773,6 @@ config BLK_DEV_IDEDMA_PMAC
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
 
-config BLK_DEV_IDE_PMAC_BLINK
-	bool "Blink laptop LED on drive activity"
-	depends on BLK_DEV_IDE_PMAC && ADB_PMU
-	help
-	  This option enables the use of the sleep LED as a hard drive
-	  activity LED.
-
 config BLK_DEV_IDE_SWARM
 	tristate "IDE for Sibyte evaluation boards"
 	depends on SIBYTE_SB1xxx_SOC
--- linux-2.6.orig/drivers/ide/ppc/pmac.c	2006-04-28 13:13:58.967288704 +0200
+++ linux-2.6/drivers/ide/ppc/pmac.c	2006-04-28 13:17:01.657288704 +0200
@@ -421,107 +421,6 @@ static void pmac_ide_kauai_selectproc(id
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 /*
- * Below is the code for blinking the laptop LED along with hard
- * disk activity.
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-
-/* Set to 50ms minimum led-on time (also used to limit frequency
- * of requests sent to the PMU
- */
-#define PMU_HD_BLINK_TIME	(HZ/50)
-
-static struct adb_request pmu_blink_on, pmu_blink_off;
-static spinlock_t pmu_blink_lock;
-static unsigned long pmu_blink_stoptime;
-static int pmu_blink_ledstate;
-static struct timer_list pmu_blink_timer;
-static int pmu_ide_blink_enabled;
-
-
-static void
-pmu_hd_blink_timeout(unsigned long data)
-{
-	unsigned long flags;
-	
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-
-	/* We may have been triggered again in a racy way, check
-	 * that we really want to switch it off
-	 */
-	if (time_after(pmu_blink_stoptime, jiffies))
-		goto done;
-
-	/* Previous req. not complete, try 100ms more */
-	if (pmu_blink_off.complete == 0)
-		mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME);
-	else if (pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0);
-		pmu_blink_ledstate = 0;
-	}
-done:
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static void
-pmu_hd_kick_blink(void *data, int rw)
-{
-	unsigned long flags;
-	
-	pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME;
-	wmb();
-	mod_timer(&pmu_blink_timer, pmu_blink_stoptime);
-	/* Fast path when LED is already ON */
-	if (pmu_blink_ledstate == 1)
-		return;
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-	if (pmu_blink_on.complete && !pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1);
-		pmu_blink_ledstate = 1;
-	}
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static int
-pmu_hd_blink_init(void)
-{
-	struct device_node *dt;
-	const char *model;
-
-	/* Currently, I only enable this feature on KeyLargo based laptops,
-	 * older laptops may support it (at least heathrow/paddington) but
-	 * I don't feel like loading those venerable old machines with so
-	 * much additional interrupt & PMU activity...
-	 */
-	if (pmu_get_model() != PMU_KEYLARGO_BASED)
-		return 0;
-	
-	dt = of_find_node_by_path("/");
-	if (dt == NULL)
-		return 0;
-	model = (const char *)get_property(dt, "model", NULL);
-	if (model == NULL)
-		return 0;
-	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
-	    strncmp(model, "iBook", strlen("iBook")) != 0) {
-		of_node_put(dt);
-	    	return 0;
-	}
-	of_node_put(dt);
-
-	pmu_blink_on.complete = 1;
-	pmu_blink_off.complete = 1;
-	spin_lock_init(&pmu_blink_lock);
-	init_timer(&pmu_blink_timer);
-	pmu_blink_timer.function = pmu_hd_blink_timeout;
-
-	return 1;
-}
-
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
-/*
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
@@ -1190,23 +1089,6 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
 	pmif->timings[0] = 0;
 	pmif->timings[1] = 0;
 	
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	/* Note: This code will be called for every hwif, thus we'll
-	 * try several time to stop the LED blinker timer,  but that
-	 * should be harmless
-	 */
-	if (pmu_ide_blink_enabled) {
-		unsigned long flags;
-
-		/* Make sure we don't hit the PMU blink */
-		spin_lock_irqsave(&pmu_blink_lock, flags);
-		if (pmu_blink_ledstate)
-			del_timer(&pmu_blink_timer);
-		pmu_blink_ledstate = 0;
-		spin_unlock_irqrestore(&pmu_blink_lock, flags);
-	}
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
 	disable_irq(pmif->irq);
 
 	/* The media bay will handle itself just fine */
@@ -1374,13 +1256,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *p
 		hwif->selectproc = pmac_ide_selectproc;
 	hwif->speedproc = pmac_ide_tune_chipset;
 
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	pmu_ide_blink_enabled = pmu_hd_blink_init();
-
-	if (pmu_ide_blink_enabled)
-		hwif->led_act = pmu_hd_kick_blink;
-#endif
-
 	printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
 	       hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
 	       pmif->mediabay ? " (mediabay)" : "", hwif->irq);
--- linux-2.6.orig/drivers/macintosh/Kconfig	2006-04-28 13:31:24.347288704 +0200
+++ linux-2.6/drivers/macintosh/Kconfig	2006-04-28 13:31:43.677288704 +0200
@@ -78,6 +78,16 @@ config ADB_PMU
 	  this device; you should do so if your machine is one of those
 	  mentioned above.
 
+config ADB_PMU_LED
+	bool "Support for the Power/iBook front LED"
+	depends on LEDS_CLASS && ADB_PMU
+	help
+	  Support the front LED on Power/iBooks as a generic LED that can
+	  be triggered by any of the supported triggers. To get the
+	  behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this
+	  and the ide-disk LED trigger and configure appropriately through
+	  sysfs.
+
 config PMAC_SMU
 	bool "Support for SMU  based PowerMacs"
 	depends on PPC_PMAC64
--- linux-2.6.orig/drivers/macintosh/Makefile	2006-04-28 13:35:17.977288704 +0200
+++ linux-2.6/drivers/macintosh/Makefile	2006-04-28 13:46:44.887288704 +0200
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
 obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o
 obj-$(CONFIG_PMAC_SMU)		+= smu.o
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/macintosh/via-pmu-led.c	2006-04-28 13:56:28.537288704 +0200
@@ -0,0 +1,80 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/prom.h>
+#include "via-pmu-led.h"
+
+static spinlock_t pmu_blink_lock;
+static struct adb_request pmu_blink_req;
+
+static void pmu_led_off(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	/* I currently ignore the result of this request */
+	pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, 0);
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_on(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, 1);
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_set(struct led_classdev *led_cdev,
+			 enum led_brightness brightness)
+{
+	switch (brightness) {
+	case LED_OFF:
+		pmu_led_off();
+		break;
+	case LED_FULL:
+		pmu_led_on();
+		break;
+	default:
+		/* ignore other levels */
+		break;
+	}
+}
+
+static struct led_classdev pmu_led = {
+	.name = "pmu-front-led",
+	.brightness_set = pmu_led_set,
+};
+
+int pmu_led_init(void)
+{
+	/* this is only called for keylargo based systems */
+	struct device_node *dt;
+	const char *model;
+
+	dt = of_find_node_by_path("/");
+	if (dt == NULL)
+		return -ENODEV;
+	model = (const char *)get_property(dt, "model", NULL);
+	if (model == NULL)
+		return -ENODEV;
+	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
+	    strncmp(model, "iBook", strlen("iBook")) != 0) {
+		of_node_put(dt);
+		/* silently ignore */
+		return 0;
+	}
+	of_node_put(dt);
+
+	spin_lock_init(&pmu_blink_lock);
+	return led_classdev_register(NULL, &pmu_led);
+}
+
+void pmu_led_exit(void)
+{
+	led_classdev_unregister(&pmu_led);
+}
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/macintosh/via-pmu-led.h	2006-04-28 13:48:19.177288704 +0200
@@ -0,0 +1,18 @@
+#ifndef __VIA_PMU_LED_H
+#define __VIA_PMU_LED_H
+#include <config/adb/pmu/led.h>
+
+#ifdef CONFIG_ADB_PMU_LED
+extern int pmu_led_init(void);
+extern void pmu_led_exit(void);
+#else
+static inline int pmu_led_init(void)
+{
+	return 0;
+}
+static inline void pmu_led_exit(void)
+{
+}
+#endif /* CONFIG_ADB_PMU_LED */
+
+#endif /* __VIA_PMU_LED_H */
--- linux-2.6.orig/drivers/macintosh/via-pmu.c	2006-04-28 13:09:02.197288704 +0200
+++ linux-2.6/drivers/macintosh/via-pmu.c	2006-04-28 16:55:57.877288704 +0200
@@ -69,6 +69,8 @@
 #include <asm/open_pic.h>
 #endif
 
+#include "via-pmu-led.h"
+
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
@@ -2896,11 +2898,30 @@ static int __init init_pmu_sysfs(void)
 		printk(KERN_ERR "Failed registering PMU sys driver\n");
 		return -ENODEV;
 	}
+
 	return 0;
 }
 
 subsys_initcall(init_pmu_sysfs);
 
+static int __init init_pmu_led(void)
+{
+	/* Only enable this feature on KeyLargo based laptops, older
+	 * laptops may support it (at least heathrow/paddington) but
+	 * I don't feel like loading those venerable old machines with
+	 * so much additional interrupt & PMU activity...
+	 */
+	if (pmu_kind == PMU_KEYLARGO_BASED) {
+		if (pmu_led_init()) {
+			printk(KERN_WARNING "via-pmu: LED failed to init\n");
+		}
+	}
+
+	return 0;
+}
+
+late_initcall(init_pmu_led);
+
 EXPORT_SYMBOL(pmu_request);
 EXPORT_SYMBOL(pmu_queue_request);
 EXPORT_SYMBOL(pmu_poll);

^ permalink raw reply

* [PATCH] convert powermac ide blink to new led infrastructure
From: Johannes Berg @ 2006-04-28 14:49 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, debian-powerpc

This patch removes the old pmac ide led blink code and adds generic LED
subsystem support for the LED.

Ben: I removed the retry code that was present in the original. I guess
LEDs aren't really too important but if it really is necessary please
tell me and I'll add it back.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- linux-2.6.orig/drivers/ide/Kconfig	2006-04-28 13:13:38.777288704 +0200
+++ linux-2.6/drivers/ide/Kconfig	2006-04-28 13:13:48.797288704 +0200
@@ -773,13 +773,6 @@ config BLK_DEV_IDEDMA_PMAC
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
 
-config BLK_DEV_IDE_PMAC_BLINK
-	bool "Blink laptop LED on drive activity"
-	depends on BLK_DEV_IDE_PMAC && ADB_PMU
-	help
-	  This option enables the use of the sleep LED as a hard drive
-	  activity LED.
-
 config BLK_DEV_IDE_SWARM
 	tristate "IDE for Sibyte evaluation boards"
 	depends on SIBYTE_SB1xxx_SOC
--- linux-2.6.orig/drivers/ide/ppc/pmac.c	2006-04-28 13:13:58.967288704 +0200
+++ linux-2.6/drivers/ide/ppc/pmac.c	2006-04-28 13:17:01.657288704 +0200
@@ -421,107 +421,6 @@ static void pmac_ide_kauai_selectproc(id
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
 /*
- * Below is the code for blinking the laptop LED along with hard
- * disk activity.
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-
-/* Set to 50ms minimum led-on time (also used to limit frequency
- * of requests sent to the PMU
- */
-#define PMU_HD_BLINK_TIME	(HZ/50)
-
-static struct adb_request pmu_blink_on, pmu_blink_off;
-static spinlock_t pmu_blink_lock;
-static unsigned long pmu_blink_stoptime;
-static int pmu_blink_ledstate;
-static struct timer_list pmu_blink_timer;
-static int pmu_ide_blink_enabled;
-
-
-static void
-pmu_hd_blink_timeout(unsigned long data)
-{
-	unsigned long flags;
-	
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-
-	/* We may have been triggered again in a racy way, check
-	 * that we really want to switch it off
-	 */
-	if (time_after(pmu_blink_stoptime, jiffies))
-		goto done;
-
-	/* Previous req. not complete, try 100ms more */
-	if (pmu_blink_off.complete == 0)
-		mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME);
-	else if (pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0);
-		pmu_blink_ledstate = 0;
-	}
-done:
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static void
-pmu_hd_kick_blink(void *data, int rw)
-{
-	unsigned long flags;
-	
-	pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME;
-	wmb();
-	mod_timer(&pmu_blink_timer, pmu_blink_stoptime);
-	/* Fast path when LED is already ON */
-	if (pmu_blink_ledstate == 1)
-		return;
-	spin_lock_irqsave(&pmu_blink_lock, flags);
-	if (pmu_blink_on.complete && !pmu_blink_ledstate) {
-		pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1);
-		pmu_blink_ledstate = 1;
-	}
-	spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static int
-pmu_hd_blink_init(void)
-{
-	struct device_node *dt;
-	const char *model;
-
-	/* Currently, I only enable this feature on KeyLargo based laptops,
-	 * older laptops may support it (at least heathrow/paddington) but
-	 * I don't feel like loading those venerable old machines with so
-	 * much additional interrupt & PMU activity...
-	 */
-	if (pmu_get_model() != PMU_KEYLARGO_BASED)
-		return 0;
-	
-	dt = of_find_node_by_path("/");
-	if (dt == NULL)
-		return 0;
-	model = (const char *)get_property(dt, "model", NULL);
-	if (model == NULL)
-		return 0;
-	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
-	    strncmp(model, "iBook", strlen("iBook")) != 0) {
-		of_node_put(dt);
-	    	return 0;
-	}
-	of_node_put(dt);
-
-	pmu_blink_on.complete = 1;
-	pmu_blink_off.complete = 1;
-	spin_lock_init(&pmu_blink_lock);
-	init_timer(&pmu_blink_timer);
-	pmu_blink_timer.function = pmu_hd_blink_timeout;
-
-	return 1;
-}
-
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
-/*
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
@@ -1190,23 +1089,6 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
 	pmif->timings[0] = 0;
 	pmif->timings[1] = 0;
 	
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	/* Note: This code will be called for every hwif, thus we'll
-	 * try several time to stop the LED blinker timer,  but that
-	 * should be harmless
-	 */
-	if (pmu_ide_blink_enabled) {
-		unsigned long flags;
-
-		/* Make sure we don't hit the PMU blink */
-		spin_lock_irqsave(&pmu_blink_lock, flags);
-		if (pmu_blink_ledstate)
-			del_timer(&pmu_blink_timer);
-		pmu_blink_ledstate = 0;
-		spin_unlock_irqrestore(&pmu_blink_lock, flags);
-	}
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
 	disable_irq(pmif->irq);
 
 	/* The media bay will handle itself just fine */
@@ -1374,13 +1256,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *p
 		hwif->selectproc = pmac_ide_selectproc;
 	hwif->speedproc = pmac_ide_tune_chipset;
 
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-	pmu_ide_blink_enabled = pmu_hd_blink_init();
-
-	if (pmu_ide_blink_enabled)
-		hwif->led_act = pmu_hd_kick_blink;
-#endif
-
 	printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
 	       hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
 	       pmif->mediabay ? " (mediabay)" : "", hwif->irq);
--- linux-2.6.orig/drivers/macintosh/Kconfig	2006-04-28 13:31:24.347288704 +0200
+++ linux-2.6/drivers/macintosh/Kconfig	2006-04-28 13:31:43.677288704 +0200
@@ -78,6 +78,16 @@ config ADB_PMU
 	  this device; you should do so if your machine is one of those
 	  mentioned above.
 
+config ADB_PMU_LED
+	bool "Support for the Power/iBook front LED"
+	depends on LEDS_CLASS && ADB_PMU
+	help
+	  Support the front LED on Power/iBooks as a generic LED that can
+	  be triggered by any of the supported triggers. To get the
+	  behaviour of the old CONFIG_BLK_DEV_IDE_PMAC_BLINK, select this
+	  and the ide-disk LED trigger and configure appropriately through
+	  sysfs.
+
 config PMAC_SMU
 	bool "Support for SMU  based PowerMacs"
 	depends on PPC_PMAC64
--- linux-2.6.orig/drivers/macintosh/Makefile	2006-04-28 13:35:17.977288704 +0200
+++ linux-2.6/drivers/macintosh/Makefile	2006-04-28 13:46:44.887288704 +0200
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
 obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o
 obj-$(CONFIG_PMAC_SMU)		+= smu.o
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/macintosh/via-pmu-led.c	2006-04-28 13:56:28.537288704 +0200
@@ -0,0 +1,80 @@
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/leds.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/prom.h>
+#include "via-pmu-led.h"
+
+static spinlock_t pmu_blink_lock;
+static struct adb_request pmu_blink_req;
+
+static void pmu_led_off(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	/* I currently ignore the result of this request */
+	pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, 0);
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_on(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_blink_lock, flags);
+	pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, 1);
+	spin_unlock_irqrestore(&pmu_blink_lock, flags);
+}
+
+static void pmu_led_set(struct led_classdev *led_cdev,
+			 enum led_brightness brightness)
+{
+	switch (brightness) {
+	case LED_OFF:
+		pmu_led_off();
+		break;
+	case LED_FULL:
+		pmu_led_on();
+		break;
+	default:
+		/* ignore other levels */
+		break;
+	}
+}
+
+static struct led_classdev pmu_led = {
+	.name = "pmu-front-led",
+	.brightness_set = pmu_led_set,
+};
+
+int pmu_led_init(void)
+{
+	/* this is only called for keylargo based systems */
+	struct device_node *dt;
+	const char *model;
+
+	dt = of_find_node_by_path("/");
+	if (dt == NULL)
+		return -ENODEV;
+	model = (const char *)get_property(dt, "model", NULL);
+	if (model == NULL)
+		return -ENODEV;
+	if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
+	    strncmp(model, "iBook", strlen("iBook")) != 0) {
+		of_node_put(dt);
+		/* silently ignore */
+		return 0;
+	}
+	of_node_put(dt);
+
+	spin_lock_init(&pmu_blink_lock);
+	return led_classdev_register(NULL, &pmu_led);
+}
+
+void pmu_led_exit(void)
+{
+	led_classdev_unregister(&pmu_led);
+}
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/macintosh/via-pmu-led.h	2006-04-28 13:48:19.177288704 +0200
@@ -0,0 +1,18 @@
+#ifndef __VIA_PMU_LED_H
+#define __VIA_PMU_LED_H
+#include <config/adb/pmu/led.h>
+
+#ifdef CONFIG_ADB_PMU_LED
+extern int pmu_led_init(void);
+extern void pmu_led_exit(void);
+#else
+static inline int pmu_led_init(void)
+{
+	return 0;
+}
+static inline void pmu_led_exit(void)
+{
+}
+#endif /* CONFIG_ADB_PMU_LED */
+
+#endif /* __VIA_PMU_LED_H */
--- linux-2.6.orig/drivers/macintosh/via-pmu.c	2006-04-28 13:09:02.197288704 +0200
+++ linux-2.6/drivers/macintosh/via-pmu.c	2006-04-28 15:58:45.497288704 +0200
@@ -69,6 +69,8 @@
 #include <asm/open_pic.h>
 #endif
 
+#include "via-pmu-led.h"
+
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
@@ -2896,11 +2898,25 @@ static int __init init_pmu_sysfs(void)
 		printk(KERN_ERR "Failed registering PMU sys driver\n");
 		return -ENODEV;
 	}
+
 	return 0;
 }
 
 subsys_initcall(init_pmu_sysfs);
 
+static int __init init_pmu_led(void)
+{
+	if (pmu_kind == PMU_KEYLARGO_BASED) {
+		if (pmu_led_init()) {
+			printk(KERN_WARNING "via-pmu: LED failed to init\n");
+		}
+	}
+
+	return 0;
+}
+
+late_initcall(init_pmu_led);
+
 EXPORT_SYMBOL(pmu_request);
 EXPORT_SYMBOL(pmu_queue_request);
 EXPORT_SYMBOL(pmu_poll);

^ permalink raw reply

* Re: FT u-boot shim
From: Kumar Gala @ 2006-04-28 16:01 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev@ozlabs.org list
In-Reply-To: <17489.64606.75404.314368@cargo.ozlabs.ibm.com>


On Apr 28, 2006, at 6:28 AM, Paul Mackerras wrote:

> Kumar Gala writes:
>
>> If we have a u-boot shim there are some questions that need  
>> answering:
>> * where should the .dts live (hate duplicating the file both in u-
>> boot and kernel source tree)
>> * how does build system find .dts
>> * a Kconfig option to enable shim
>> * assume done as a boot wrapper of sorts
>
> What I think would be useful is a stand-alone tool that would take a
> kernel and a dts and construct an image that is bootable on a given
> board by its existing firmware.  That means there would either need to
> be a version of the tool for each firmware, or alternatively a set of
> command-line options to tell it what sort of firmware you have.
>
> This wouldn't have to be done at kernel build time; it could be
> potentially be done much later.  Hopefully then the board vendors
> could take on the job of generating the dts.  In fact for some boards
> the board-support package could be just the dts.
>
> This tool would need to insert a suitable shim, which might actually
> need to contain code to pull stuff out of a firmware-specific
> structure such as a bd_t, and stuff it into the dts.  That should be
> doable provided there is a convention about labels in the dts for
> things such as memory size, ethernet mac address, etc.
>
> Clearly it is neater if the firmware can supply the device-tree blob
> directly, and just boot a raw kernel.  However, there will always be
> situations where we don't get to choose the firmware, so I think we
> need this tool.

I agree with this (after having it beaten into me :).

However, I really hate introducing some third project that is  
required.  If we decide to pull ALL of boot wrappers out of the  
kernel tree than I'd be ok with it.  But until that time I think this  
lives under arch/powerpc/boot/...

What I envision as the way one boots for something like u-boot is one  
of three options:
1. using an old u-boot + boot wrapper (bd_t -> wrapper -> kernel)
2. using a u-boot that is ft aware + dtb (boot command in u-boot  
takes kernel & dtb images, updates blob and passes to kernel)
3. using a u-boot that is ft aware + built in dtb.

The issue is that for a given system/board you may need to support  
multiple or all three.  This raises the question where does the .dts  
live.  For the time being I say it lives in the boot wrapper part of  
the kernel tree.  Thus we handle the three cases as follows:

1. built as part of the boot wrapper
2. build a multi image u-boot image, one section for the blob
3. point u-boot build system at .dts

- kumar

^ permalink raw reply

* [RFC , PATCH] support for the ibm,pa_features cpu property
From: Will Schmidt @ 2006-04-28 18:41 UTC (permalink / raw)
  To: linuxppc-dev list, paulus


To determine if our processors support some features, such as large
pages, we should be using the ibm,pa_features property, rather than just
the PVR values.  
This is an initial pass at the functionality.  This has been tested in
the case where the property is missing, but still needs to be tested
against a system where the property actually exists.  :-o  



diff --git a/arch/powerpc/kernel/setup_64.c
b/arch/powerpc/kernel/setup_64.c
index 13e91c4..78ad054 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -106,6 +106,65 @@ static struct notifier_block ppc64_panic
 	.priority = INT_MIN /* may not return; must be done last */
 };
 
+/*
+ * ibm,pa-features is a per-cpu property that contains a 2 byte header
+ * plus up to 256 bytes worth of processor attributes.  First header
+ * byte specifies the number of bytes implemented by the platform.
+ * Second header byte is an "attribute-specifier" type, which should
+ * be zero.  Remainder of the data consists of ones and zeros.
+ * Implementation:  Pass in the byte and bit offset for the feature
+ * that we are interested in.  The function will return -1 if the
+ * pa-features property is missing, or a 1/0 to indicate if the feature
+ * is supported/not supported.
+ */
+
+static int get_pa_features(int pabyte,int pabit)
+{
+	struct device_node *cpu;
+	char *pa_feature_table;
+
+	cpu = of_find_node_by_type(NULL, "cpu");
+	pa_feature_table = 
+		(char *)get_property(cpu, "ibm,pa-features", NULL);
+
+	if ( pa_feature_table == NULL ) {
+		printk("ibm,pa-features property is missing.\n");
+		return -1;
+	}
+
+	/* sanity check */
+	if ( pabyte > pa_feature_table[0] ) {
+		printk("%s: %d out of range for table of size %d\n",
+			__FUNCTION__,pabyte,pa_feature_table[0]);
+		return -1;
+	}
+	
+	return pa_feature_table[2+pabyte*8+pabit];
+}
+
+/*
+ * set values within the cur_cpu_spec table according to
+ * the ibm,pa_features property. 
+ * potential entries include: 
+ * Byte 0, bit 1 - FPU available
+ * Byte 1, bit 2 - Large Pages 
+ * Byte 2, bit 3 - DAR set on alignment Interrupt. 
+ */
+static void add_cpu_features()
+{
+	/* if no property, bail early */
+	if (get_pa_features(0,0) == -1 ) return;
+
+	if (get_pa_features(1,2) ) {
+		printk("Adding CI_LARGE_PAGE to cur_cpu_spec \n");
+		cur_cpu_spec->cpu_features |= CPU_FTR_CI_LARGE_PAGE;
+	}
+
+	/* add more here... */
+
+}
+
+
 #ifdef CONFIG_SMP
 
 static int smt_enabled_cmdline;
@@ -425,6 +484,8 @@ void __init setup_system(void)
 
 	parse_early_param();
 
+	add_cpu_features();
+
 	check_smt_enabled();
 	smp_setup_cpu_maps();
 

^ permalink raw reply related

* Re: FT u-boot shim
From: Wolfgang Denk @ 2006-04-28 19:11 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <EA2821E8-FB7E-4DDA-8C18-C659B5483DC2@kernel.crashing.org>

In message <EA2821E8-FB7E-4DDA-8C18-C659B5483DC2@kernel.crashing.org>
Kumar Gala wrote:
> 
> What I envision as the way one boots for something like u-boot is one  
> of three options:
> 1. using an old u-boot + boot wrapper (bd_t -> wrapper -> kernel)
> 2. using a u-boot that is ft aware + dtb (boot command in u-boot  
> takes kernel & dtb images, updates blob and passes to kernel)
> 3. using a u-boot that is ft aware + built in dtb.
> 
> The issue is that for a given system/board you may need to support  
> multiple or all three.  This raises the question where does the .dts  

Assuming we had 2., under which circumstances would we need 3. then?


Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
A conservative is a man with two perfectly good legs  who  has  never
learned to walk.                              - Franklin D. Roosevelt

^ permalink raw reply

* [PATCH] via-pmu: report powerbutton as proper input event
From: Johannes Berg @ 2006-04-28 19:15 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, debian-powerpc

This patch adds an input device for the power button so that userspace gets
notified about the user pressing it via the standard input layer.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

--- linux-2.6.orig/drivers/macintosh/Makefile	2006-04-28 19:07:27.057288704 +0200
+++ linux-2.6/drivers/macintosh/Makefile	2006-04-28 19:07:49.987288704 +0200
@@ -11,7 +11,7 @@ obj-$(CONFIG_MAC_EMUMOUSEBTN)	+= mac_hid
 obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
-obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU)		+= via-pmu.o via-pmu-event.o
 obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/macintosh/via-pmu-event.c	2006-04-28 20:35:12.277288704 +0200
@@ -0,0 +1,35 @@
+#include <linux/input.h>
+#include "via-pmu-event.h"
+
+static struct input_dev *pmu_input_dev;
+
+int pmu_event_init(void)
+{
+	pmu_input_dev = input_allocate_device();
+	if (unlikely(!pmu_input_dev))
+		return -ENODEV;
+
+	pmu_input_dev->name = "PMU powerbutton";
+	pmu_input_dev->id.bustype = BUS_PMU;
+	pmu_input_dev->id.vendor = 0x0001;
+	pmu_input_dev->id.product = 0x0001;
+	pmu_input_dev->id.version = 0x0100;
+
+	pmu_input_dev->evbit[0] = BIT(EV_KEY);
+	pmu_input_dev->keybit[LONG(KEY_POWER)] = BIT(KEY_POWER);
+
+	return input_register_device(pmu_input_dev);
+}
+
+void pmu_event_powerbutton(int down)
+{
+	static int powerbutton_pressed;
+
+	if (unlikely(!pmu_input_dev))
+		return;
+	if (powerbutton_pressed == down)
+		return;
+	powerbutton_pressed = down;
+	input_report_key(pmu_input_dev, KEY_POWER, down);
+	input_sync(pmu_input_dev);
+}
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/drivers/macintosh/via-pmu-event.h	2006-04-28 20:09:34.967288704 +0200
@@ -0,0 +1,8 @@
+#ifndef __VIA_PMU_EVENT_H
+#define __VIA_PMU_EVENT_H
+
+extern int pmu_event_init(void);
+
+extern void pmu_event_powerbutton(int down);
+
+#endif /* __VIA_PMU_EVENT_H */
--- linux-2.6.orig/include/linux/input.h	2006-04-28 20:00:37.417288704 +0200
+++ linux-2.6/include/linux/input.h	2006-04-28 20:00:48.157288704 +0200
@@ -658,6 +658,7 @@ struct input_absinfo {
 #define BUS_I2C			0x18
 #define BUS_HOST		0x19
 #define BUS_GSC			0x1A
+#define BUS_PMU			0x20
 
 /*
  * Values describing the status of an effect
--- linux-2.6.orig/drivers/macintosh/via-pmu.c	2006-04-28 19:07:19.207288704 +0200
+++ linux-2.6/drivers/macintosh/via-pmu.c	2006-04-28 20:35:23.417288704 +0200
@@ -70,6 +70,7 @@
 #endif
 
 #include "via-pmu-led.h"
+#include "via-pmu-event.h"
 
 /* Some compile options */
 #undef SUSPEND_USES_PMU
@@ -1443,6 +1444,11 @@ next:
 		if (pmu_battery_count)
 			query_battery_state();
 		pmu_pass_intr(data, len);
+		/* if the thing has the powerbutton bit set then
+		 * update the powerbutton key status */
+		if (len == 6) {
+			pmu_event_powerbutton(!!(data[1]&8));
+		}
 	} else {
 	       pmu_pass_intr(data, len);
 	}
@@ -2915,6 +2921,10 @@ static int __init init_pmu_led(void)
 		if (pmu_led_init()) {
 			printk(KERN_WARNING "via-pmu: LED failed to init\n");
 		}
+
+		/* only on keylargo can the power button be on the pmu ... */
+		if (pmu_event_init())
+			printk(KERN_WARNING "via-pmu: couldn't add event device");
 	}
 
 	return 0;

^ permalink raw reply

* Re: [RFC , PATCH] support for the ibm,pa_features cpu property
From: Olof Johansson @ 2006-04-28 19:21 UTC (permalink / raw)
  To: Will Schmidt; +Cc: linuxppc-dev list, paulus
In-Reply-To: <1146249684.27214.18.camel@localhost.localdomain>

Hi Will,

Some general comments below. Not having seen the documentation for the
new property I obviously can't comment on the correctness from that
perspective.

Do you know why they went for this brand new extra architected bitfield
instead of continuing down the way that processor features always have
been documented before, by adding a property to the cpu device node?

That seems like a much more logical solution to me. It sort of sounds
like someone was bored one day and decided to get busy with architecting
yet another way to specify processor capabilities. :(

(Now, the naming convention of calling it a "pa feature" is unfortunate,
but nothing I can really complain about since our stuff is not yet in
tree.)


-Olof

On Fri, Apr 28, 2006 at 01:41:24PM -0500, Will Schmidt wrote:
> 
> To determine if our processors support some features, such as large
> pages, we should be using the ibm,pa_features property, rather than just
> the PVR values.  
> This is an initial pass at the functionality.  This has been tested in
> the case where the property is missing, but still needs to be tested
> against a system where the property actually exists.  :-o  
> 
> 
> 
> diff --git a/arch/powerpc/kernel/setup_64.c
> b/arch/powerpc/kernel/setup_64.c
> index 13e91c4..78ad054 100644
> --- a/arch/powerpc/kernel/setup_64.c
> +++ b/arch/powerpc/kernel/setup_64.c
> @@ -106,6 +106,65 @@ static struct notifier_block ppc64_panic
>  	.priority = INT_MIN /* may not return; must be done last */
>  };
>  
> +/*
> + * ibm,pa-features is a per-cpu property that contains a 2 byte header
> + * plus up to 256 bytes worth of processor attributes.  First header
> + * byte specifies the number of bytes implemented by the platform.
> + * Second header byte is an "attribute-specifier" type, which should
> + * be zero.  Remainder of the data consists of ones and zeros.

So, essentially a bit array with one bit per feature with a 2-byte
header?

> + * Implementation:  Pass in the byte and bit offset for the feature
> + * that we are interested in.  The function will return -1 if the
> + * pa-features property is missing, or a 1/0 to indicate if the feature
> + * is supported/not supported.
> + */
> +
> +static int get_pa_features(int pabyte,int pabit)

So this is more of a check_pa_feature (int pabyte, int pabit)

(note space after comma, CodingStyle)

> +{
> +	struct device_node *cpu;
> +	char *pa_feature_table;
> +
> +	cpu = of_find_node_by_type(NULL, "cpu");
> +	pa_feature_table = 
> +		(char *)get_property(cpu, "ibm,pa-features", NULL);
> +	if ( pa_feature_table == NULL ) {

No spaces after ( and before )

> +		printk("ibm,pa-features property is missing.\n");
> +		return -1;
> +	}

This will read the property on every call. How about making the table
pointer static instead and keeping it cached?

> +
> +	/* sanity check */
> +	if ( pabyte > pa_feature_table[0] ) {
> +		printk("%s: %d out of range for table of size %d\n",
> +			__FUNCTION__,pabyte,pa_feature_table[0]);

This might pop on regular machines, so you might want to do away with
the printk by default, or add it under a DBG() macro that's not enabled
by default (see other powerpc files for examples)

> +		return -1;
> +	}
> +	
> +	return pa_feature_table[2+pabyte*8+pabit];
> +}

Not knowing the order of the bitfield, I'm guessing you might want this
instead:

	return pa_feature_table[2+pabyte] & (0x80 >> pabit);

I would prefer to see a 0/1 return. 1 if the feature is set, 0
otherwise. I.e. no -1 on failure.

> +/*
> + * set values within the cur_cpu_spec table according to
> + * the ibm,pa_features property. 
> + * potential entries include: 
> + * Byte 0, bit 1 - FPU available
> + * Byte 1, bit 2 - Large Pages 
> + * Byte 2, bit 3 - DAR set on alignment Interrupt. 

Wow, that's a really sparse array, 8 empty entries between each
allocated bit so far.

I would like to see these as #defines as well. It might make more sense
to have them as just bit number, and calculate the byte in the function
above instead. That way it's only one define per feature.

> + */
> +static void add_cpu_features()
> +{
> +	/* if no property, bail early */
> +	if (get_pa_features(0,0) == -1 ) return;

Probably no need to bail early, especially if the feature check function
just returns 0 if it's out-of-bounds (or no property exists)

> +
> +	if (get_pa_features(1,2) ) {
> +		printk("Adding CI_LARGE_PAGE to cur_cpu_spec \n");
> +		cur_cpu_spec->cpu_features |= CPU_FTR_CI_LARGE_PAGE;
> +	}
> +
> +	/* add more here... */
> +
> +}
> +
> +
>  #ifdef CONFIG_SMP
>  
>  static int smt_enabled_cmdline;
> @@ -425,6 +484,8 @@ void __init setup_system(void)
>  
>  	parse_early_param();
>  
> +	add_cpu_features();
> +
>  	check_smt_enabled();
>  	smp_setup_cpu_maps();
>  
> 
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [RFC , PATCH] support for the ibm,pa_features cpu property
From: Nathan Lynch @ 2006-04-28 19:31 UTC (permalink / raw)
  To: Will Schmidt; +Cc: linuxppc-dev list, paulus
In-Reply-To: <1146249684.27214.18.camel@localhost.localdomain>

Will Schmidt wrote:
> +static int get_pa_features(int pabyte,int pabit)
> +{
> +	struct device_node *cpu;
> +	char *pa_feature_table;
> +
> +	cpu = of_find_node_by_type(NULL, "cpu");
> +	pa_feature_table = 
> +		(char *)get_property(cpu, "ibm,pa-features", NULL);
> +
> +	if ( pa_feature_table == NULL ) {
> +		printk("ibm,pa-features property is missing.\n");
> +		return -1;
> +	}
> +
> +	/* sanity check */
> +	if ( pabyte > pa_feature_table[0] ) {
> +		printk("%s: %d out of range for table of size %d\n",
> +			__FUNCTION__,pabyte,pa_feature_table[0]);
> +		return -1;
> +	}
> +	
> +	return pa_feature_table[2+pabyte*8+pabit];
> +}

This function needs to of_node_put(cpu) before returning or we won't
be able to deconfigure the processor.

^ permalink raw reply

* Re: [PATCH] powerpc: ibmveth: Harden driver initilisation for kexec
From: Santiago Leon @ 2006-04-28 19:51 UTC (permalink / raw)
  To: michael; +Cc: linuxppc64-dev, jgarzik, netdev
In-Reply-To: <1146047837.10735.29.camel@localhost.localdomain>

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

Michael Ellerman wrote:
>>Looks like this hit the floor. Any chance of getting it into to 2.6.17
>>Jeff? AFAICT it should still apply cleanly.
>  
> /me knocks politely

Actually, it doesn't apply cleanly anymore.  Here's a patch that does.
-- 
Santiago A. Leon
Power Linux Development
IBM Linux Technology Center

[-- Attachment #2: ibmveth_harden_init.patch --]
[-- Type: text/plain, Size: 2193 bytes --]

From: Michael Ellerman <michael@ellerman.id.au>

After a kexec the ibmveth driver will fail when trying to register with the Hypervisor because the previous kernel has not unregistered.

So if the registration fails, we unregister and then try again.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Acked-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Santiago Leon <santil@us.ibm.com>

 ibmveth.c |   31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

Index: kexec/drivers/net/ibmveth.c
===================================================================
--- a/drivers/net/ibmveth.c	2006-04-28 13:16:22.244724056 -0500
+++ b/drivers/net/ibmveth.c	2006-04-28 13:29:49.429736784 -0500
@@ -436,6 +436,31 @@ static void ibmveth_cleanup(struct ibmve
 		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
 }
 
+static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
+        union ibmveth_buf_desc rxq_desc, u64 mac_address)
+{
+	int rc, try_again = 1;
+
+	/* After a kexec the adapter will still be open, so our attempt to
+	* open it will fail. So if we get a failure we free the adapter and
+	* try again, but only once. */
+retry:
+	rc = h_register_logical_lan(adapter->vdev->unit_address,
+				    adapter->buffer_list_dma, rxq_desc.desc,
+				    adapter->filter_list_dma, mac_address);
+
+	if (rc != H_SUCCESS && try_again) {
+		do {
+			rc = h_free_logical_lan(adapter->vdev->unit_address);
+		} while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY));
+
+		try_again = 0;
+		goto retry;
+	}
+
+	return rc;
+}
+
 static int ibmveth_open(struct net_device *netdev)
 {
 	struct ibmveth_adapter *adapter = netdev->priv;
@@ -505,11 +530,7 @@ static int ibmveth_open(struct net_devic
 	ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
 
     
-	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
-					 adapter->buffer_list_dma,
-					 rxq_desc.desc,
-					 adapter->filter_list_dma,
-					 mac_address);
+	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
 
 	if(lpar_rc != H_SUCCESS) {
 		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);

^ permalink raw reply

* Re: FT u-boot shim
From: Tom Rini @ 2006-04-28 19:52 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@ozlabs.org list, Paul Mackerras
In-Reply-To: <EA2821E8-FB7E-4DDA-8C18-C659B5483DC2@kernel.crashing.org>

On Fri, Apr 28, 2006 at 11:01:20AM -0500, Kumar Gala wrote:

> However, I really hate introducing some third project that is  
> required.  If we decide to pull ALL of boot wrappers out of the  
> kernel tree than I'd be ok with it.  But until that time I think this  
> lives under arch/powerpc/boot/...

The more I think about this, and hear about what some vendors do,
pulling arch/p*pc/boot/ out of the kernel is making more and more sense.
Especially with the serial headache, a depends-on-nothing,
can-translate-$(firmware information) tool might be best.

> What I envision as the way one boots for something like u-boot is one  
> of three options:
> 1. using an old u-boot + boot wrapper (bd_t -> wrapper -> kernel)
> 2. using a u-boot that is ft aware + dtb (boot command in u-boot  
> takes kernel & dtb images, updates blob and passes to kernel)
> 3. using a u-boot that is ft aware + built in dtb.

And more generally:
1. using an old firmware + kernel boot wrapper (firmware->dtb converter)
boots kernel.
2. using a dtb-aware firmware boots kernel (compressed or not) and
passes dtb in.

> The issue is that for a given system/board you may need to support  
> multiple or all three.  This raises the question where does the .dts  
> live.  For the time being I say it lives in the boot wrapper part of  
> the kernel tree.  Thus we handle the three cases as follows:

We could stick it in the seprate kernel boot wrapper project.  But I
really think this really has to live in two places.  The kernel should
be The Owner, as until *BSD or something adopts this, it's a
Linux-specific thing.  But any firmware that wishes to skip the kernel
boot wrapper and be a direct kernel booter, will need to own a copy.

-- 
Tom Rini
http://gate.crashing.org/~trini/

^ permalink raw reply

* Re: [PATCH] [2.6.18] powerpc: kill union tce_entry
From: Jon Mason @ 2006-04-28 20:42 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev, mulix, paulus, sfr
In-Reply-To: <20060428140835.GG5518@pb15.lixom.net>

This looks very similar to the way Muli did it for x86_64 Calgary, only
in the reverse.  You gotta love endianness. :-)

Looks good to my eyeball.

Thanks,
Jon


On Fri, Apr 28, 2006 at 09:08:35AM -0500, Olof Johansson wrote:
> It's been long overdue to kill the union tce_entry in the pSeries/iSeries
> TCE code, especially since I asked the Summit guys to do it on the code
> they copied from us.
> 
> Also, while I was at it, I cleaned up some whitespace.
> 
> Built and booted on pSeries, built on iSeries.
> 
> 
> Signed-off-by: Olof Johansson <olof@lixom.net>
> 
> 
> Index: powerpc/arch/powerpc/platforms/iseries/iommu.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/iseries/iommu.c
> +++ powerpc/arch/powerpc/platforms/iseries/iommu.c
> @@ -4,6 +4,7 @@
>   * Rewrite, cleanup:
>   *
>   * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
> + * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
>   *
>   * Dynamic DMA mapping support, iSeries-specific parts.
>   *
> @@ -43,30 +44,28 @@ static void tce_build_iSeries(struct iom
>  		unsigned long uaddr, enum dma_data_direction direction)
>  {
>  	u64 rc;
> -	union tce_entry tce;
> +	u64 tce, rpn;
>  
>  	index <<= TCE_PAGE_FACTOR;
>  	npages <<= TCE_PAGE_FACTOR;
>  
>  	while (npages--) {
> -		tce.te_word = 0;
> -		tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
> +		rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
> +		tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
>  
>  		if (tbl->it_type == TCE_VB) {
>  			/* Virtual Bus */
> -			tce.te_bits.tb_valid = 1;
> -			tce.te_bits.tb_allio = 1;
> +			tce |= TCE_VALID|TCE_ALLIO;
>  			if (direction != DMA_TO_DEVICE)
> -				tce.te_bits.tb_rdwr = 1;
> +				tce |= TCE_VB_WRITE;
>  		} else {
>  			/* PCI Bus */
> -			tce.te_bits.tb_rdwr = 1; /* Read allowed */
> +			tce |= TCE_PCI_READ; /* Read allowed */
>  			if (direction != DMA_TO_DEVICE)
> -				tce.te_bits.tb_pciwr = 1;
> +				tce |= TCE_PCI_WRITE;
>  		}
>  
> -		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
> -				tce.te_word);
> +		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
>  		if (rc)
>  			panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
>  					rc);
> @@ -124,7 +123,7 @@ void iommu_table_getparms_iSeries(unsign
>  
>  	/* itc_size is in pages worth of table, it_size is in # of entries */
>  	tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) /
> -			sizeof(union tce_entry)) >> TCE_PAGE_FACTOR;
> +			TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR;
>  	tbl->it_busno = parms->itc_busno;
>  	tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR;
>  	tbl->it_index = parms->itc_index;
> Index: powerpc/arch/powerpc/platforms/pseries/iommu.c
> ===================================================================
> --- powerpc.orig/arch/powerpc/platforms/pseries/iommu.c
> +++ powerpc/arch/powerpc/platforms/pseries/iommu.c
> @@ -1,23 +1,24 @@
>  /*
>   * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
>   *
> - * Rewrite, cleanup: 
> + * Rewrite, cleanup:
>   *
>   * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
> + * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
>   *
>   * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
>   *
> - * 
> + *
>   * 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.
> - * 
> + *
>   * This program is distributed in the hope that it will be useful,
>   * but WITHOUT ANY WARRANTY; without even the implied warranty of
>   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>   * GNU General Public License for more details.
> - * 
> + *
>   * You should have received a copy of the GNU General Public License
>   * along with this program; if not, write to the Free Software
>   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> @@ -49,52 +50,46 @@
>  
>  #define DBG(fmt...)
>  
> -static void tce_build_pSeries(struct iommu_table *tbl, long index, 
> -			      long npages, unsigned long uaddr, 
> +static void tce_build_pSeries(struct iommu_table *tbl, long index,
> +			      long npages, unsigned long uaddr,
>  			      enum dma_data_direction direction)
>  {
> -	union tce_entry t;
> -	union tce_entry *tp;
> +	u64 proto_tce;
> +	u64 *tcep;
> +	u64 rpn;
>  
>  	index <<= TCE_PAGE_FACTOR;
>  	npages <<= TCE_PAGE_FACTOR;
>  
> -	t.te_word = 0;
> -	t.te_rdwr = 1; // Read allowed 
> +	proto_tce = TCE_PCI_READ; // Read allowed
>  
>  	if (direction != DMA_TO_DEVICE)
> -		t.te_pciwr = 1;
> +		proto_tce |= TCE_PCI_WRITE;
>  
> -	tp = ((union tce_entry *)tbl->it_base) + index;
> +	tcep = ((u64 *)tbl->it_base) + index;
>  
>  	while (npages--) {
>  		/* can't move this out since we might cross LMB boundary */
> -		t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> -	
> -		tp->te_word = t.te_word;
> +		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> +		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
>  
>  		uaddr += TCE_PAGE_SIZE;
> -		tp++;
> +		tcep++;
>  	}
>  }
>  
>  
>  static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
>  {
> -	union tce_entry t;
> -	union tce_entry *tp;
> +	u64 *tcep;
>  
>  	npages <<= TCE_PAGE_FACTOR;
>  	index <<= TCE_PAGE_FACTOR;
>  
> -	t.te_word = 0;
> -	tp  = ((union tce_entry *)tbl->it_base) + index;
> -		
> -	while (npages--) {
> -		tp->te_word = t.te_word;
> -		
> -		tp++;
> -	}
> +	tcep = ((u64 *)tbl->it_base) + index;
> +
> +	while (npages--)
> +		*(tcep++) = 0;
>  }
>  
>  
> @@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct i
>  				enum dma_data_direction direction)
>  {
>  	u64 rc;
> -	union tce_entry tce;
> +	u64 proto_tce, tce;
> +	u64 rpn;
>  
>  	tcenum <<= TCE_PAGE_FACTOR;
>  	npages <<= TCE_PAGE_FACTOR;
>  
> -	tce.te_word = 0;
> -	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> -	tce.te_rdwr = 1;
> +	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> +	proto_tce = TCE_PCI_READ;
>  	if (direction != DMA_TO_DEVICE)
> -		tce.te_pciwr = 1;
> +		proto_tce |= TCE_PCI_WRITE;
>  
>  	while (npages--) {
> -		rc = plpar_tce_put((u64)tbl->it_index, 
> -				   (u64)tcenum << 12, 
> -				   tce.te_word );
> -		
> +		tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
> +		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
> +
>  		if (rc && printk_ratelimit()) {
>  			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
>  			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
>  			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
> -			printk("\ttce val = 0x%lx\n", tce.te_word );
> +			printk("\ttce val = 0x%lx\n", tce );
>  			show_stack(current, (unsigned long *)__get_SP());
>  		}
> -			
> +
>  		tcenum++;
> -		tce.te_rpn++;
> +		rpn++;
>  	}
>  }
>  
> -static DEFINE_PER_CPU(void *, tce_page) = NULL;
> +static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
>  
>  static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
>  				     long npages, unsigned long uaddr,
>  				     enum dma_data_direction direction)
>  {
>  	u64 rc;
> -	union tce_entry tce, *tcep;
> +	u64 proto_tce;
> +	u64 *tcep;
> +	u64 rpn;
>  	long l, limit;
>  
>  	if (TCE_PAGE_FACTOR == 0 && npages == 1)
> @@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(str
>  	 * from iommu_alloc{,_sg}()
>  	 */
>  	if (!tcep) {
> -		tcep = (void *)__get_free_page(GFP_ATOMIC);
> +		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
>  		/* If allocation fails, fall back to the loop implementation */
>  		if (!tcep)
>  			return tce_build_pSeriesLP(tbl, tcenum, npages,
> @@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(str
>  	tcenum <<= TCE_PAGE_FACTOR;
>  	npages <<= TCE_PAGE_FACTOR;
>  
> -	tce.te_word = 0;
> -	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> -	tce.te_rdwr = 1;
> +	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
> +	proto_tce = TCE_PCI_READ;
>  	if (direction != DMA_TO_DEVICE)
> -		tce.te_pciwr = 1;
> +		proto_tce |= TCE_PCI_WRITE;
>  
>  	/* We can map max one pageful of TCEs at a time */
>  	do {
> @@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(str
>  		 * Set up the page with TCE data, looping through and setting
>  		 * the values.
>  		 */
> -		limit = min_t(long, npages, 4096/sizeof(union tce_entry));
> +		limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
>  
>  		for (l = 0; l < limit; l++) {
> -			tcep[l] = tce;
> -			tce.te_rpn++;
> +			tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
> +			rpn++;
>  		}
>  
>  		rc = plpar_tce_put_indirect((u64)tbl->it_index,
> @@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(str
>  		printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
>  		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
>  		printk("\tnpages  = 0x%lx\n", (u64)npages);
> -		printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
> +		printk("\ttce[0] val = 0x%lx\n", tcep[0]);
>  		show_stack(current, (unsigned long *)__get_SP());
>  	}
>  }
> @@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(str
>  static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
>  {
>  	u64 rc;
> -	union tce_entry tce;
>  
>  	tcenum <<= TCE_PAGE_FACTOR;
>  	npages <<= TCE_PAGE_FACTOR;
>  
> -	tce.te_word = 0;
> -
>  	while (npages--) {
> -		rc = plpar_tce_put((u64)tbl->it_index,
> -				   (u64)tcenum << 12,
> -				   tce.te_word);
> +		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
>  
>  		if (rc && printk_ratelimit()) {
>  			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
>  			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
>  			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
> -			printk("\ttce val = 0x%lx\n", tce.te_word );
>  			show_stack(current, (unsigned long *)__get_SP());
>  		}
>  
> @@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct io
>  static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
>  {
>  	u64 rc;
> -	union tce_entry tce;
>  
>  	tcenum <<= TCE_PAGE_FACTOR;
>  	npages <<= TCE_PAGE_FACTOR;
>  
> -	tce.te_word = 0;
> -
> -	rc = plpar_tce_stuff((u64)tbl->it_index,
> -			   (u64)tcenum << 12,
> -			   tce.te_word,
> -			   npages);
> +	rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
>  
>  	if (rc && printk_ratelimit()) {
>  		printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
>  		printk("\trc      = %ld\n", rc);
>  		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
>  		printk("\tnpages  = 0x%lx\n", (u64)npages);
> -		printk("\ttce val = 0x%lx\n", tce.te_word );
>  		show_stack(current, (unsigned long *)__get_SP());
>  	}
>  }
>  
>  static void iommu_table_setparms(struct pci_controller *phb,
>  				 struct device_node *dn,
> -				 struct iommu_table *tbl) 
> +				 struct iommu_table *tbl)
>  {
>  	struct device_node *node;
>  	unsigned long *basep;
> @@ -275,16 +257,16 @@ static void iommu_table_setparms(struct 
>  	memset((void *)tbl->it_base, 0, *sizep);
>  
>  	tbl->it_busno = phb->bus->number;
> -	
> +
>  	/* Units of tce entries */
>  	tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
> -	
> +
>  	/* Test if we are going over 2GB of DMA space */
>  	if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
>  		udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
> -		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
> +		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
>  	}
> -	
> +
>  	phb->dma_window_base_cur += phb->dma_window_size;
>  
>  	/* Set the tce table size - measured in entries */
> @@ -442,7 +424,7 @@ static void iommu_bus_setup_pSeriesLP(st
>  
>  		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
>  						    GFP_KERNEL);
> -	
> +
>  		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
>  
>  		ppci->iommu_table = iommu_init_table(tbl);
> Index: powerpc/include/asm-powerpc/tce.h
> ===================================================================
> --- powerpc.orig/include/asm-powerpc/tce.h
> +++ powerpc/include/asm-powerpc/tce.h
> @@ -35,32 +35,15 @@
>  #define TCE_PAGE_SIZE	(1 << TCE_SHIFT)
>  #define TCE_PAGE_FACTOR	(PAGE_SHIFT - TCE_SHIFT)
>  
> +#define TCE_ENTRY_SIZE		8		/* each TCE is 64 bits */
>  
> -/* tce_entry
> - * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
> - * abstracted so layout is irrelevant.
> - */
> -union tce_entry {
> -   	unsigned long te_word;
> -	struct {
> -		unsigned int  tb_cacheBits :6;	/* Cache hash bits - not used */
> -		unsigned int  tb_rsvd      :6;
> -		unsigned long tb_rpn       :40;	/* Real page number */
> -		unsigned int  tb_valid     :1;	/* Tce is valid (vb only) */
> -		unsigned int  tb_allio     :1;	/* Tce is valid for all lps (vb only) */
> -		unsigned int  tb_lpindex   :8;	/* LpIndex for user of TCE (vb only) */
> -		unsigned int  tb_pciwr     :1;	/* Write allowed (pci only) */
> -		unsigned int  tb_rdwr      :1;	/* Read allowed  (pci), Write allowed (vb) */
> -	} te_bits;
> -#define te_cacheBits te_bits.tb_cacheBits
> -#define te_rpn       te_bits.tb_rpn
> -#define te_valid     te_bits.tb_valid
> -#define te_allio     te_bits.tb_allio
> -#define te_lpindex   te_bits.tb_lpindex
> -#define te_pciwr     te_bits.tb_pciwr
> -#define te_rdwr      te_bits.tb_rdwr
> -};
> -
> +#define TCE_RPN_MASK		0xfffffffffful  /* 40-bit RPN (4K pages) */
> +#define TCE_RPN_SHIFT		12
> +#define TCE_VALID		0x200		/* TCE valid */
> +#define TCE_ALLIO		0x100		/* TCE valid for all lpars */
> +#define TCE_PCI_WRITE		0x2		/* write from PCI allowed */
> +#define TCE_PCI_READ		0x1		/* read from PCI allowed */
> +#define TCE_VB_WRITE		0x1		/* write from VB allowed */
>  
>  #endif /* __KERNEL__ */
>  #endif /* _ASM_POWERPC_TCE_H */
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ 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