From moilanen at austin.ibm.com Tue Nov 1 08:45:40 2005 From: moilanen at austin.ibm.com (Jake Moilanen) Date: Mon, 31 Oct 2005 15:45:40 -0600 Subject: [PATCH 2/2] Export Physical IO base address In-Reply-To: <1130540087.29054.128.camel@gaston> References: <20051028150035.3d1da846.moilanen@austin.ibm.com> <20051028150804.73b5cedb.moilanen@austin.ibm.com> <1130540087.29054.128.camel@gaston> Message-ID: <20051031154540.195b0de0.moilanen@austin.ibm.com> On Sat, 29 Oct 2005 08:54:47 +1000 Benjamin Herrenschmidt wrote: > On Fri, 2005-10-28 at 15:08 -0500, Jake Moilanen wrote: > > This patch exports the physical IO base address so drivers can pick it > > up when using addresses from the device-tree. > > Why ? What is your driver exactly trying to do ? TPM needs to get the base address for IO as an offset into IO space. This base physical address is stored in the reg property in the device-node. To calculate the offset, need to do: TPM_base_phy_addr - io_base_phys. Thus the need to export this address. Jake From arndb at de.ibm.com Tue Nov 1 12:08:38 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Mon, 31 Oct 2005 20:08:38 -0500 Subject: [patch 2/5] powerpc: create a new arch/powerpc/platforms/cell/smp.c References: <20051101010836.771791000@localhost> Message-ID: <20051101011133.300238000@localhost> An embedded and charset-unspecified text was scrubbed... Name: cell-smp.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051031/03409828/attachment.txt From arndb at de.ibm.com Tue Nov 1 12:08:37 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Mon, 31 Oct 2005 20:08:37 -0500 Subject: [patch 1/5] powerpc: Rename BPA to Cell References: <20051101010836.771791000@localhost> Message-ID: <20051101011133.134984000@localhost> An embedded and charset-unspecified text was scrubbed... Name: cell-kconfig.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051031/751fab3b/attachment.txt From arndb at de.ibm.com Tue Nov 1 12:08:36 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Mon, 31 Oct 2005 20:08:36 -0500 Subject: [patch 0/5] Move Cell stuff to arch/powerpc Message-ID: <20051101010836.771791000@localhost> As promised, here is my new patch set moving all Cell stuff over to arch/powerpc. Please apply. Arnd <>< From arndb at de.ibm.com Tue Nov 1 12:08:40 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Mon, 31 Oct 2005 20:08:40 -0500 Subject: [patch 4/5] powerpc: move mmio_nvram.c over to arch/powerpc References: <20051101010836.771791000@localhost> Message-ID: <20051101011133.623411000@localhost> An embedded and charset-unspecified text was scrubbed... Name: mmio-nvram.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051031/f47181fa/attachment.txt From arndb at de.ibm.com Tue Nov 1 12:08:39 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Mon, 31 Oct 2005 20:08:39 -0500 Subject: [patch 3/5] powerpc: move rtas_fw.c out of platforms/pseries References: <20051101010836.771791000@localhost> Message-ID: <20051101011133.463223000@localhost> An embedded and charset-unspecified text was scrubbed... Name: rtas-flash.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051031/5894915b/attachment.txt From arndb at de.ibm.com Tue Nov 1 12:08:41 2005 From: arndb at de.ibm.com (Arnd Bergmann) Date: Mon, 31 Oct 2005 20:08:41 -0500 Subject: [patch 5/5] powerpc: move arch/ppc64/kernel/bpa* to arch/powerpc/platforms/cell References: <20051101010836.771791000@localhost> Message-ID: <20051101011133.788778000@localhost> An embedded and charset-unspecified text was scrubbed... Name: cell-platform.diff Url: http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051031/13827568/attachment.txt From michael at ellerman.id.au Tue Nov 1 10:26:55 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Tue, 1 Nov 2005 10:26:55 +1100 Subject: [patch 2/5] powerpc: create a new arch/powerpc/platforms/cell/smp.c In-Reply-To: <20051101011133.300238000@localhost> References: <20051101010836.771791000@localhost> <20051101011133.300238000@localhost> Message-ID: <200511011026.59266.michael@ellerman.id.au> On Tue, 1 Nov 2005 12:08, Arnd Bergmann wrote: > During the conversion to the merge tree, the Cell specific > SMP initialization was removed from the pSeries code. > > This creates a new Cell specific SMP implementation file. > > Signed-off-by: Arnd Bergmann > > --- > > arch/powerpc/platforms/Makefile | 1 > arch/powerpc/platforms/cell/Makefile | 1 > arch/powerpc/platforms/cell/smp.c | 230 ++++++++++++++++++++ > include/asm-ppc64/smp.h | 1 > 4 files changed, 233 insertions(+) A lot of your smp routines are identical to the pSeries versions. Wouldn't it be preferable to only have one implementation? cheers -- Michael Ellerman IBM OzLabs email: michael:ellerman.id.au inmsg: mpe:jabber.org 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 -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051101/0d649a53/attachment.pgp From benh at kernel.crashing.org Tue Nov 1 10:27:23 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 01 Nov 2005 10:27:23 +1100 Subject: [PATCH 2/2] Export Physical IO base address In-Reply-To: <20051031154540.195b0de0.moilanen@austin.ibm.com> References: <20051028150035.3d1da846.moilanen@austin.ibm.com> <20051028150804.73b5cedb.moilanen@austin.ibm.com> <1130540087.29054.128.camel@gaston> <20051031154540.195b0de0.moilanen@austin.ibm.com> Message-ID: <1130801243.29054.376.camel@gaston> On Mon, 2005-10-31 at 15:45 -0600, Jake Moilanen wrote: > On Sat, 29 Oct 2005 08:54:47 +1000 > Benjamin Herrenschmidt wrote: > > > On Fri, 2005-10-28 at 15:08 -0500, Jake Moilanen wrote: > > > This patch exports the physical IO base address so drivers can pick it > > > up when using addresses from the device-tree. > > > > Why ? What is your driver exactly trying to do ? > > TPM needs to get the base address for IO as an offset into IO space. > > This base physical address is stored in the reg property in the > device-node. > > To calculate the offset, need to do: TPM_base_phy_addr - io_base_phys. > > Thus the need to export this address. Hrm... that is sooo bogus. If the device-tree exposes a full physical address in "reg", then just use that with ioremap (ignore the fact that it's actually IO space). Additionally, tell the firmware folks to fix their device-tree, this is all very bogus to me. The TPM device is on the LPC bus right ? Thus it should appear below the LPC/ISA bridge and thus get proper address space. It's totally broken to put it anywhere else Ben. From arnd at arndb.de Tue Nov 1 10:50:48 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Tue, 1 Nov 2005 00:50:48 +0100 Subject: [patch 2/5] powerpc: create a new arch/powerpc/platforms/cell/smp.c In-Reply-To: <200511011026.59266.michael@ellerman.id.au> References: <20051101010836.771791000@localhost> <20051101011133.300238000@localhost> <200511011026.59266.michael@ellerman.id.au> Message-ID: <200511010050.48828.arnd@arndb.de> On Dinsdag 01 November 2005 00:26, Michael Ellerman wrote: > A lot of your smp routines are identical to the pSeries versions. Wouldn't it > be preferable to only have one implementation? Yes it would. I'm not sure how that would best be done however. Until 2.6.14, we've just used the pSeries implementation, which does not work any more now that we want to keep the platform stuff in separate directories. One idea might be to split out the rtas calls (startup_cpu, give_timebase, take_timebase) to rtas.c so they can be included by all chrp-descendants. smp_init_cell() can be further simplified under the assumption that we're always SMT and never LPAR, although the latter might change in the future. Arnd <>< From benh at kernel.crashing.org Tue Nov 1 11:05:08 2005 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Tue, 01 Nov 2005 11:05:08 +1100 Subject: [PATCH] tpm: support PPC64 hardware In-Reply-To: <1130769479.4882.35.camel@localhost.localdomain> References: <1130769479.4882.35.camel@localhost.localdomain> Message-ID: <1130803508.29054.388.camel@gaston> On Mon, 2005-10-31 at 08:37 -0600, Kylene Jo Hall wrote: > The TPM is discovered differently on PPC64 because the device must be > discovered through the device tree in order to open the proper holes in > the io_page_mask for reading and writing in the low memory space. This > does not happen automatically like most devices because the tpm is not a > normal pci device and lives under the root node. > > This patch contains the necessary changes to the tpm logic. > > This depends on patches submitted by Jake Moilanen (10/28) to allow for > the opening of holes in the io_page_mask for this device. Please submit to the appropriate list (linuxppc64-dev at ozlabs.org). There are some issues with that patch. One, I intend to get rid of the io_page_mask, so that part at least is gone. I don't like the exporting of io_base_phys neither, it's an ugly hack. Other comments inline. > +/* Verify this is a 1.1 Atmel TPM */ > +static int atmel_verify_tpm11(void) > +{ > + struct device_node * dn; > + char *compat; > + int compat_len; > + > + dn = find_devices("tpm"); find_devices() is a deprecated interface. Use the of_find_node_* series and do an of_node_put() once done. > + if (!dn) > + return 1; > + > + compat = (char *) get_property(dn, "compatible", &compat_len); > + if (!compat) > + return 1; > + > + if ( strcmp( compat,"AT97SC3201_r") == 0 ) > + return 0; > + Testing the "compatible" property this way is bogus. Use device_is_compatible(). Or better, use of_find_compatible_node() which allows you to find by type & compatible in one step. > + dn = find_devices("tpm"); Same comment as above. In addition, why do you have to do it twice ? You should rethink your changes. Only one "probe" should be needed that retreives the base addresses. > + if (!dn) > + return 0; > + > + reg = (unsigned int *) get_property(dn, "reg", ®len); > + naddrc = prom_n_addr_cells(dn); > + nsizec = prom_n_size_cells(dn); > + > + for (i = 0; i < reglen; i = i + naddrc + nsizec) { > + > + if (naddrc == 2) > + address = ((unsigned long)reg[i] << 32) | reg[i+1]; > + else > + address = reg[i]; > + > + address = address - pci_io_base_phys; That is bogosity. Your address is an ISA IO address, It should be relative to the parent LPC bus and thus useable as is. It looks like the firmware folks crapped the device-tree. Please check that with them. If they decide to stick with a broken device-tree, then you'll have to consider the address as an MMIO address. That mean you'll have to change the IO accesses of the TPM driver to use the iomap API thus making it immune of IO cs. MMIO distinction. > + allow_isa_address(address, address+size-1); That is going away. Ben. From michael at ellerman.id.au Tue Nov 1 11:13:23 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Tue, 1 Nov 2005 11:13:23 +1100 Subject: [patch 2/5] powerpc: create a new arch/powerpc/platforms/cell/smp.c In-Reply-To: <200511010050.48828.arnd@arndb.de> References: <20051101010836.771791000@localhost> <200511011026.59266.michael@ellerman.id.au> <200511010050.48828.arnd@arndb.de> Message-ID: <200511011113.26609.michael@ellerman.id.au> On Tue, 1 Nov 2005 10:50, Arnd Bergmann wrote: > On Dinsdag 01 November 2005 00:26, Michael Ellerman wrote: > > A lot of your smp routines are identical to the pSeries versions. > > Wouldn't it be preferable to only have one implementation? > > Yes it would. I'm not sure how that would best be done however. Until > 2.6.14, we've just used the pSeries implementation, which does not work any > more now that we want to keep the platform stuff in separate directories. > > One idea might be to split out the rtas calls (startup_cpu, give_timebase, > take_timebase) to rtas.c so they can be included by all chrp-descendants. > smp_init_cell() can be further simplified under the assumption that we're > always SMT and never LPAR, although the latter might change in the future. OK, I'm not sure what the best spot is. arch/powerpc/sysdev is apparently the place for stuff that's not core-kernel but shared between platforms, although maybe smp ops are core, I dunno. cheers -- Michael Ellerman IBM OzLabs email: michael:ellerman.id.au inmsg: mpe:jabber.org 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 -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: not available Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051101/dc38ac71/attachment.pgp From david at gibson.dropbear.id.au Tue Nov 1 15:30:26 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Tue, 1 Nov 2005 15:30:26 +1100 Subject: powerpc: Move naca.h to platforms/iseries Message-ID: <20051101043026.GB27961@localhost.localdomain> Paulus, please apply. These days, the NACA only exists on iSeries. Therefore, this patch moves naca.h from include/asm-ppc64 to arch/powerpc/platforms/iseries. There was one file including naca.h outside of platforms/iseries - arch/ppc64/kernel/udbg_scc.c. However, that's obviously a hangover from older days. The include is not necessary, so this patch simply removes it. Built and booted on iSeries, built for G5 (which uses udbg_scc.o). Signed-off-by: David Gibson Index: working-2.6/arch/powerpc/platforms/iseries/lpardata.c =================================================================== --- working-2.6.orig/arch/powerpc/platforms/iseries/lpardata.c 2005-10-31 15:20:20.000000000 +1100 +++ working-2.6/arch/powerpc/platforms/iseries/lpardata.c 2005-11-01 15:15:57.000000000 +1100 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -23,6 +22,7 @@ #include #include +#include "naca.h" #include "vpd_areas.h" #include "spcomm_area.h" #include "ipl_parms.h" Index: working-2.6/arch/powerpc/platforms/iseries/naca.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ working-2.6/arch/powerpc/platforms/iseries/naca.h 2005-11-01 15:28:03.000000000 +1100 @@ -0,0 +1,24 @@ +#ifndef _PLATFORMS_ISERIES_NACA_H +#define _PLATFORMS_ISERIES_NACA_H + +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include + +struct naca_struct { + /* Kernel only data - undefined for user space */ + void *xItVpdAreas; /* VPD Data 0x00 */ + void *xRamDisk; /* iSeries ramdisk 0x08 */ + u64 xRamDiskSize; /* In pages 0x10 */ +}; + +extern struct naca_struct naca; + +#endif /* _PLATFORMS_ISERIES_NACA_H */ Index: working-2.6/arch/powerpc/platforms/iseries/release_data.h =================================================================== --- working-2.6.orig/arch/powerpc/platforms/iseries/release_data.h 2005-10-31 15:20:20.000000000 +1100 +++ working-2.6/arch/powerpc/platforms/iseries/release_data.h 2005-11-01 15:15:57.000000000 +1100 @@ -24,7 +24,7 @@ * address of the OS's NACA). */ #include -#include +#include "naca.h" /* * When we IPL a secondary partition, we will check if if the Index: working-2.6/arch/powerpc/platforms/iseries/setup.c =================================================================== --- working-2.6.orig/arch/powerpc/platforms/iseries/setup.c 2005-10-31 15:44:59.000000000 +1100 +++ working-2.6/arch/powerpc/platforms/iseries/setup.c 2005-11-01 15:15:57.000000000 +1100 @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -53,6 +52,7 @@ #include #include +#include "naca.h" #include "setup.h" #include "irq.h" #include "vpd_areas.h" Index: working-2.6/arch/ppc64/kernel/udbg_scc.c =================================================================== --- working-2.6.orig/arch/ppc64/kernel/udbg_scc.c 2005-10-25 11:59:53.000000000 +1000 +++ working-2.6/arch/ppc64/kernel/udbg_scc.c 2005-11-01 15:15:57.000000000 +1100 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include Index: working-2.6/include/asm-ppc64/naca.h =================================================================== --- working-2.6.orig/include/asm-ppc64/naca.h 2005-10-25 11:59:59.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#ifndef _NACA_H -#define _NACA_H - -/* - * c 2001 PPC 64 Team, IBM Corp - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include - -struct naca_struct { - /* Kernel only data - undefined for user space */ - void *xItVpdAreas; /* VPD Data 0x00 */ - void *xRamDisk; /* iSeries ramdisk 0x08 */ - u64 xRamDiskSize; /* In pages 0x10 */ -}; - -extern struct naca_struct naca; - -#endif /* _NACA_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/people/dgibson From david at gibson.dropbear.id.au Tue Nov 1 16:53:24 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Tue, 1 Nov 2005 16:53:24 +1100 Subject: powerpc: Merge ipcbuf.h Message-ID: <20051101055324.GA3551@localhost.localdomain> Paulus, please apply. This patch merges ppc32 and ppc64 versions of ipcbuf.h. The merge is essentially trivial, since the structure defined in each version was already identical. Only wrinkle is that the merged version now includes linux/types.h in order to get the fixed width integer types. In fact, the old versions probably should have been including that anyway, since the file uses various __kernel_*_t types. Built and booted on G5, built for 32-bit pmac, but not booted, since the merge tree currently doesn't boot there. Signed-off-by: David Gibson Index: working-2.6/include/asm-powerpc/ipcbuf.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ working-2.6/include/asm-powerpc/ipcbuf.h 2005-11-01 15:44:01.000000000 +1100 @@ -0,0 +1,34 @@ +#ifndef _ASM_POWERPC_IPCBUF_H +#define _ASM_POWERPC_IPCBUF_H + +/* + * The ipc64_perm structure for the powerpc is identical to + * kern_ipc_perm as we have always had 32-bit UIDs and GIDs in the + * kernel. Note extra padding because this structure is passed back + * and forth between kernel and user space. Pad space is left for: + * - 1 32-bit value to fill up for 8-byte alignment + * - 2 miscellaneous 64-bit values + * + * 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 + +struct ipc64_perm +{ + __kernel_key_t key; + __kernel_uid_t uid; + __kernel_gid_t gid; + __kernel_uid_t cuid; + __kernel_gid_t cgid; + __kernel_mode_t mode; + unsigned int seq; + unsigned int __pad1; + u64 __unused1; + u64 __unused2; +}; + +#endif /* _ASM_POWERPC_IPCBUF_H */ Index: working-2.6/include/asm-ppc64/ipcbuf.h =================================================================== --- working-2.6.orig/include/asm-ppc64/ipcbuf.h 2005-10-25 11:59:59.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -#ifndef __PPC64_IPCBUF_H__ -#define __PPC64_IPCBUF_H__ - -/* - * The ipc64_perm structure for the PPC is identical to kern_ipc_perm - * as we have always had 32-bit UIDs and GIDs in the kernel. - * - * 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. - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned int seq; - unsigned int __pad1; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* __PPC64_IPCBUF_H__ */ Index: working-2.6/include/asm-ppc/ipcbuf.h =================================================================== --- working-2.6.orig/include/asm-ppc/ipcbuf.h 2005-10-25 11:59:59.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#ifndef __PPC_IPCBUF_H__ -#define __PPC_IPCBUF_H__ - -/* - * The ipc64_perm structure for PPC architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 1 32-bit value to fill up for 8-byte alignment - * - 2 miscellaneous 64-bit values (so that this structure matches - * PPC64 ipc64_perm) - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid_t uid; - __kernel_gid_t gid; - __kernel_uid_t cuid; - __kernel_gid_t cgid; - __kernel_mode_t mode; - unsigned long seq; - unsigned int __pad2; - unsigned long long __unused1; - unsigned long long __unused2; -}; - -#endif /* __PPC_IPCBUF_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/people/dgibson From david at gibson.dropbear.id.au Tue Nov 1 17:28:10 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Tue, 1 Nov 2005 17:28:10 +1100 Subject: powerpc: Merge bitops.h In-Reply-To: <20051031064823.GD6622@localhost.localdomain> References: <20051031064823.GD6622@localhost.localdomain> Message-ID: <20051101062810.GC3551@localhost.localdomain> Here's a revised version. This re-introduces the set_bits() function from ppc64, which I removed because I thought it was unused (it exists on no other arch). In fact it is used in the powermac interrupt code (but not on pSeries). This seems to be running fine on my G5 (ARCH=powerpc), but it still hasn't been tested on 32-bit, which should probably happen before merging. - We use LARXL/STCXL macros to generate the right (32 or 64 bit) instructions, similar to LDL/STL from ppc_asm.h, used in fpu.S - ppc32 previously used a full "sync" barrier at the end of test_and_*_bit(), whereas ppc64 used an "isync". The merged version uses "isync", since I believe that's sufficient. - The ppc64 versions of then minix_*() bitmap functions have changed semantics. Previously on ppc64, these functions were big-endian (that is bit 0 was the LSB in the first 64-bit, big-endian word). On ppc32 (and x86, for that matter, they were little-endian. As far as I can tell, the big-endian usage was simply wrong - I guess no-one ever tried to use minixfs on ppc64. - On ppc32 find_next_bit() and find_next_zero_bit() are no longer inline (they were already out-of-line on ppc64). - For ppc64, sched_find_first_bit() has moved from mmu_context.h to the merged bitops. What it was doing in mmu_context.h in the first place, I have no idea. - The fls() function is now implemented using the cntlzw instruction on ppc64, instead of generic_fls(), as it already was on ppc32. - For ARCH=ppc, this patch requires adding arch/powerpc/lib to the arch/ppc/Makefile. This in turn requires some changes to arch/powerpc/lib/Makefile which didn't correctly handle ARCH=ppc. Built and running on G5. Signed-off-by: David Gibson Index: working-2.6/include/asm-ppc/bitops.h =================================================================== --- working-2.6.orig/include/asm-ppc/bitops.h 2005-10-25 11:59:59.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,460 +0,0 @@ -/* - * bitops.h: Bit string operations on the ppc - */ - -#ifdef __KERNEL__ -#ifndef _PPC_BITOPS_H -#define _PPC_BITOPS_H - -#include -#include -#include -#include - -/* - * The test_and_*_bit operations are taken to imply a memory barrier - * on SMP systems. - */ -#ifdef CONFIG_SMP -#define SMP_WMB "eieio\n" -#define SMP_MB "\nsync" -#else -#define SMP_WMB -#define SMP_MB -#endif /* CONFIG_SMP */ - -static __inline__ void set_bit(int nr, volatile unsigned long * addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - or %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc" ); -} - -/* - * non-atomic version - */ -static __inline__ void __set_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - *p |= mask; -} - -/* - * clear_bit doesn't imply a memory barrier - */ -#define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() smp_mb() - -static __inline__ void clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - andc %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -/* - * non-atomic version - */ -static __inline__ void __clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - *p &= ~mask; -} - -static __inline__ void change_bit(int nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 \n\ - xor %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -/* - * non-atomic version - */ -static __inline__ void __change_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - *p ^= mask; -} - -/* - * test_and_*_bit do imply a memory barrier (?) - */ -static __inline__ int test_and_set_bit(int nr, volatile unsigned long *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - or %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -/* - * non-atomic version - */ -static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - unsigned long old = *p; - - *p = old | mask; - return (old & mask) != 0; -} - -static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - andc %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -/* - * non-atomic version - */ -static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - unsigned long old = *p; - - *p = old & ~mask; - return (old & mask) != 0; -} - -static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - xor %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -/* - * non-atomic version - */ -static __inline__ int __test_and_change_bit(int nr, volatile unsigned long *addr) -{ - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - unsigned long old = *p; - - *p = old ^ mask; - return (old & mask) != 0; -} - -static __inline__ int test_bit(int nr, __const__ volatile unsigned long *addr) -{ - return ((addr[nr >> 5] >> (nr & 0x1f)) & 1) != 0; -} - -/* Return the bit position of the most significant 1 bit in a word */ -static __inline__ int __ilog2(unsigned long x) -{ - int lz; - - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); - return 31 - lz; -} - -static __inline__ int ffz(unsigned long x) -{ - if ((x = ~x) == 0) - return 32; - return __ilog2(x & -x); -} - -static inline int __ffs(unsigned long x) -{ - return __ilog2(x & -x); -} - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __inline__ int ffs(int x) -{ - return __ilog2(x & -x) + 1; -} - -/* - * fls: find last (most-significant) bit set. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -static __inline__ int fls(unsigned int x) -{ - int lz; - - asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); - return 32 - lz; -} - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ - -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -/* - * Find the first bit set in a 140-bit bitmap. - * The first 100 bits are unlikely to be set. - */ -static inline int sched_find_first_bit(const unsigned long *b) -{ - if (unlikely(b[0])) - return __ffs(b[0]); - if (unlikely(b[1])) - return __ffs(b[1]) + 32; - if (unlikely(b[2])) - return __ffs(b[2]) + 64; - if (b[3]) - return __ffs(b[3]) + 96; - return __ffs(b[4]) + 128; -} - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -static __inline__ unsigned long find_next_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - unsigned int *p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = *p++; - tmp &= ~0UL << offset; - if (size < 32) - goto found_first; - if (tmp) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = *p++) != 0) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= ~0UL >> (32 - size); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} - -/** - * find_first_bit - find the first set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit-number of the first set bit, not the number of the byte - * containing a bit. - */ -#define find_first_bit(addr, size) \ - find_next_bit((addr), (size), 0) - -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ -#define find_first_zero_bit(addr, size) \ - find_next_zero_bit((addr), (size), 0) - -static __inline__ unsigned long find_next_zero_bit(const unsigned long *addr, - unsigned long size, unsigned long offset) -{ - unsigned int * p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = *p++; - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (tmp != ~0U) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = *p++) != ~0U) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - - -#define ext2_set_bit(nr, addr) __test_and_set_bit((nr) ^ 0x18, (unsigned long *)(addr)) -#define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 0x18, (unsigned long *)(addr)) -#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 0x18, (unsigned long *)(addr)) -#define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 0x18, (unsigned long *)(addr)) - -static __inline__ int ext2_test_bit(int nr, __const__ void * addr) -{ - __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - - return (ADDR[nr >> 3] >> (nr & 7)) & 1; -} - -/* - * This implementation of ext2_find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h and modified for a big-endian machine. - */ - -#define ext2_find_first_zero_bit(addr, size) \ - ext2_find_next_zero_bit((addr), (size), 0) - -static __inline__ unsigned long ext2_find_next_zero_bit(const void *addr, - unsigned long size, unsigned long offset) -{ - unsigned int *p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = cpu_to_le32p(p++); - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (tmp != ~0U) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = cpu_to_le32p(p++)) != ~0U) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = cpu_to_le32p(p); -found_first: - tmp |= ~0U << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -/* Bitmap functions for the minix filesystem. */ -#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr) -#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr)) -#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size) - -#endif /* _PPC_BITOPS_H */ -#endif /* __KERNEL__ */ Index: working-2.6/include/asm-ppc64/bitops.h =================================================================== --- working-2.6.orig/include/asm-ppc64/bitops.h 2005-10-31 15:20:22.000000000 +1100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,360 +0,0 @@ -/* - * PowerPC64 atomic bit operations. - * Dave Engebretsen, Todd Inglett, Don Reed, Pat McCarthy, Peter Bergner, - * Anton Blanchard - * - * Originally taken from the 32b PPC code. Modified to use 64b values for - * the various counters & memory references. - * - * Bitops are odd when viewed on big-endian systems. They were designed - * on little endian so the size of the bitset doesn't matter (low order bytes - * come first) as long as the bit in question is valid. - * - * Bits are "tested" often using the C expression (val & (1< - -/* - * clear_bit doesn't imply a memory barrier - */ -#define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() smp_mb() - -static __inline__ int test_bit(unsigned long nr, __const__ volatile unsigned long *addr) -{ - return (1UL & (addr[nr >> 6] >> (nr & 63))); -} - -static __inline__ void set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # set_bit\n\ - or %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -static __inline__ void clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # clear_bit\n\ - andc %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -static __inline__ void change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # change_bit\n\ - xor %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -static __inline__ int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old, t; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: ldarx %0,0,%3 # test_and_set_bit\n\ - or %1,%0,%2 \n\ - stdcx. %1,0,%3 \n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old, t; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: ldarx %0,0,%3 # test_and_clear_bit\n\ - andc %1,%0,%2\n\ - stdcx. %1,0,%3\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long old, t; - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - __asm__ __volatile__( - EIEIO_ON_SMP -"1: ldarx %0,0,%3 # test_and_change_bit\n\ - xor %1,%0,%2\n\ - stdcx. %1,0,%3\n\ - bne- 1b" - ISYNC_ON_SMP - : "=&r" (old), "=&r" (t) - : "r" (mask), "r" (p) - : "cc", "memory"); - - return (old & mask) != 0; -} - -static __inline__ void set_bits(unsigned long mask, unsigned long *addr) -{ - unsigned long old; - - __asm__ __volatile__( -"1: ldarx %0,0,%3 # set_bit\n\ - or %0,%0,%2\n\ - stdcx. %0,0,%3\n\ - bne- 1b" - : "=&r" (old), "=m" (*addr) - : "r" (mask), "r" (addr), "m" (*addr) - : "cc"); -} - -/* - * non-atomic versions - */ -static __inline__ void __set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - *p |= mask; -} - -static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - *p &= ~mask; -} - -static __inline__ void __change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - - *p ^= mask; -} - -static __inline__ int __test_and_set_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - unsigned long old = *p; - - *p = old | mask; - return (old & mask) != 0; -} - -static __inline__ int __test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - unsigned long old = *p; - - *p = old & ~mask; - return (old & mask) != 0; -} - -static __inline__ int __test_and_change_bit(unsigned long nr, volatile unsigned long *addr) -{ - unsigned long mask = 1UL << (nr & 0x3f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 6); - unsigned long old = *p; - - *p = old ^ mask; - return (old & mask) != 0; -} - -/* - * Return the zero-based bit position (from RIGHT TO LEFT, 63 -> 0) of the - * most significant (left-most) 1-bit in a double word. - */ -static __inline__ int __ilog2(unsigned long x) -{ - int lz; - - asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x)); - return 63 - lz; -} - -/* - * Determines the bit position of the least significant (rightmost) 0 bit - * in the specified double word. The returned bit position will be zero-based, - * starting from the right side (63 - 0). - */ -static __inline__ unsigned long ffz(unsigned long x) -{ - /* no zero exists anywhere in the 8 byte area. */ - if ((x = ~x) == 0) - return 64; - - /* - * Calculate the bit position of the least signficant '1' bit in x - * (since x has been changed this will actually be the least signficant - * '0' bit in * the original x). Note: (x & -x) gives us a mask that - * is the least significant * (RIGHT-most) 1-bit of the value in x. - */ - return __ilog2(x & -x); -} - -static __inline__ int __ffs(unsigned long x) -{ - return __ilog2(x & -x); -} - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __inline__ int ffs(int x) -{ - unsigned long i = (unsigned long)x; - return __ilog2(i & -i) + 1; -} - -/* - * fls: find last (most-significant) bit set. - * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. - */ -#define fls(x) generic_fls(x) - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ -#define hweight64(x) generic_hweight64(x) -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_first_zero_bit(addr, size) \ - find_next_zero_bit((addr), (size), 0) - -extern unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_first_bit(addr, size) \ - find_next_bit((addr), (size), 0) - -extern unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset); -#define find_first_zero_le_bit(addr, size) \ - find_next_zero_le_bit((addr), (size), 0) - -static __inline__ int test_le_bit(unsigned long nr, __const__ unsigned long * addr) -{ - __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; - return (ADDR[nr >> 3] >> (nr & 7)) & 1; -} - -#define test_and_clear_le_bit(nr, addr) \ - test_and_clear_bit((nr) ^ 0x38, (addr)) -#define test_and_set_le_bit(nr, addr) \ - test_and_set_bit((nr) ^ 0x38, (addr)) - -/* - * non-atomic versions - */ - -#define __set_le_bit(nr, addr) \ - __set_bit((nr) ^ 0x38, (addr)) -#define __clear_le_bit(nr, addr) \ - __clear_bit((nr) ^ 0x38, (addr)) -#define __test_and_clear_le_bit(nr, addr) \ - __test_and_clear_bit((nr) ^ 0x38, (addr)) -#define __test_and_set_le_bit(nr, addr) \ - __test_and_set_bit((nr) ^ 0x38, (addr)) - -#define ext2_set_bit(nr,addr) \ - __test_and_set_le_bit((nr), (unsigned long*)addr) -#define ext2_clear_bit(nr, addr) \ - __test_and_clear_le_bit((nr), (unsigned long*)addr) - -#define ext2_set_bit_atomic(lock, nr, addr) \ - test_and_set_le_bit((nr), (unsigned long*)addr) -#define ext2_clear_bit_atomic(lock, nr, addr) \ - test_and_clear_le_bit((nr), (unsigned long*)addr) - - -#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) -#define ext2_find_first_zero_bit(addr, size) \ - find_first_zero_le_bit((unsigned long*)addr, size) -#define ext2_find_next_zero_bit(addr, size, off) \ - find_next_zero_le_bit((unsigned long*)addr, size, off) - -#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) -#define minix_set_bit(nr,addr) set_bit(nr,addr) -#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) - -#endif /* __KERNEL__ */ -#endif /* _PPC64_BITOPS_H */ Index: working-2.6/arch/powerpc/lib/bitops.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ working-2.6/arch/powerpc/lib/bitops.c 2005-11-01 15:51:56.000000000 +1100 @@ -0,0 +1,150 @@ +#include +#include +#include +#include + +/** + * find_next_bit - find the next set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < BITS_PER_LONG) + goto found_first; + if (tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if ((tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (64 - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __ffs(tmp); +} +EXPORT_SYMBOL(find_next_bit); + +/* + * This implementation of find_{first,next}_zero_bit was stolen from + * Linus' asm-alpha/bitops.h. + */ +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG-1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (BITS_PER_LONG - offset); + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG-1)) { + if (~(tmp = *(p++))) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} +EXPORT_SYMBOL(find_next_zero_bit); + +static inline unsigned int ext2_ilog2(unsigned int x) +{ + int lz; + + asm("cntlzw %0,%1": "=r"(lz):"r"(x)); + return 31 - lz; +} + +static inline unsigned int ext2_ffz(unsigned int x) +{ + u32 rc; + if ((x = ~x) == 0) + return 32; + rc = ext2_ilog2(x & -x); + return rc; +} + +unsigned long find_next_zero_le_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) +{ + const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5); + unsigned int result = offset & ~31; + unsigned int tmp; + + if (offset >= size) + return size; + size -= result; + offset &= 31; + if (offset) { + tmp = cpu_to_le32p(p++); + tmp |= ~0U >> (32 - offset); /* bug or feature ? */ + if (size < 32) + goto found_first; + if (tmp != ~0) + goto found_middle; + size -= 32; + result += 32; + } + while (size >= 32) { + if ((tmp = cpu_to_le32p(p++)) != ~0) + goto found_middle; + result += 32; + size -= 32; + } + if (!size) + return result; + tmp = cpu_to_le32p(p); +found_first: + tmp |= ~0 << size; + if (tmp == ~0) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ext2_ffz(tmp); +} +EXPORT_SYMBOL(find_next_zero_le_bit); Index: working-2.6/arch/ppc64/kernel/bitops.c =================================================================== --- working-2.6.orig/arch/ppc64/kernel/bitops.c 2005-10-25 11:59:53.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -/* - * These are too big to be inlined. - */ - -#include -#include -#include -#include - -unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (64 - offset); - if (size < 64) - goto found_first; - if (~tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -EXPORT_SYMBOL(find_next_zero_bit); - -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + (offset >> 6); - unsigned long result = offset & ~63UL; - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 63UL; - if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < 64) - goto found_first; - if (tmp) - goto found_middle; - size -= 64; - result += 64; - } - while (size & ~63UL) { - if ((tmp = *(p++))) - goto found_middle; - result += 64; - size -= 64; - } - if (!size) - return result; - tmp = *p; - -found_first: - tmp &= (~0UL >> (64 - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} - -EXPORT_SYMBOL(find_next_bit); - -static inline unsigned int ext2_ilog2(unsigned int x) -{ - int lz; - - asm("cntlzw %0,%1": "=r"(lz):"r"(x)); - return 31 - lz; -} - -static inline unsigned int ext2_ffz(unsigned int x) -{ - u32 rc; - if ((x = ~x) == 0) - return 32; - rc = ext2_ilog2(x & -x); - return rc; -} - -unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5); - unsigned int result = offset & ~31; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31; - if (offset) { - tmp = cpu_to_le32p(p++); - tmp |= ~0U >> (32 - offset); /* bug or feature ? */ - if (size < 32) - goto found_first; - if (tmp != ~0) - goto found_middle; - size -= 32; - result += 32; - } - while (size >= 32) { - if ((tmp = cpu_to_le32p(p++)) != ~0) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = cpu_to_le32p(p); -found_first: - tmp |= ~0 << size; - if (tmp == ~0) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ext2_ffz(tmp); -} - -EXPORT_SYMBOL(find_next_zero_le_bit); Index: working-2.6/arch/powerpc/kernel/ppc_ksyms.c =================================================================== --- working-2.6.orig/arch/powerpc/kernel/ppc_ksyms.c 2005-10-31 15:20:57.000000000 +1100 +++ working-2.6/arch/powerpc/kernel/ppc_ksyms.c 2005-11-01 15:51:56.000000000 +1100 @@ -81,15 +81,6 @@ EXPORT_SYMBOL(ucSystemType); #endif -#if !defined(__INLINE_BITOPS) -EXPORT_SYMBOL(set_bit); -EXPORT_SYMBOL(clear_bit); -EXPORT_SYMBOL(change_bit); -EXPORT_SYMBOL(test_and_set_bit); -EXPORT_SYMBOL(test_and_clear_bit); -EXPORT_SYMBOL(test_and_change_bit); -#endif /* __INLINE_BITOPS */ - EXPORT_SYMBOL(strcpy); EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strcat); Index: working-2.6/arch/ppc/kernel/bitops.c =================================================================== --- working-2.6.orig/arch/ppc/kernel/bitops.c 2005-10-25 11:59:53.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright (C) 1996 Paul Mackerras. - */ - -#include -#include - -/* - * If the bitops are not inlined in bitops.h, they are defined here. - * -- paulus - */ -#if !__INLINE_BITOPS -void set_bit(int nr, volatile void * addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%3 \n\ - or %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc" ); -} - -void clear_bit(int nr, volatile void *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%3 \n\ - andc %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -void change_bit(int nr, volatile void *addr) -{ - unsigned long old; - unsigned long mask = 1 << (nr & 0x1f); - unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%3 \n\ - xor %0,%0,%2 \n" - PPC405_ERR77(0,%3) -" stwcx. %0,0,%3 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); -} - -int test_and_set_bit(int nr, volatile void *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - or %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); - - return (old & mask) != 0; -} - -int test_and_clear_bit(int nr, volatile void *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - andc %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); - - return (old & mask) != 0; -} - -int test_and_change_bit(int nr, volatile void *addr) -{ - unsigned int old, t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - __asm__ __volatile__(SMP_WMB "\n\ -1: lwarx %0,0,%4 \n\ - xor %1,%0,%3 \n" - PPC405_ERR77(0,%4) -" stwcx. %1,0,%4 \n\ - bne 1b" - SMP_MB - : "=&r" (old), "=&r" (t), "=m" (*p) - : "r" (mask), "r" (p), "m" (*p) - : "cc"); - - return (old & mask) != 0; -} -#endif /* !__INLINE_BITOPS */ Index: working-2.6/arch/ppc64/kernel/Makefile =================================================================== --- working-2.6.orig/arch/ppc64/kernel/Makefile 2005-10-31 15:20:57.000000000 +1100 +++ working-2.6/arch/ppc64/kernel/Makefile 2005-11-01 15:51:56.000000000 +1100 @@ -13,7 +13,7 @@ obj-y += irq.o idle.o dma.o \ signal.o \ - align.o bitops.o pacaData.o \ + align.o pacaData.o \ udbg.o ioctl32.o \ rtc.o \ cpu_setup_power4.o \ Index: working-2.6/include/asm-powerpc/bitops.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ working-2.6/include/asm-powerpc/bitops.h 2005-11-01 15:51:56.000000000 +1100 @@ -0,0 +1,437 @@ +/* + * PowerPC atomic bit operations. + * + * Merged version by David Gibson . + * Based on ppc64 versions by: Dave Engebretsen, Todd Inglett, Don + * Reed, Pat McCarthy, Peter Bergner, Anton Blanchard. They + * originally took it from the ppc32 code. + * + * Within a word, bits are numbered LSB first. Lot's of places make + * this assumption by directly testing bits with (val & (1< 1 word) bitmaps on a + * big-endian system because, unlike little endian, the number of each + * bit depends on the word size. + * + * The bitop functions are defined to work on unsigned longs, so for a + * ppc64 system the bits end up numbered: + * |63..............0|127............64|191...........128|255...........196| + * and on ppc32: + * |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224| + * + * There are a few little-endian macros used mostly for filesystem + * bitmaps, these work on similar bit arrays layouts, but + * byte-oriented: + * |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56| + * + * The main difference is that bit 3-5 (64b) or 3-4 (32b) in the bit + * number field needs to be reversed compared to the big-endian bit + * fields. This can be achieved by XOR with 0x38 (64b) or 0x18 (32b). + * + * 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. + */ + +#ifndef _ASM_POWERPC_BITOPS_H +#define _ASM_POWERPC_BITOPS_H + +#ifdef __KERNEL__ + +#include +#include +#include + +/* + * clear_bit doesn't imply a memory barrier + */ +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() smp_mb() + +#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7) + +#ifdef CONFIG_PPC64 +#define LARXL "ldarx" +#define STCXL "stdcx." +#define CNTLZL "cntlzd" +#else +#define LARXL "lwarx" +#define STCXL "stwcx." +#define CNTLZL "cntlzw" +#endif + +static __inline__ void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "or %0,%0,%2\n" + PPC405_ERR77(0,%3) + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r"(old), "=m"(*p) + : "r"(mask), "r"(p), "m"(*p) + : "cc" ); +} + +static __inline__ void clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "andc %0,%0,%2\n" + PPC405_ERR77(0,%3) + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r"(old), "=m"(*p) + : "r"(mask), "r"(p), "m"(*p) + : "cc" ); +} + +static __inline__ void change_bit(int nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "xor %0,%0,%2\n" + PPC405_ERR77(0,%3) + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r"(old), "=m"(*p) + : "r"(mask), "r"(p), "m"(*p) + : "cc" ); +} + +static __inline__ int test_and_set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1:" LARXL " %0,0,%3 # test_and_set_bit\n" + "or %1,%0,%2 \n" + PPC405_ERR77(0,%3) + STCXL " %1,0,%3 \n" + "bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ int test_and_clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1:" LARXL " %0,0,%3 # test_and_clear_bit\n" + "andc %1,%0,%2 \n" + PPC405_ERR77(0,%3) + STCXL " %1,0,%3 \n" + "bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ int test_and_change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1:" LARXL " %0,0,%3 # test_and_change_bit\n" + "xor %1,%0,%2 \n" + PPC405_ERR77(0,%3) + STCXL " %1,0,%3 \n" + "bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ void set_bits(unsigned long mask, unsigned long *addr) +{ + unsigned long old; + + __asm__ __volatile__( +"1:" LARXL " %0,0,%3 # set_bit\n" + "or %0,%0,%2\n" + STCXL " %0,0,%3\n" + "bne- 1b" + : "=&r" (old), "=m" (*addr) + : "r" (mask), "r" (addr), "m" (*addr) + : "cc"); +} + +/* Non-atomic versions */ +static __inline__ int test_bit(unsigned long nr, + __const__ volatile unsigned long *addr) +{ + return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} + +static __inline__ void __set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + *p |= mask; +} + +static __inline__ void __clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + *p &= ~mask; +} + +static __inline__ void __change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + + *p ^= mask; +} + +static __inline__ int __test_and_set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + unsigned long old = *p; + + *p = old | mask; + return (old & mask) != 0; +} + +static __inline__ int __test_and_clear_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + unsigned long old = *p; + + *p = old & ~mask; + return (old & mask) != 0; +} + +static __inline__ int __test_and_change_bit(unsigned long nr, + volatile unsigned long *addr) +{ + unsigned long mask = BITOP_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr); + unsigned long old = *p; + + *p = old ^ mask; + return (old & mask) != 0; +} + +/* + * Return the zero-based bit position (LE, not IBM bit numbering) of + * the most significant 1-bit in a double word. + */ +static __inline__ int __ilog2(unsigned long x) +{ + int lz; + + asm (CNTLZL " %0,%1" : "=r" (lz) : "r" (x)); + return BITS_PER_LONG - 1 - lz; +} + +/* + * Determines the bit position of the least significant 0 bit in the + * specified double word. The returned bit position will be + * zero-based, starting from the right side (63/31 - 0). + */ +static __inline__ unsigned long ffz(unsigned long x) +{ + /* no zero exists anywhere in the 8 byte area. */ + if ((x = ~x) == 0) + return BITS_PER_LONG; + + /* + * Calculate the bit position of the least signficant '1' bit in x + * (since x has been changed this will actually be the least signficant + * '0' bit in * the original x). Note: (x & -x) gives us a mask that + * is the least significant * (RIGHT-most) 1-bit of the value in x. + */ + return __ilog2(x & -x); +} + +static __inline__ int __ffs(unsigned long x) +{ + return __ilog2(x & -x); +} + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static __inline__ int ffs(int x) +{ + unsigned long i = (unsigned long)x; + return __ilog2(i & -i) + 1; +} + +/* + * fls: find last (most-significant) bit set. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +static __inline__ int fls(unsigned int x) +{ + int lz; + + asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); + return 32 - lz; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ +#define hweight64(x) generic_hweight64(x) +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) +unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); +/** + * find_first_bit - find the first set bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first set bit, not the number of the byte + * containing a bit. + */ +#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) +unsigned long find_next_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); + +/* Little-endian versions */ + +static __inline__ int test_le_bit(unsigned long nr, + __const__ unsigned long *addr) +{ + __const__ unsigned char *tmp = (__const__ unsigned char *) addr; + return (tmp[nr >> 3] >> (nr & 7)) & 1; +} + +#define __set_le_bit(nr, addr) \ + __set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define __clear_le_bit(nr, addr) \ + __clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) + +#define test_and_set_le_bit(nr, addr) \ + test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define test_and_clear_le_bit(nr, addr) \ + test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) + +#define __test_and_set_le_bit(nr, addr) \ + __test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) +#define __test_and_clear_le_bit(nr, addr) \ + __test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr)) + +#define find_first_zero_le_bit(addr, size) find_next_zero_le_bit((addr), (size), 0) +unsigned long find_next_zero_le_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); + +/* Bitmap functions for the ext2 filesystem */ + +#define ext2_set_bit(nr,addr) \ + __test_and_set_le_bit((nr), (unsigned long*)addr) +#define ext2_clear_bit(nr, addr) \ + __test_and_clear_le_bit((nr), (unsigned long*)addr) + +#define ext2_set_bit_atomic(lock, nr, addr) \ + test_and_set_le_bit((nr), (unsigned long*)addr) +#define ext2_clear_bit_atomic(lock, nr, addr) \ + test_and_clear_le_bit((nr), (unsigned long*)addr) + +#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) + +#define ext2_find_first_zero_bit(addr, size) \ + find_first_zero_le_bit((unsigned long*)addr, size) +#define ext2_find_next_zero_bit(addr, size, off) \ + find_next_zero_le_bit((unsigned long*)addr, size, off) + +/* Bitmap functions for the minix filesystem. */ + +#define minix_test_and_set_bit(nr,addr) \ + __test_and_set_le_bit(nr, (unsigned long *)addr) +#define minix_set_bit(nr,addr) \ + __set_le_bit(nr, (unsigned long *)addr) +#define minix_test_and_clear_bit(nr,addr) \ + __test_and_clear_le_bit(nr, (unsigned long *)addr) +#define minix_test_bit(nr,addr) \ + test_le_bit(nr, (unsigned long *)addr) + +#define minix_find_first_zero_bit(addr,size) \ + find_first_zero_le_bit((unsigned long *)addr, size) + +/* + * Every architecture must define this function. It's the fastest + * way of searching a 140-bit bitmap where the first 100 bits are + * unlikely to be set. It's guaranteed that at least one of the 140 + * bits is cleared. + */ +static inline int sched_find_first_bit(const unsigned long *b) +{ +#ifdef CONFIG_PPC64 + if (unlikely(b[0])) + return __ffs(b[0]); + if (unlikely(b[1])) + return __ffs(b[1]) + 64; + return __ffs(b[2]) + 128; +#else + if (unlikely(b[0])) + return __ffs(b[0]); + if (unlikely(b[1])) + return __ffs(b[1]) + 32; + if (unlikely(b[2])) + return __ffs(b[2]) + 64; + if (b[3]) + return __ffs(b[3]) + 96; + return __ffs(b[4]) + 128; +#endif +} + +#endif /* __KERNEL__ */ + +#endif /* _ASM_POWERPC_BITOPS_H */ Index: working-2.6/include/asm-ppc64/mmu_context.h =================================================================== --- working-2.6.orig/include/asm-ppc64/mmu_context.h 2005-10-25 11:59:59.000000000 +1000 +++ working-2.6/include/asm-ppc64/mmu_context.h 2005-11-01 15:51:56.000000000 +1100 @@ -16,21 +16,6 @@ * 2 of the License, or (at your option) any later version. */ -/* - * Every architecture must define this function. It's the fastest - * way of searching a 140-bit bitmap where the first 100 bits are - * unlikely to be set. It's guaranteed that at least one of the 140 - * bits is cleared. - */ -static inline int sched_find_first_bit(unsigned long *b) -{ - if (unlikely(b[0])) - return __ffs(b[0]); - if (unlikely(b[1])) - return __ffs(b[1]) + 64; - return __ffs(b[2]) + 128; -} - static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { } Index: working-2.6/arch/ppc/Makefile =================================================================== --- working-2.6.orig/arch/ppc/Makefile 2005-10-31 15:20:57.000000000 +1100 +++ working-2.6/arch/ppc/Makefile 2005-11-01 15:51:56.000000000 +1100 @@ -66,7 +66,8 @@ core-y += arch/ppc/kernel/ arch/powerpc/kernel/ \ arch/ppc/platforms/ \ arch/ppc/mm/ arch/ppc/lib/ \ - arch/ppc/syslib/ arch/powerpc/sysdev/ + arch/ppc/syslib/ arch/powerpc/sysdev/ \ + arch/powerpc/lib/ core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/ core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/ core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/ Index: working-2.6/arch/powerpc/lib/Makefile =================================================================== --- working-2.6.orig/arch/powerpc/lib/Makefile 2005-10-31 15:20:57.000000000 +1100 +++ working-2.6/arch/powerpc/lib/Makefile 2005-11-01 15:51:56.000000000 +1100 @@ -3,13 +3,14 @@ # ifeq ($(CONFIG_PPC_MERGE),y) -obj-y := string.o +obj-y := string.o strcase.o +obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o endif -obj-y += strcase.o -obj-$(CONFIG_PPC32) += div64.o copy_32.o checksum_32.o +obj-y += bitops.o obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \ - memcpy_64.o usercopy_64.o mem_64.o + memcpy_64.o usercopy_64.o mem_64.o \ + strcase.o obj-$(CONFIG_PPC_ISERIES) += e2a.o obj-$(CONFIG_XMON) += sstep.o -- 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/people/dgibson From mikey at neuling.org Tue Nov 1 18:14:40 2005 From: mikey at neuling.org (Michael Neuling) Date: Tue, 1 Nov 2005 18:14:40 +1100 (EST) Subject: [PATCH 0/3] powerpc: Fix legacy drivers for remove io_page_mask patch Message-ID: <1130829279.790724.373020147318.qpush@coopers> These patches are the same as I send the other day, except updated for the merge tree. Also now contains an updated version of Anton's original patch which will apply cleanly to the merge tree. Anton's patch is necessary for running kexec with some e1000 revisions. The issue we have is that the reset is not being sent to the e1000 correctly, resulting in it still running during the second boot. Other two patches fix drivers which have issues with the first patch. Mikey From mikey at neuling.org Tue Nov 1 18:14:41 2005 From: mikey at neuling.org (Michael Neuling) Date: Tue, 1 Nov 2005 18:14:41 +1100 (EST) Subject: [PATCH 1/3] powerpc: Updated remove io_page_mask In-Reply-To: <1130829279.790724.373020147318.qpush@coopers> Message-ID: <20051101071441.1C53668662@ozlabs.org> From: Anton Blanchard Retransmit of Anton's patch from here: http://ozlabs.org/pipermail/linuxppc64-dev/2005-May/003922.html Updated for merge tree. Signed-off-by: Michael Neuling arch/powerpc/platforms/iseries/pci.c | 3 --- arch/powerpc/platforms/maple/pci.c | 3 --- arch/powerpc/platforms/powermac/pci.c | 3 --- arch/ppc64/kernel/iomap.c | 2 -- arch/ppc64/kernel/pci.c | 30 +++--------------------------- include/asm-ppc64/eeh.h | 15 +++------------ include/asm-ppc64/io.h | 6 ------ 7 files changed, 6 insertions(+), 56 deletions(-) Index: linux-2.6/arch/powerpc/platforms/iseries/pci.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/iseries/pci.c 2005-11-01 10:30:35.000000000 +1100 +++ linux-2.6/arch/powerpc/platforms/iseries/pci.c 2005-11-01 11:04:27.000000000 +1100 @@ -45,8 +45,6 @@ #include "pci.h" #include "call_pci.h" -extern unsigned long io_page_mask; - /* * Forward declares of prototypes. */ @@ -288,7 +286,6 @@ PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); iomm_table_initialize(); find_and_init_phbs(); - io_page_mask = -1; PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); } Index: linux-2.6/arch/powerpc/platforms/maple/pci.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/maple/pci.c 2005-11-01 10:30:35.000000000 +1100 +++ linux-2.6/arch/powerpc/platforms/maple/pci.c 2005-11-01 11:06:30.000000000 +1100 @@ -455,9 +455,6 @@ /* Tell pci.c to use the common resource allocation mecanism */ pci_probe_only = 0; - - /* Allow all IO */ - io_page_mask = -1; } int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) Index: linux-2.6/arch/powerpc/platforms/powermac/pci.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/powermac/pci.c 2005-11-01 10:30:35.000000000 +1100 +++ linux-2.6/arch/powerpc/platforms/powermac/pci.c 2005-11-01 11:10:07.000000000 +1100 @@ -926,9 +926,6 @@ /* Tell pci.c to not use the common resource allocation mechanism */ pci_probe_only = 1; - /* Allow all IO */ - io_page_mask = -1; - #else /* CONFIG_PPC64 */ init_p2pbridge(); fixup_nec_usb2(); Index: linux-2.6/arch/ppc64/kernel/iomap.c =================================================================== --- linux-2.6.orig/arch/ppc64/kernel/iomap.c 2005-11-01 10:30:32.000000000 +1100 +++ linux-2.6/arch/ppc64/kernel/iomap.c 2005-11-01 11:05:01.000000000 +1100 @@ -108,8 +108,6 @@ void __iomem *ioport_map(unsigned long port, unsigned int len) { - if (!_IO_IS_VALID(port)) - return NULL; return (void __iomem *) (port+pci_io_base); } Index: linux-2.6/arch/ppc64/kernel/pci.c =================================================================== --- linux-2.6.orig/arch/ppc64/kernel/pci.c 2005-11-01 10:30:35.000000000 +1100 +++ linux-2.6/arch/ppc64/kernel/pci.c 2005-11-01 11:08:44.000000000 +1100 @@ -42,14 +42,6 @@ unsigned long pci_probe_only = 1; unsigned long pci_assign_all_buses = 0; -/* - * legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch - * devices we don't have access to. - */ -unsigned long io_page_mask; - -EXPORT_SYMBOL(io_page_mask); - #ifdef CONFIG_PPC_MULTIPLATFORM static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); @@ -995,8 +987,6 @@ pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, hose->io_base_virt); of_node_put(isa_dn); - /* Allow all IO */ - io_page_mask = -1; } } @@ -1132,27 +1122,13 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) { struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned long start, end, mask, offset; + unsigned long offset; if (res->flags & IORESOURCE_IO) { offset = (unsigned long)hose->io_base_virt - pci_io_base; - start = res->start += offset; - end = res->end += offset; - - /* Need to allow IO access to pages that are in the - ISA range */ - if (start < MAX_ISA_PORT) { - if (end > MAX_ISA_PORT) - end = MAX_ISA_PORT; - - start >>= PAGE_SHIFT; - end >>= PAGE_SHIFT; - - /* get the range of pages for the map */ - mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1); - io_page_mask |= mask; - } + res->start += offset; + res->end += offset; } else if (res->flags & IORESOURCE_MEM) { res->start += hose->pci_mem_offset; res->end += hose->pci_mem_offset; Index: linux-2.6/include/asm-ppc64/eeh.h =================================================================== --- linux-2.6.orig/include/asm-ppc64/eeh.h 2005-11-01 10:30:32.000000000 +1100 +++ linux-2.6/include/asm-ppc64/eeh.h 2005-11-01 11:13:05.000000000 +1100 @@ -311,8 +311,6 @@ static inline u8 eeh_inb(unsigned long port) { u8 val; - if (!_IO_IS_VALID(port)) - return ~0; val = in_8((u8 __iomem *)(port+pci_io_base)); if (EEH_POSSIBLE_ERROR(val, u8)) return eeh_check_failure((void __iomem *)(port), val); @@ -321,15 +319,12 @@ static inline void eeh_outb(u8 val, unsigned long port) { - if (_IO_IS_VALID(port)) - out_8((u8 __iomem *)(port+pci_io_base), val); + out_8((u8 __iomem *)(port+pci_io_base), val); } static inline u16 eeh_inw(unsigned long port) { u16 val; - if (!_IO_IS_VALID(port)) - return ~0; val = in_le16((u16 __iomem *)(port+pci_io_base)); if (EEH_POSSIBLE_ERROR(val, u16)) return eeh_check_failure((void __iomem *)(port), val); @@ -338,15 +333,12 @@ static inline void eeh_outw(u16 val, unsigned long port) { - if (_IO_IS_VALID(port)) - out_le16((u16 __iomem *)(port+pci_io_base), val); + out_le16((u16 __iomem *)(port+pci_io_base), val); } static inline u32 eeh_inl(unsigned long port) { u32 val; - if (!_IO_IS_VALID(port)) - return ~0; val = in_le32((u32 __iomem *)(port+pci_io_base)); if (EEH_POSSIBLE_ERROR(val, u32)) return eeh_check_failure((void __iomem *)(port), val); @@ -355,8 +347,7 @@ static inline void eeh_outl(u32 val, unsigned long port) { - if (_IO_IS_VALID(port)) - out_le32((u32 __iomem *)(port+pci_io_base), val); + out_le32((u32 __iomem *)(port+pci_io_base), val); } /* in-string eeh macros */ Index: linux-2.6/include/asm-ppc64/io.h =================================================================== --- linux-2.6.orig/include/asm-ppc64/io.h 2005-11-01 10:30:35.000000000 +1100 +++ linux-2.6/include/asm-ppc64/io.h 2005-11-01 11:13:40.000000000 +1100 @@ -33,12 +33,6 @@ extern unsigned long isa_io_base; extern unsigned long pci_io_base; -extern unsigned long io_page_mask; - -#define MAX_ISA_PORT 0x10000 - -#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \ - & io_page_mask) #ifdef CONFIG_PPC_ISERIES /* __raw_* accessors aren't supported on iSeries */ From mikey at neuling.org Tue Nov 1 18:14:41 2005 From: mikey at neuling.org (Michael Neuling) Date: Tue, 1 Nov 2005 18:14:41 +1100 (EST) Subject: [PATCH 2/3] powerpc: Updated parallel port init fix In-Reply-To: <1130829279.790724.373020147318.qpush@coopers> Message-ID: <20051101071441.1B6BB68665@ozlabs.org> Updated for powerpc merge tree. Signed-off-by: Michael Neuling include/asm-powerpc/parport.h | 28 ++++++++++++++++++++++++++-- 1 files changed, 26 insertions(+), 2 deletions(-) Index: linux-2.6/include/asm-powerpc/parport.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/parport.h 2005-11-01 10:30:35.000000000 +1100 +++ linux-2.6/include/asm-powerpc/parport.h 2005-11-01 11:35:05.000000000 +1100 @@ -9,10 +9,34 @@ #ifndef _ASM_POWERPC_PARPORT_H #define _ASM_POWERPC_PARPORT_H -static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma); +#include + +extern struct parport *parport_pc_probe_port (unsigned long int base, + unsigned long int base_hi, + int irq, int dma, + struct pci_dev *dev); + static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) { - return parport_pc_find_isa_ports (autoirq, autodma); + struct device_node *np; + u32 *prop; + u32 io1, io2; + int propsize; + int count = 0; + for (np = NULL; (np = of_find_compatible_node(np, + "parallel", + "pnpPNP,400")) != NULL;) { + prop = (u32 *)get_property(np, "reg", &propsize); + if (!prop || propsize > 6*sizeof(u32)) + continue; + io1 = prop[1]; io2 = prop[2]; + prop = (u32 *)get_property(np, "interrupts", NULL); + if (!prop) + continue; + if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL) != NULL) + count++; + } + return count; } #endif /* !(_ASM_POWERPC_PARPORT_H) */ From mikey at neuling.org Tue Nov 1 18:14:42 2005 From: mikey at neuling.org (Michael Neuling) Date: Tue, 1 Nov 2005 18:14:42 +1100 (EST) Subject: [PATCH 3/3] powerpc: Updated PC speaker init fix In-Reply-To: <1130829279.790724.373020147318.qpush@coopers> Message-ID: <20051101071442.CD1C66866A@ozlabs.org> Updated for powerpc merge tree. Adds architecture specific init to pcspkr. Signed-off-by: Michael Neuling Acked-by: Paul Mackerras drivers/input/misc/pcspkr.c | 5 +++++ include/asm-powerpc/8253pit.h | 13 +++++++++++++ 2 files changed, 18 insertions(+) Index: linux-2.6/drivers/input/misc/pcspkr.c =================================================================== --- linux-2.6.orig/drivers/input/misc/pcspkr.c 2005-10-31 15:16:39.000000000 +1100 +++ linux-2.6/drivers/input/misc/pcspkr.c 2005-10-31 15:21:13.000000000 +1100 @@ -66,6 +66,11 @@ static int __init pcspkr_init(void) { +#ifdef HAS_PCSPKR_ARCH_INIT + int rc = pcspkr_arch_init(); + if (rc) + return rc; +#endif pcspkr_dev = input_allocate_device(); if (!pcspkr_dev) return -ENOMEM; Index: linux-2.6/include/asm-powerpc/8253pit.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/8253pit.h 2005-10-31 15:02:18.000000000 +1100 +++ linux-2.6/include/asm-powerpc/8253pit.h 2005-10-31 15:20:30.000000000 +1100 @@ -5,6 +5,19 @@ * 8253/8254 Programmable Interval Timer */ +#include + #define PIT_TICK_RATE 1193182UL +#define HAS_PCSPKR_ARCH_INIT + +static inline int pcspkr_arch_init(void) +{ + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "pnpPNP,100"); + of_node_put(np); + return np ? 0 : -ENODEV; +} + #endif /* _ASM_POWERPC_8253PIT_H */ From paulus at samba.org Tue Nov 1 16:53:37 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 1 Nov 2005 16:53:37 +1100 Subject: Patches for 2.6.15 In-Reply-To: <20051028103041.B15268@cox.net> References: <17250.8725.358204.62510@cargo.ozlabs.ibm.com> <20051028103041.B15268@cox.net> Message-ID: <17255.737.832440.137041@cargo.ozlabs.ibm.com> Matt Porter writes: > Ok, we have a set of 4xx patches that I plan to send to Andrew. > They are some existing 4xx SoC/board updates as well as a new > SoC/board. They are obviously mostly confined to the 4xx code paths > but there's likely conflicts in changes to Makefiles, etc. > > Would you prefer these going upstream before or after the > powerpc-merge pull? Did you send them yet? Linus has pulled the powerpc-merge tree, as I'm sure you've noticed. Paul. From paulus at samba.org Tue Nov 1 16:46:29 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 1 Nov 2005 16:46:29 +1100 Subject: [PATCH] VMX get_user w/ irq disabled In-Reply-To: <20051028115509.1bb23cb6.moilanen@austin.ibm.com> References: <20051028115509.1bb23cb6.moilanen@austin.ibm.com> Message-ID: <17255.309.688169.531174@cargo.ozlabs.ibm.com> Jake Moilanen writes: > Looks like we have a get_user() call with interrupts disabled. While I > haven't seen the problem, I believe we have the same hole in mainline. > > The patch below fixed the problem on Redhat (rebased at 2.6.14). The problem is that altivec_assist_exception gets called with interrupts disabled on ppc64. I haven't decided whether to change head_64.S or just do a local_irq_enable() inside altivec_assist_exception(). Paul. From paulus at samba.org Tue Nov 1 16:57:58 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 1 Nov 2005 16:57:58 +1100 Subject: Patches for 2.6.15 In-Reply-To: References: <17250.8725.358204.62510@cargo.ozlabs.ibm.com> Message-ID: <17255.998.459385.399953@cargo.ozlabs.ibm.com> Kumar Gala writes: > Can you merge this in: > > http://patchwork.ozlabs.org/linuxppc/patch?id=2931 Having the same extern declaration in several C files raises a red flag. Could we have that in a suitable header file instead please? Paul. From paulus at samba.org Tue Nov 1 20:55:17 2005 From: paulus at samba.org (Paul Mackerras) Date: Tue, 1 Nov 2005 20:55:17 +1100 Subject: [patch 2/5] powerpc: create a new arch/powerpc/platforms/cell/smp.c In-Reply-To: <200511010050.48828.arnd@arndb.de> References: <20051101010836.771791000@localhost> <20051101011133.300238000@localhost> <200511011026.59266.michael@ellerman.id.au> <200511010050.48828.arnd@arndb.de> Message-ID: <17255.15237.695554.410362@cargo.ozlabs.ibm.com> Arnd Bergmann writes: > On Dinsdag 01 November 2005 00:26, Michael Ellerman wrote: > > A lot of your smp routines are identical to the pSeries versions. Wouldn't it > > be preferable to only have one implementation? > > Yes it would. I'm not sure how that would best be done however. Until 2.6.14, > we've just used the pSeries implementation, which does not work any more now > that we want to keep the platform stuff in separate directories. I don't mind putting generic rtas stuff in arch/powerpc/kernel. Paul. From mporter at kernel.crashing.org Wed Nov 2 00:22:50 2005 From: mporter at kernel.crashing.org (Matt Porter) Date: Tue, 1 Nov 2005 06:22:50 -0700 Subject: Patches for 2.6.15 In-Reply-To: <17255.737.832440.137041@cargo.ozlabs.ibm.com>; from paulus@samba.org on Tue, Nov 01, 2005 at 04:53:37PM +1100 References: <17250.8725.358204.62510@cargo.ozlabs.ibm.com> <20051028103041.B15268@cox.net> <17255.737.832440.137041@cargo.ozlabs.ibm.com> Message-ID: <20051101062250.A28639@cox.net> On Tue, Nov 01, 2005 at 04:53:37PM +1100, Paul Mackerras wrote: > Matt Porter writes: > > > Ok, we have a set of 4xx patches that I plan to send to Andrew. > > They are some existing 4xx SoC/board updates as well as a new > > SoC/board. They are obviously mostly confined to the 4xx code paths > > but there's likely conflicts in changes to Makefiles, etc. > > > > Would you prefer these going upstream before or after the > > powerpc-merge pull? > > Did you send them yet? Linus has pulled the powerpc-merge tree, as > I'm sure you've noticed. Yes I did. I saw the merge go into mainline and rebased what was necessary off of that. Andrew now has them queued up for Linus so we are set. BTW, we're starting to look at merging 4xx to arch/powerpc/ now. -Matt From dwmw2 at infradead.org Wed Nov 2 02:54:04 2005 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 01 Nov 2005 15:54:04 +0000 Subject: please pull the powerpc-merge.git tree In-Reply-To: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> References: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> Message-ID: <1130860444.21212.52.camel@hades.cambridge.redhat.com> On Mon, 2005-10-31 at 15:23 +1100, Paul Mackerras wrote: > It is now possible to build kernels for powermac, pSeries, iSeries and > maple with ARCH=powerpc, and for powermac, both 32-bit and 64-bit > build and run. Hm. Not entirely in line with my experience. Can you share the configs you used? Using http://david/woodhou.se/powerpc-merge-32.config it doesn't actually boot on my powerbook. I'll try it on the Pegasos later or tomorrow, where I have a serial console; it dies very early. Aside from disabling CONFIG_NVRAM because call_rtas() isn't implemented anywhere, I also needed to do this to make that config build: --- linux-2.6.14/arch/powerpc/kernel/setup-common.c.orig 2005-11-01 10:14:32.000000000 +0000 +++ linux-2.6.14/arch/powerpc/kernel/setup-common.c 2005-11-01 10:15:03.000000000 +0000 @@ -203,11 +203,11 @@ static int show_cpuinfo(struct seq_file #ifdef CONFIG_TAU_AVERAGE /* more straightforward, but potentially misleading */ seq_printf(m, "temperature \t: %u C (uncalibrated)\n", - cpu_temp(i)); + cpu_temp(cpu_id)); #else /* show the actual temp sensor range */ u32 temp; - temp = cpu_temp_both(i); + temp = cpu_temp_both(cpu_id); seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n", temp & 0xff, temp >> 16); #endif -- dwmw2 From dwmw2 at infradead.org Wed Nov 2 03:06:47 2005 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 01 Nov 2005 16:06:47 +0000 Subject: please pull the powerpc-merge.git tree In-Reply-To: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> References: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> Message-ID: <1130861207.21212.66.camel@hades.cambridge.redhat.com> On Mon, 2005-10-31 at 15:23 +1100, Paul Mackerras wrote: > It is now possible to build kernels for powermac, pSeries, iSeries and > maple with ARCH=powerpc, and for powermac, both 32-bit and 64-bit > build and run. The ppc64 build (http://david.woodhou.se/powerpc-merge-64.config) fares worse than ppc32 for me -- it doesn't even build. arch/powerpc/platforms/powermac/pic.c:614: error: ?ppc_cached_irq_mask? undeclared (first use in this function) arch/powerpc/platforms/powermac/pic.c:620: error: ?pmac_irq_hw? undeclared (first use in this function) arch/powerpc/platforms/powermac/pic.c:621: error: ?max_real_irqs? undeclared (first use in this function) arch/powerpc/platforms/powermac/pic.c:641: warning: implicit declaration of function ?pmac_unmask_irq? If I leave CONFIG_ADB_PMU enabled (as I think I should since some G5s have it?) I also see this: drivers/macintosh/via-pmu.c:2410: undefined reference to `.pmac_tweak_clock_spreading' drivers/macintosh/via-pmu.c:2494: undefined reference to `.set_context' drivers/macintosh/via-pmu.c:2670: undefined reference to `._nmask_and_or_msr' drivers/macintosh/via-pmu.c:2592: undefined reference to `.set_context' If I turn CONFIG_ADB_PMU off, I see this: arch/powerpc/platforms/powermac/time.c:335: undefined reference to `.pmu_register_sleep_notifier' I think I'll leave the task of switching the Fedora rawhide kernel to arch/powerpc to another day :) -- dwmw2 From miltonm at bga.com Wed Nov 2 02:02:08 2005 From: miltonm at bga.com (Milton Miller) Date: Tue, 1 Nov 2005 09:02:08 -0600 Subject: Patches for 2.6.15 Message-ID: Paul wrote: > Kumar Gala writes: > > http://patchwork.ozlabs.org/linuxppc/patch?id=2931 > > Having the same extern declaration in several C files raises a red > flag. Could we have that in a suitable header file instead please? And the patch header says: > Having a prototype that uses seq_file without always including > seq_file.h generates a lot of warnings. This happened when asm/irq.h > was merged. Hint: a simple struct seq_file; in the approprate header should suffice. milton From arnd at arndb.de Wed Nov 2 06:13:50 2005 From: arnd at arndb.de (Arnd Bergmann) Date: Tue, 1 Nov 2005 20:13:50 +0100 Subject: powerpc: Merge ipcbuf.h In-Reply-To: <20051101055324.GA3551@localhost.localdomain> References: <20051101055324.GA3551@localhost.localdomain> Message-ID: <200511012013.51443.arnd@arndb.de> On Dinsdag 01 November 2005 06:53, David Gibson wrote: > +struct ipc64_perm > +{ > +???????__kernel_key_t??key; > +???????__kernel_uid_t??uid; > +???????__kernel_gid_t??gid; > +???????__kernel_uid_t??cuid; > +???????__kernel_gid_t??cgid; > +???????__kernel_mode_t?mode; > +???????unsigned int????seq; > +???????unsigned int????__pad1; > +???????u64?????????????__unused1; > +???????u64?????????????__unused2; > +}; ipc64_perm is a user visible structure, so you have to use __u64 here instead of u64. Even that does not exists if you build with 32 bit and __STRICT_ANSI__, so it might be better yet to use four __u32 for the unused fields. Arnd <>< From ingvar at linpro.no Wed Nov 2 09:49:26 2005 From: ingvar at linpro.no (Ingvar Hagelund) Date: 01 Nov 2005 23:49:26 +0100 Subject: dlpar problem on sles9/openpower Message-ID: This is a pure user question We have an IBM OpenPower 720 with hypervisor and a set of lpars. Earlier we got dlpar to work, at least a couple of times, but not anymore. Here's an example: Ran this on the hmc: ~> chhwres -r virtualio -m Server-9124-720-SNXXXXXXX -p mgmt -o a \ --rsubtype eth -s 11 \ -a "ieee_virtual_eth=1,port_vlan_id=1,is_trunk=1,\"addl_vlan_ids=600,601\"" HSCL294C DLPAR ADD Virtual I/O resources failed: HMC adding Virtual I/O ...... HMC Virtual slot DLPAR operation failed. Here are the virtual slot IDs that failed and the reasons for failure: 11 The dynamic logical partitioning operation failed. On the lpar "mgmt", running sles9 sp2 kernel 2.6.5-7.193-pseries64, we have the magic rpms from IBM installed: evlog-drv-tmpl-0.8-1 diagela-1.3.0.0-6 lsvpd-0.12.7-1 ppc64-utils-2.5-2 librtas-1.2-1 ... and the following IBM services are running: # lssrc -a Subsystem Group PID Status ctrmc rsct 5011 active IBM.ServiceRM rsct_rm 5103 active IBM.DRM rsct_rm 5110 active IBM.HostRM rsct_rm 5186 active IBM.CSMAgentRM rsct_rm 5217 active IBM.ERRM rsct_rm 5221 active IBM.AuditRM rsct_rm 5266 active ctcas rsct 7705 active IBM.SensorRM rsct_rm 7721 active IBM.FSRM rsct_rm 7722 active IBM.ConfigRM rsct_rm 7723 active The hmc seems to be able to talk to the managed system ~> lshwres -r virtualio --rsubtype eth -m Server-9124-720-SNXXXXXXX \ --level lpar --filter "lpar_names=mgmt" lpar_name=mgmt,lpar_id=1,slot_num=10,state=null,ieee_virtual_eth=1,port_vlan_id=1,"addl_vlan_ids=500,501,502,503",is_trunk=1,is_required=0,mac_addr=AE808000100A ... and to the lpar: ~> lspartition -dlpar <#0> Partition:<1, power0.somewhere.tld, 10.0.0.2> Active:<1>, OS:, DCaps:<0xf>, CmdCaps:<0x1, 0x1>, PinnedMem:<0> So, where can I start digging? Regards, Ingvar -- Many that live deserve death. And some that die deserve life. Can you give it to them? Then do not be too eager to deal out death in judgement. For even the very wise cannot see all ends. Gandalf From tdgarcia at us.ibm.com Wed Nov 2 09:51:24 2005 From: tdgarcia at us.ibm.com (tdgarcia) Date: Tue, 01 Nov 2005 16:51:24 -0600 Subject: lockmeter port for ppc64 Message-ID: <4367F16C.5080003@us.ibm.com> My team and I adapted your lockmeter code to the ppc64 architecture. I am attaching the ppc64 specific code to this email. This code should patch cleanly to the 2.6.13 kernel. diff -Narup linux-2.6.13/arch/ppc64/Kconfig.debug linux-2.6.13-lockmeter/arch/ppc64/Kconfig.debug --- linux-2.6.13/arch/ppc64/Kconfig.debug 2005-08-28 16:41:01.000000000 -0700 +++ linux-2.6.13-lockmeter/arch/ppc64/Kconfig.debug 2005-10-11 07:40:28.000000000 -0700 @@ -19,6 +19,13 @@ config KPROBES for kernel debugging, non-intrusive instrumentation and testing. If in doubt, say "N". +config LOCKMETER + bool "Kernel lock metering" + depends on SMP && !PREEMPT + help + Say Y to enable kernel lock metering, which adds overhead to SMP locks, + but allows you to see various statistics using the lockstat command. + config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" depends on DEBUG_KERNEL diff -Narup linux-2.6.13/arch/ppc64/lib/dec_and_lock.c linux-2.6.13-lockmeter/arch/ppc64/lib/dec_and_lock.c --- linux-2.6.13/arch/ppc64/lib/dec_and_lock.c 2005-08-28 16:41:01.000000000 -0700 +++ linux-2.6.13-lockmeter/arch/ppc64/lib/dec_and_lock.c 2005-10-10 13:02:47.000000000 -0700 @@ -28,7 +28,13 @@ */ #ifndef ATOMIC_DEC_AND_LOCK + +#ifndef CONFIG_LOCKMETER +int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +#else int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +#endif /* CONFIG_LOCKMETER */ + { int counter; int newcount; @@ -51,5 +57,10 @@ int _atomic_dec_and_lock(atomic_t *atomi return 0; } +#ifndef CONFIG_LOCKMETER +EXPORT_SYMBOL(atomic_dec_and_lock); +#else EXPORT_SYMBOL(_atomic_dec_and_lock); +#endif /* CONFIG_LOCKMETER */ + #endif /* ATOMIC_DEC_AND_LOCK */ diff -Narup linux-2.6.13/include/asm-ppc64/lockmeter.h linux-2.6.13-lockmeter/include/asm-ppc64/lockmeter.h --- linux-2.6.13/include/asm-ppc64/lockmeter.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.13-lockmeter/include/asm-ppc64/lockmeter.h 2005-10-11 08:48:48.000000000 -0700 @@ -0,0 +1,110 @@ +/* + * Copyright (C) 1999,2000 Silicon Graphics, Inc. + * + * Written by John Hawkes (hawkes at sgi.com) + * Based on klstat.h by Jack Steiner (steiner at sgi.com) + * + * Modified by Ray Bryant (raybry at us.ibm.com) + * Changes Copyright (C) 2000 IBM, Inc. + * Added save of index in spinlock_t to improve efficiency + * of "hold" time reporting for spinlocks. + * Added support for hold time statistics for read and write + * locks. + * Moved machine dependent code here from include/lockmeter.h. + * + * Modified by Tony Garcia (garcia1 at us.ibm.com) + * Ported to Power PC 64 + */ + +#ifndef _PPC64_LOCKMETER_H +#define _PPC64_LOCKMETER_H + + +#include +#include +#include + +#include /* definitions for SPRN_TBRL + SPRN_TBRU, mftb() */ +extern unsigned long ppc_proc_freq; + +#define CPU_CYCLE_FREQUENCY ppc_proc_freq + +#define THIS_CPU_NUMBER smp_processor_id() + +/* + * macros to cache and retrieve an index value inside of a spin lock + * these macros assume that there are less than 65536 simultaneous + * (read mode) holders of a rwlock. Not normally a problem!! + * we also assume that the hash table has less than 65535 entries. + */ +/* + * instrumented spinlock structure -- never used to allocate storage + * only used in macros below to overlay a spinlock_t + */ +typedef struct inst_spinlock_s { + volatile unsigned int lock; + unsigned int index; +} inst_spinlock_t; + +#define PUT_INDEX(lock_ptr,indexv) ((inst_spinlock_t *)(lock_ptr))->index = indexv +#define GET_INDEX(lock_ptr) ((inst_spinlock_t *)(lock_ptr))->index + +/* + * macros to cache and retrieve an index value in a read/write lock + * as well as the cpu where a reader busy period started + * we use the 2nd word (the debug word) for this, so require the + * debug word to be present + */ +/* + * instrumented rwlock structure -- never used to allocate storage + * only used in macros below to overlay a rwlock_t + */ +typedef struct inst_rwlock_s { + volatile signed int lock; + unsigned int index; + unsigned int cpu; +} inst_rwlock_t; + +#define PUT_RWINDEX(rwlock_ptr,indexv) ((inst_rwlock_t *)(rwlock_ptr))->index = indexv +#define GET_RWINDEX(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->index +#define PUT_RW_CPU(rwlock_ptr,cpuv) ((inst_rwlock_t *)(rwlock_ptr))->cpu = cpuv +#define GET_RW_CPU(rwlock_ptr) ((inst_rwlock_t *)(rwlock_ptr))->cpu + +/* + * return the number of readers for a rwlock_t + */ +#define RWLOCK_READERS(rwlock_ptr) rwlock_readers(rwlock_ptr) + +/* Return number of readers */ +extern inline int rwlock_readers(rwlock_t *rwlock_ptr) +{ + signed int tmp = rwlock_ptr->lock; + + if ( tmp > 0 ) + return tmp; + else + return 0; +} + +/* + * return true if rwlock is write locked + * (note that other lock attempts can cause the lock value to be negative) + */ +#define RWLOCK_IS_WRITE_LOCKED(rwlock_ptr) ((signed int)(rwlock_ptr)->lock < 0) +#define RWLOCK_IS_READ_LOCKED(rwlock_ptr) ((signed int)(rwlock_ptr)->lock > 0 ) + +/*Written by Carl L. to get the time base counters on ppc, + rplaces the Intel only call rtds*/ +static inline long get_cycles64 (void) +{ + unsigned long tb; + + /* read the upper and lower 32 bit Time base counter */ + tb = mfspr(SPRN_TBRU); + tb = (tb << 32) | mfspr(SPRN_TBRL); + + return(tb); +} + +#endif /* _PPC64_LOCKMETER_H */ diff -Narup linux-2.6.13/include/asm-ppc64/spinlock.h linux-2.6.13-lockmeter/include/asm-ppc64/spinlock.h --- linux-2.6.13/include/asm-ppc64/spinlock.h 2005-08-28 16:41:01.000000000 -0700 +++ linux-2.6.13-lockmeter/include/asm-ppc64/spinlock.h 2005-10-10 14:04:25.000000000 -0700 @@ -23,6 +23,9 @@ typedef struct { volatile unsigned int lock; +#ifdef CONFIG_LOCKMETER + unsigned int lockmeter_magic; +#endif /* CONFIG_LOCKMETER */ #ifdef CONFIG_PREEMPT unsigned int break_lock; #endif @@ -30,13 +33,20 @@ typedef struct { typedef struct { volatile signed int lock; +#ifdef CONFIG_LOCKMETER + unsigned int index; + unsigned int cpu; +#endif /* CONFIG_LOCKMETER */ #ifdef CONFIG_PREEMPT unsigned int break_lock; #endif } rwlock_t; -#ifdef __KERNEL__ -#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } +#ifdef CONFIG_LOCKMETER + #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } +#else + #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 , 0} +#endif /* CONFIG_LOCKMETER */ #define spin_is_locked(x) ((x)->lock != 0) #define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0) @@ -144,7 +154,7 @@ static void __inline__ _raw_spin_lock_fl * irq-safe write-lock, but readers can get non-irqsafe * read-locks. */ -#define RW_LOCK_UNLOCKED (rwlock_t) { 0 } +#define RW_LOCK_UNLOCKED (rwlock_t) { 0 , 0 , 0 } #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) @@ -157,6 +167,44 @@ static __inline__ void _raw_write_unlock rw->lock = 0; } +#if defined(CONFIG_LOCKMETER) && defined(CONFIG_HAVE_DEC_LOCK) +extern void _metered_spin_lock (spinlock_t *lock, void *caller_pc); +extern void _metered_spin_unlock(spinlock_t *lock); + +/* + * Matches what is in arch/ppc64/lib/dec_and_lock.c, except this one is + * "static inline" so that the spin_lock(), if actually invoked, is charged + * against the real caller, not against the catch-all atomic_dec_and_lock + */ +static inline int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +{ + int counter; + int newcount; + + for (;;) { + counter = atomic_read(atomic); + newcount = counter - 1; + if (!newcount) + break; /* do it the slow way */ + + newcount = cmpxchg(&atomic->counter, counter, newcount); + if (newcount == counter) + return 0; + } + + preempt_disable(); + _metered_spin_lock(lock, __builtin_return_address(0)); + if (atomic_dec_and_test(atomic)) + return 1; + _metered_spin_unlock(lock); + preempt_enable(); + + return 0; +} + +#define ATOMIC_DEC_AND_LOCK +#endif /* CONFIG_LOCKMETER and CONFIG_HAVE_DEC_LOCK */ + /* * This returns the old value in the lock + 1, * so we got a read lock if the return value is > 0. @@ -256,5 +304,4 @@ static void __inline__ _raw_write_lock(r } } -#endif /* __KERNEL__ */ #endif /* __ASM_SPINLOCK_H */ From hien at us.ibm.com Wed Nov 2 11:14:42 2005 From: hien at us.ibm.com (Hien Nguyen) Date: Tue, 01 Nov 2005 16:14:42 -0800 Subject: [PATCH] exporting validate_sp Message-ID: <1130890483.4032.20.camel@dyn9047022138.beaverton.ibm.com> This patch will export the validate_sp() function (part of dump_stack code). I am developers for the systemtap project: http://sourceware.org/systemtap/ The SystemTap runtime includes a function for capturing a stack trace as a string. For the ppc64 port, we need to have the validate_sp() function exported so it is accessible to our stack-trace function, which is part of a SystemTap-generated kernel module. This patch should apply to kernel 2.6.14-rc5-mm1. Thanks, Hien. Signed-off-by: Hien Nguyen --- linux-2.6.14-rc5.org/arch/ppc64/kernel/process.c 2005-10-19 23:23:05.000000000 -0700 +++ linux-2.6.14-rc5/arch/ppc64/kernel/process.c 2005-11-01 12:54:23.000000000 -0800 @@ -626,6 +626,7 @@ return 0; } +EXPORT_SYMBOL_GPL(validate_sp); unsigned long get_wchan(struct task_struct *p) { From david at gibson.dropbear.id.au Wed Nov 2 11:06:44 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Wed, 2 Nov 2005 11:06:44 +1100 Subject: please pull the powerpc-merge.git tree In-Reply-To: <1130860444.21212.52.camel@hades.cambridge.redhat.com> References: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> <1130860444.21212.52.camel@hades.cambridge.redhat.com> Message-ID: <20051102000644.GB8308@localhost.localdomain> On Tue, Nov 01, 2005 at 03:54:04PM +0000, David Woodhouse wrote: > On Mon, 2005-10-31 at 15:23 +1100, Paul Mackerras wrote: > > It is now possible to build kernels for powermac, pSeries, iSeries and > > maple with ARCH=powerpc, and for powermac, both 32-bit and 64-bit > > build and run. > > Hm. Not entirely in line with my experience. Can you share the configs > you used? I gather paulus doesn't believe in CONFIG_TAU. > Using http://david/woodhou.se/powerpc-merge-32.config it doesn't > actually boot on my powerbook. I'll try it on the Pegasos later or > tomorrow, where I have a serial console; it dies very early. > > Aside from disabling CONFIG_NVRAM because call_rtas() isn't implemented > anywhere, I also needed to do this to make that config build: > > --- linux-2.6.14/arch/powerpc/kernel/setup-common.c.orig 2005-11-01 10:14:32.000000000 +0000 > +++ linux-2.6.14/arch/powerpc/kernel/setup-common.c 2005-11-01 10:15:03.000000000 +0000 > @@ -203,11 +203,11 @@ static int show_cpuinfo(struct seq_file > #ifdef CONFIG_TAU_AVERAGE > /* more straightforward, but potentially misleading */ > seq_printf(m, "temperature \t: %u C (uncalibrated)\n", > - cpu_temp(i)); > + cpu_temp(cpu_id)); > #else > /* show the actual temp sensor range */ > u32 temp; > - temp = cpu_temp_both(i); > + temp = cpu_temp_both(cpu_id); > seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n", > temp & 0xff, temp >> 16); > #endif > > -- 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/people/dgibson From david at gibson.dropbear.id.au Wed Nov 2 11:44:26 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Wed, 2 Nov 2005 11:44:26 +1100 Subject: powerpc: Merge ipcbuf.h In-Reply-To: <200511012013.51443.arnd@arndb.de> References: <20051101055324.GA3551@localhost.localdomain> <200511012013.51443.arnd@arndb.de> Message-ID: <20051102004426.GC8308@localhost.localdomain> On Tue, Nov 01, 2005 at 08:13:50PM +0100, Arnd Bergmann wrote: > On Dinsdag 01 November 2005 06:53, David Gibson wrote: > > +struct ipc64_perm > > +{ > > +???????__kernel_key_t??key; > > +???????__kernel_uid_t??uid; > > +???????__kernel_gid_t??gid; > > +???????__kernel_uid_t??cuid; > > +???????__kernel_gid_t??cgid; > > +???????__kernel_mode_t?mode; > > +???????unsigned int????seq; > > +???????unsigned int????__pad1; > > +???????u64?????????????__unused1; > > +???????u64?????????????__unused2; > > +}; > > ipc64_perm is a user visible structure, so you have to use > __u64 here instead of u64. Even that does not exists if > you build with 32 bit and __STRICT_ANSI__, so it might > be better yet to use four __u32 for the unused fields. Oops. I realised it was user visible, but forgot the wrinkle that the 'uXX' names can't be used there. Here's a patch to correct it. Paulus, please apply. Oops, when merging ipcbuf.h, I forgot that 'u64' can't be used in user-visible headers. This patch corrects the problem, replacing the unused fields with an array of four __u32s. Signed-off-by: David Gibson Index: working-2.6/include/asm-powerpc/ipcbuf.h =================================================================== --- working-2.6.orig/include/asm-powerpc/ipcbuf.h 2005-11-02 10:41:06.000000000 +1100 +++ working-2.6/include/asm-powerpc/ipcbuf.h 2005-11-02 11:41:36.000000000 +1100 @@ -27,8 +27,7 @@ __kernel_mode_t mode; unsigned int seq; unsigned int __pad1; - u64 __unused1; - u64 __unused2; + __u32 __unused[4]; }; #endif /* _ASM_POWERPC_IPCBUF_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/people/dgibson From paulus at samba.org Wed Nov 2 12:03:26 2005 From: paulus at samba.org (Paul Mackerras) Date: Wed, 2 Nov 2005 12:03:26 +1100 Subject: please pull the powerpc-merge.git tree In-Reply-To: <1130860444.21212.52.camel@hades.cambridge.redhat.com> References: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> <1130860444.21212.52.camel@hades.cambridge.redhat.com> Message-ID: <17256.4190.184855.821331@cargo.ozlabs.ibm.com> David Woodhouse writes: > Hm. Not entirely in line with my experience. Can you share the configs > you used? Sure, attached (as a .tar.gz). For 32-bit pmac, you currently have to disable CONFIG_PREP and (I believe) the TAU options. For the 64-bit configs I basically just used the defconfigs in arch/ppc64/configs. > Using http://david/woodhou.se/powerpc-merge-32.config it doesn't > actually boot on my powerbook. I'll try it on the Pegasos later or > tomorrow, where I have a serial console; it dies very early. That's probably either the pci quirk that got added to do USB host controller handoff unconditionally on all platforms, and which touches the device without doing pci_enable_device or checking whether MMIO is enabled. A fix has gone into Linus' tree for that. There was also a bug added to the adbhid.c driver which would cause an oops when you pressed a key if you had an ADB keyboard (which powerbooks do). That's also fixed in Linus' tree. > Aside from disabling CONFIG_NVRAM because call_rtas() isn't implemented > anywhere, I also needed to do this to make that config build: > > --- linux-2.6.14/arch/powerpc/kernel/setup-common.c.orig 2005-11-01 10:14:32.000000000 +0000 > +++ linux-2.6.14/arch/powerpc/kernel/setup-common.c 2005-11-01 10:15:03.000000000 +0000 > @@ -203,11 +203,11 @@ static int show_cpuinfo(struct seq_file > #ifdef CONFIG_TAU_AVERAGE > /* more straightforward, but potentially misleading */ > seq_printf(m, "temperature \t: %u C (uncalibrated)\n", > - cpu_temp(i)); > + cpu_temp(cpu_id)); > #else > /* show the actual temp sensor range */ > u32 temp; > - temp = cpu_temp_both(i); > + temp = cpu_temp_both(cpu_id); > seq_printf(m, "temperature \t: %u-%u C (uncalibrated)\n", > temp & 0xff, temp >> 16); > #endif Thanks, I'll put that in. Paul. From paulus at samba.org Wed Nov 2 12:04:07 2005 From: paulus at samba.org (Paul Mackerras) Date: Wed, 2 Nov 2005 12:04:07 +1100 Subject: please pull the powerpc-merge.git tree In-Reply-To: <1130860444.21212.52.camel@hades.cambridge.redhat.com> References: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> <1130860444.21212.52.camel@hades.cambridge.redhat.com> Message-ID: <17256.4231.124394.723713@cargo.ozlabs.ibm.com> David Woodhouse writes: > Hm. Not entirely in line with my experience. Can you share the configs > you used? Forgot to attach the configs on my previous reply. Paul. -------------- next part -------------- A non-text attachment was scrubbed... Name: configs.tar.gz Type: application/octet-stream Size: 19644 bytes Desc: config tarball Url : http://ozlabs.org/pipermail/linuxppc64-dev/attachments/20051102/55f01850/attachment.obj From david at gibson.dropbear.id.au Wed Nov 2 13:58:22 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Wed, 2 Nov 2005 13:58:22 +1100 Subject: powerpc: Merge futex.h Message-ID: <20051102025822.GB10682@localhost.localdomain> This patch merges the ppc32 and ppc64 versions of futex.h, essentially by taking the ppc64 version as the powerpc version. The old ppc32 version did not implement the futex_atomic_op_inuser() callback (it always returned -ENOSYS), so FUTEX_WAKE_OP would not work on ppc32. In fact the ppc64 version of this function is almost suitable for ppc32 as well - the only change needed is to extend ppc_asm.h with a macro expanding to to the right pseudo-op to store a pointer (either ".long" or ".llong"). Built and booted on pSeries. Built for 32-bit powermac. Signed-off-by: David Gibson Index: working-2.6/include/asm-powerpc/futex.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ working-2.6/include/asm-powerpc/futex.h 2005-11-02 13:43:08.000000000 +1100 @@ -0,0 +1,84 @@ +#ifndef _ASM_POWERPC_FUTEX_H +#define _ASM_POWERPC_FUTEX_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile ( \ + SYNC_ON_SMP \ +"1: lwarx %0,0,%2\n" \ + insn \ +"2: stwcx. %1,0,%2\n" \ + "bne- 1b\n" \ + "li %1,0\n" \ +"3: .section .fixup,\"ax\"\n" \ +"4: li %1,%3\n" \ + "b 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + ".align 3\n" \ + DATAL " 1b,4b,2b,4b\n" \ + ".previous" \ + : "=&r" (oldval), "=&r" (ret) \ + : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ + : "cr0", "memory") + +static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + inc_preempt_count(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + dec_preempt_count(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; + } + } + return ret; +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_FUTEX_H */ Index: working-2.6/include/asm-ppc/futex.h =================================================================== --- working-2.6.orig/include/asm-ppc/futex.h 2005-10-25 11:59:59.000000000 +1000 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#ifdef __KERNEL__ - -#include -#include -#include - -static inline int -futex_atomic_op_inuser (int encoded_op, int __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret; - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - case FUTEX_OP_ADD: - case FUTEX_OP_OR: - case FUTEX_OP_ANDN: - case FUTEX_OP_XOR: - default: - ret = -ENOSYS; - } - - dec_preempt_count(); - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -#endif -#endif Index: working-2.6/include/asm-ppc64/futex.h =================================================================== --- working-2.6.orig/include/asm-ppc64/futex.h 2005-10-31 15:20:22.000000000 +1100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#ifdef __KERNEL__ - -#include -#include -#include -#include - -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ - __asm__ __volatile (SYNC_ON_SMP \ -"1: lwarx %0,0,%2\n" \ - insn \ -"2: stwcx. %1,0,%2\n\ - bne- 1b\n\ - li %1,0\n\ -3: .section .fixup,\"ax\"\n\ -4: li %1,%3\n\ - b 3b\n\ - .previous\n\ - .section __ex_table,\"a\"\n\ - .align 3\n\ - .llong 1b,4b,2b,4b\n\ - .previous" \ - : "=&r" (oldval), "=&r" (ret) \ - : "b" (uaddr), "i" (-EFAULT), "1" (oparg) \ - : "cr0", "memory") - -static inline int -futex_atomic_op_inuser (int encoded_op, int __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret; - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - __futex_atomic_op("", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_ADD: - __futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_OR: - __futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_ANDN: - __futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - case FUTEX_OP_XOR: - __futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg); - break; - default: - ret = -ENOSYS; - } - - dec_preempt_count(); - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -#endif -#endif Index: working-2.6/include/asm-powerpc/ppc_asm.h =================================================================== --- working-2.6.orig/include/asm-powerpc/ppc_asm.h 2005-10-31 15:20:57.000000000 +1100 +++ working-2.6/include/asm-powerpc/ppc_asm.h 2005-11-02 13:48:08.000000000 +1100 @@ -506,6 +506,13 @@ #else #define __ASM_CONST(x) x##UL #define ASM_CONST(x) __ASM_CONST(x) + +#ifdef CONFIG_PPC64 +#define DATAL ".llong" +#else +#define DATAL ".long" +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_PPC_ASM_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/people/dgibson From david at gibson.dropbear.id.au Wed Nov 2 15:13:20 2005 From: david at gibson.dropbear.id.au (David Gibson) Date: Wed, 2 Nov 2005 15:13:20 +1100 Subject: powerpc: Move dart.h Message-ID: <20051102041320.GA15666@localhost.localdomain> asm-ppc64/dart.h is included in exactly one place - arch/powerpc/sysdev/u3_iommu.c. This patch, therefore, moves it into arch/powerpc/sysdev. While we're at it, update the #ifndef/#define protecting the include, and the filename in the comments of u3_iommu.c. Built and booted on pSeries and G5, built for ppc32 powermac. Signed-off-by: David Gibson Index: working-2.6/arch/powerpc/sysdev/dart.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ working-2.6/arch/powerpc/sysdev/dart.h 2005-11-02 14:53:28.000000000 +1100 @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * 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 + */ + +#ifndef _POWERPC_SYSDEV_DART_H +#define _POWERPC_SYSDEV_DART_H + + +/* physical base of DART registers */ +#define DART_BASE 0xf8033000UL + +/* Offset from base to control register */ +#define DARTCNTL 0 +/* Offset from base to exception register */ +#define DARTEXCP 0x10 +/* Offset from base to TLB tag registers */ +#define DARTTAG 0x1000 + + +/* Control Register fields */ + +/* base address of table (pfn) */ +#define DARTCNTL_BASE_MASK 0xfffff +#define DARTCNTL_BASE_SHIFT 12 + +#define DARTCNTL_FLUSHTLB 0x400 +#define DARTCNTL_ENABLE 0x200 + +/* size of table in pages */ +#define DARTCNTL_SIZE_MASK 0x1ff +#define DARTCNTL_SIZE_SHIFT 0 + + +/* DART table fields */ + +#define DARTMAP_VALID 0x80000000 +#define DARTMAP_RPNMASK 0x00ffffff + + +#define DART_PAGE_SHIFT 12 +#define DART_PAGE_SIZE (1 << DART_PAGE_SHIFT) +#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_PAGE_SHIFT) + + +#endif /* _POWERPC_SYSDEV_DART_H */ Index: working-2.6/include/asm-ppc64/dart.h =================================================================== --- working-2.6.orig/include/asm-ppc64/dart.h 2005-10-31 15:20:22.000000000 +1100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2004 Olof Johansson , IBM Corporation - * - * 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 - */ - -#ifndef _ASM_DART_H -#define _ASM_DART_H - - -/* physical base of DART registers */ -#define DART_BASE 0xf8033000UL - -/* Offset from base to control register */ -#define DARTCNTL 0 -/* Offset from base to exception register */ -#define DARTEXCP 0x10 -/* Offset from base to TLB tag registers */ -#define DARTTAG 0x1000 - - -/* Control Register fields */ - -/* base address of table (pfn) */ -#define DARTCNTL_BASE_MASK 0xfffff -#define DARTCNTL_BASE_SHIFT 12 - -#define DARTCNTL_FLUSHTLB 0x400 -#define DARTCNTL_ENABLE 0x200 - -/* size of table in pages */ -#define DARTCNTL_SIZE_MASK 0x1ff -#define DARTCNTL_SIZE_SHIFT 0 - - -/* DART table fields */ - -#define DARTMAP_VALID 0x80000000 -#define DARTMAP_RPNMASK 0x00ffffff - - -#define DART_PAGE_SHIFT 12 -#define DART_PAGE_SIZE (1 << DART_PAGE_SHIFT) -#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_PAGE_SHIFT) - - -#endif Index: working-2.6/arch/powerpc/sysdev/u3_iommu.c =================================================================== --- working-2.6.orig/arch/powerpc/sysdev/u3_iommu.c 2005-10-31 15:20:20.000000000 +1100 +++ working-2.6/arch/powerpc/sysdev/u3_iommu.c 2005-11-02 14:54:16.000000000 +1100 @@ -1,5 +1,5 @@ /* - * arch/ppc64/kernel/u3_iommu.c + * arch/powerpc/sysdev/u3_iommu.c * * Copyright (C) 2004 Olof Johansson , IBM Corporation * @@ -44,9 +44,10 @@ #include #include #include -#include #include +#include "dart.h" + extern int iommu_force_on; /* Physical base address and size of the DART table */ -- 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/people/dgibson From paulus at samba.org Wed Nov 2 15:43:44 2005 From: paulus at samba.org (Paul Mackerras) Date: Wed, 2 Nov 2005 15:43:44 +1100 Subject: please pull the powerpc-merge.git tree In-Reply-To: <1130861207.21212.66.camel@hades.cambridge.redhat.com> References: <17253.39993.502458.390760@cargo.ozlabs.ibm.com> <1130861207.21212.66.camel@hades.cambridge.redhat.com> Message-ID: <17256.17408.247708.622755@cargo.ozlabs.ibm.com> David Woodhouse writes: > The ppc64 build (http://david.woodhou.se/powerpc-merge-64.config) fares > worse than ppc32 for me -- it doesn't even build. Those errors were all due to getting powerbook sleep code included because you have CONFIG_PM=y. I have changed things so that that code doesn't get included on a 64-bit build (at least until BenH gets sleep going on the G5 :). I also pulled in Linus' tree, and now drivers/char/tlclk.c fails to build for some reason. I claim that's not my fault, however. :) Paul. From michael at ellerman.id.au Wed Nov 2 18:23:33 2005 From: michael at ellerman.id.au (Michael Ellerman) Date: Wed, 2 Nov 2005 18:23:33 +1100 (EST) Subject: [PATCH] powerpc: Fix random memory corruption in merged elf.h Message-ID: <20051102072333.B91D568664@ozlabs.org> The merged verison of ELF_CORE_COPY_REGS is basically the PPC64 version, with a memset that came from PPC and a few types abstracted out into #defines. But it's not _quite_ right. The first problem is we calculate the number of registers with: nregs = sizeof(struct pt_regs) / sizeof(ELF_GREG_TYPE) For a 32-bit process on a 64-bit kernel that's bogus because the registers are 64 bits, but ELF_GREG_TYPE is u32, so nregs == 88 which is wrong. The other problem is the memset, which assumes a struct pt_regs is smaller than a struct elf_regs. For a 32-bit process on a 64-bit kernel that's false. The fix is to calculate the number of regs using sizeof(unsigned long), which should always be right, and just memset the whole damn thing _before_ copying the registers in. Signed-off-by: Michael Ellerman --- include/asm-powerpc/elf.h | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-) Index: kexec/includ