* [PATCH 1/7] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
From: Akinobu Mita @ 2009-10-28 8:43 UTC (permalink / raw)
To: linux-kernel, akpm
Cc: linux-usb, linux-ia64, linuxppc-dev, Paul Mackerras,
H. Peter Anvin, sparclinux, Lothar Wassmann, x86, linux-altix,
Ingo Molnar, Fenghua Yu, Joerg Roedel, Akinobu Mita,
Yevgeny Petrilin, Thomas Gleixner, Tony Luck, netdev,
Greg Kroah-Hartman, FUJITA Tomonori, David S. Miller
This introduces new bitmap functions:
bitmap_set: Set specified bit area
bitmap_clear: Clear specified bit area
bitmap_find_next_zero_area: Find free bit area
These are mostly stolen from iommu helper. The differences are:
- Use find_next_bit instead of doing test_bit for each bit
- Rewrite bitmap_set and bitmap_clear
Instead of setting or clearing for each bit.
- Check the last bit of the limit
iommu-helper doesn't want to find such area
- The return value if there is no zero area
find_next_zero_area in iommu helper: returns -1
bitmap_find_next_zero_area: return >= bitmap size
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@ozlabs.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Lothar Wassmann <LW@KARO-electronics.de>
Cc: linux-usb@vger.kernel.org
Cc: Roland Dreier <rolandd@cisco.com>
Cc: Yevgeny Petrilin <yevgenyp@mellanox.co.il>
Cc: netdev@vger.kernel.org
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: linux-ia64@vger.kernel.org
Cc: linux-altix@sgi.com
Cc: Joerg Roedel <joerg.roedel@amd.com>
---
include/linux/bitmap.h | 11 ++++++
lib/bitmap.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 0 deletions(-)
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 756d78b..daf8c48 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -42,6 +42,9 @@
* bitmap_empty(src, nbits) Are all bits zero in *src?
* bitmap_full(src, nbits) Are all bits set in *src?
* bitmap_weight(src, nbits) Hamming Weight: number set bits
+ * bitmap_set(dst, pos, nbits) Set specified bit area
+ * bitmap_clear(dst, pos, nbits) Clear specified bit area
+ * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
* bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
* bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
* bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
@@ -108,6 +111,14 @@ extern int __bitmap_subset(const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern int __bitmap_weight(const unsigned long *bitmap, int bits);
+extern void bitmap_set(unsigned long *map, int i, int len);
+extern void bitmap_clear(unsigned long *map, int start, int nr);
+extern unsigned long bitmap_find_next_zero_area(unsigned long *map,
+ unsigned long size,
+ unsigned long start,
+ unsigned int nr,
+ unsigned long align_mask);
+
extern int bitmap_scnprintf(char *buf, unsigned int len,
const unsigned long *src, int nbits);
extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 7025658..11bf497 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -271,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
}
EXPORT_SYMBOL(__bitmap_weight);
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
+
+void bitmap_set(unsigned long *map, int start, int nr)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const int size = start + nr;
+ int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+ while (nr - bits_to_set >= 0) {
+ *p |= mask_to_set;
+ nr -= bits_to_set;
+ bits_to_set = BITS_PER_LONG;
+ mask_to_set = ~0UL;
+ p++;
+ }
+ if (nr) {
+ mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+ *p |= mask_to_set;
+ }
+}
+EXPORT_SYMBOL(bitmap_set);
+
+void bitmap_clear(unsigned long *map, int start, int nr)
+{
+ unsigned long *p = map + BIT_WORD(start);
+ const int size = start + nr;
+ int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+ unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+ while (nr - bits_to_clear >= 0) {
+ *p &= ~mask_to_clear;
+ nr -= bits_to_clear;
+ bits_to_clear = BITS_PER_LONG;
+ mask_to_clear = ~0UL;
+ p++;
+ }
+ if (nr) {
+ mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+ *p &= ~mask_to_clear;
+ }
+}
+EXPORT_SYMBOL(bitmap_clear);
+
+/*
+ * bitmap_find_next_zero_area - find a contiguous aligned zero area
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @align_mask: Alignment mask for zero area
+ *
+ * The @align_mask should be one less than a power of 2; the effect is that
+ * the bit offset of all zero areas this function finds is multiples of that
+ * power of 2. A @align_mask of 0 means no alignment is required.
+ */
+unsigned long bitmap_find_next_zero_area(unsigned long *map,
+ unsigned long size,
+ unsigned long start,
+ unsigned int nr,
+ unsigned long align_mask)
+{
+ unsigned long index, end, i;
+again:
+ index = find_next_zero_bit(map, size, start);
+
+ /* Align allocation */
+ index = __ALIGN_MASK(index, align_mask);
+
+ end = index + nr;
+ if (end > size)
+ return end;
+ i = find_next_bit(map, end, index);
+ if (i < end) {
+ start = i + 1;
+ goto again;
+ }
+ return index;
+}
+EXPORT_SYMBOL(bitmap_find_next_zero_area);
+
/*
* Bitmap printing & parsing functions: first version by Bill Irwin,
* second version by Paul Jackson, third by Joe Korty.
--
1.6.5.1
^ permalink raw reply related
* [PATCH 2/7] iommu-helper: Use bitmap library
From: Akinobu Mita @ 2009-10-28 8:43 UTC (permalink / raw)
To: linux-kernel, akpm
Cc: Joerg Roedel, x86, Akinobu Mita, FUJITA Tomonori, linuxppc-dev,
Ingo Molnar, Paul Mackerras, H. Peter Anvin, sparclinux,
Thomas Gleixner, David S. Miller
In-Reply-To: <1256719397-4258-1-git-send-email-akinobu.mita@gmail.com>
Use bitmap library and kill some unused iommu helper functions.
1. s/iommu_area_free/bitmap_clear/
2. s/iommu_area_reserve/bitmap_set/
3. Use bitmap_find_next_zero_area instead of find_next_zero_area
This cannot be simple substitution because find_next_zero_area
doesn't check the last bit of the limit in bitmap
4. Remove iommu_area_free, iommu_area_reserve, and find_next_zero_area
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@ozlabs.org
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Cc: Joerg Roedel <joerg.roedel@amd.com>
---
arch/powerpc/kernel/iommu.c | 4 +-
arch/sparc/kernel/iommu.c | 3 +-
arch/x86/kernel/amd_iommu.c | 4 +-
arch/x86/kernel/pci-calgary_64.c | 6 ++--
arch/x86/kernel/pci-gart_64.c | 6 ++--
include/linux/iommu-helper.h | 3 --
lib/iommu-helper.c | 59 ++++++--------------------------------
7 files changed, 21 insertions(+), 64 deletions(-)
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index fd51578..5547ae6 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -30,7 +30,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/dma-mapping.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/iommu-helper.h>
#include <linux/crash_dump.h>
#include <asm/io.h>
@@ -251,7 +251,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
}
ppc_md.tce_free(tbl, entry, npages);
- iommu_area_free(tbl->it_map, free_entry, npages);
+ bitmap_clear(tbl->it_map, free_entry, npages);
}
static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 7690cc2..5fad949 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -11,6 +11,7 @@
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/iommu-helper.h>
+#include <linux/bitmap.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
@@ -169,7 +170,7 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np
entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
- iommu_area_free(arena->map, entry, npages);
+ bitmap_clear(arena->map, entry, npages);
}
int iommu_table_init(struct iommu *iommu, int tsbsize,
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 98f230f..08b1d20 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -19,7 +19,7 @@
#include <linux/pci.h>
#include <linux/gfp.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/debugfs.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
@@ -959,7 +959,7 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom,
address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT;
- iommu_area_free(range->bitmap, address, pages);
+ bitmap_clear(range->bitmap, address, pages);
}
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 971a3be..c87bb20 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -31,7 +31,7 @@
#include <linux/string.h>
#include <linux/crash_dump.h>
#include <linux/dma-mapping.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/pci_ids.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -211,7 +211,7 @@ static void iommu_range_reserve(struct iommu_table *tbl,
spin_lock_irqsave(&tbl->it_lock, flags);
- iommu_area_reserve(tbl->it_map, index, npages);
+ bitmap_set(tbl->it_map, index, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
@@ -305,7 +305,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
spin_lock_irqsave(&tbl->it_lock, flags);
- iommu_area_free(tbl->it_map, entry, npages);
+ bitmap_clear(tbl->it_map, entry, npages);
spin_unlock_irqrestore(&tbl->it_lock, flags);
}
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index a7f1b64..156e362 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -23,7 +23,7 @@
#include <linux/module.h>
#include <linux/topology.h>
#include <linux/interrupt.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/kdebug.h>
#include <linux/scatterlist.h>
#include <linux/iommu-helper.h>
@@ -123,7 +123,7 @@ static void free_iommu(unsigned long offset, int size)
unsigned long flags;
spin_lock_irqsave(&iommu_bitmap_lock, flags);
- iommu_area_free(iommu_gart_bitmap, offset, size);
+ bitmap_clear(iommu_gart_bitmap, offset, size);
if (offset >= next_bit)
next_bit = offset + size;
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
@@ -782,7 +782,7 @@ void __init gart_iommu_init(void)
* Out of IOMMU space handling.
* Reserve some invalid pages at the beginning of the GART.
*/
- iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES);
+ bitmap_set(iommu_gart_bitmap, 0, EMERGENCY_PAGES);
agp_memory_reserved = iommu_size;
printk(KERN_INFO
diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h
index 3b068e5..64d1b63 100644
--- a/include/linux/iommu-helper.h
+++ b/include/linux/iommu-helper.h
@@ -14,14 +14,11 @@ static inline unsigned long iommu_device_max_index(unsigned long size,
extern int iommu_is_span_boundary(unsigned int index, unsigned int nr,
unsigned long shift,
unsigned long boundary_size);
-extern void iommu_area_reserve(unsigned long *map, unsigned long i, int len);
extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
unsigned long start, unsigned int nr,
unsigned long shift,
unsigned long boundary_size,
unsigned long align_mask);
-extern void iommu_area_free(unsigned long *map, unsigned long start,
- unsigned int nr);
extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
unsigned long io_page_size);
diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c
index 75dbda0..c0251f4 100644
--- a/lib/iommu-helper.c
+++ b/lib/iommu-helper.c
@@ -3,41 +3,7 @@
*/
#include <linux/module.h>
-#include <linux/bitops.h>
-
-static unsigned long find_next_zero_area(unsigned long *map,
- unsigned long size,
- unsigned long start,
- unsigned int nr,
- unsigned long align_mask)
-{
- unsigned long index, end, i;
-again:
- index = find_next_zero_bit(map, size, start);
-
- /* Align allocation */
- index = (index + align_mask) & ~align_mask;
-
- end = index + nr;
- if (end >= size)
- return -1;
- for (i = index; i < end; i++) {
- if (test_bit(i, map)) {
- start = i+1;
- goto again;
- }
- }
- return index;
-}
-
-void iommu_area_reserve(unsigned long *map, unsigned long i, int len)
-{
- unsigned long end = i + len;
- while (i < end) {
- __set_bit(i, map);
- i++;
- }
-}
+#include <linux/bitmap.h>
int iommu_is_span_boundary(unsigned int index, unsigned int nr,
unsigned long shift,
@@ -55,31 +21,24 @@ unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
unsigned long align_mask)
{
unsigned long index;
+
+ /* We don't want the last of the limit */
+ size -= 1;
again:
- index = find_next_zero_area(map, size, start, nr, align_mask);
- if (index != -1) {
+ index = bitmap_find_next_zero_area(map, size, start, nr, align_mask);
+ if (index < size) {
if (iommu_is_span_boundary(index, nr, shift, boundary_size)) {
/* we could do more effectively */
start = index + 1;
goto again;
}
- iommu_area_reserve(map, index, nr);
+ bitmap_set(map, index, nr);
+ return index;
}
- return index;
+ return -1;
}
EXPORT_SYMBOL(iommu_area_alloc);
-void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
-{
- unsigned long end = start + nr;
-
- while (start < end) {
- __clear_bit(start, map);
- start++;
- }
-}
-EXPORT_SYMBOL(iommu_area_free);
-
unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
unsigned long io_page_size)
{
--
1.6.5.1
^ permalink raw reply related
* RE: Accessing flash directly from User Space
From: Kenneth Johansson @ 2009-10-28 9:56 UTC (permalink / raw)
To: Jonathan Haws; +Cc: Scott Wood, Bill Gatliff, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <BB99A6BA28709744BF22A68E6D7EB51F0330D368E3@midas.usurf.usu.edu>
On Tue, 2009-10-27 at 16:52 -0600, Jonathan Haws wrote:
> > Jonathan Haws wrote:
> > > I had thought about using MTD, but decided against it because with
> > > previous benchmarking that we did with MTD and our custom driver,
> > we
> > > found that our custom driver was about 10x faster.
> >
> > Ouch. Any idea where the slowdown is coming from?
>
> From what I remember (I would have to dig up notes to make sure) it is something to do with MTD looking for a signal to go high that is processed a bunch before MTD even sees it. Our flash produces a hardware ready signal that we are triggering off of to move on. MTD took much longer to report to us that the hardware was ready.
>
> Thanks
>
It would be interesting to know in more detail what is was. If we have a
10x performance increase hiding from for us I would be very interested
in knowing where it is.
Are you using some custom command to the flash that the generic chip
drivers in Linux is not yet supporting ?
^ permalink raw reply
* Re: Accessing flash directly from User Space
From: Josh Boyer @ 2009-10-28 11:24 UTC (permalink / raw)
To: Jonathan Haws; +Cc: Bill Gatliff, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <BB99A6BA28709744BF22A68E6D7EB51F0330D3688B@midas.usurf.usu.edu>
On Tue, Oct 27, 2009 at 04:24:53PM -0600, Jonathan Haws wrote:
>> >>> How can I get that pointer? Unfortunately I cannot simply use
>> the
>> >>>
>> >> address of the flash. Is there some magical function call that
>> >> gives me access to that portion of the memory space?
>> >>
>> >> $ man 2 mmap
>> >>
>> >> You want MAP_SHARED and O_SYNC.
>> >>
>> >
>> >
>> > To use that I need to have a file descriptor to a device, do I
>> not? However, I do not have a base flash driver to give me that
>> file descriptor. Am I missing something with that call?
>> >
>>
>> /dev/mem
>>
>Okay, I now have access to the flash memory, however when I write to it the writes do not take. I have tried calling msync() on the mapping to no avail. I have opened the fd with O_SYNC, but cannot get things to work right.
>
>Here are the calls:
>
> int fd = open("/dev/mem", O_SYNC | O_RDWR);
> uint16_t * flash = (uint16_t *)mmap(NULL, NOR_FLASH_SIZE,
> (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd,
> NOR_FLASH_BASE_ADRS);
What board and CPU are you using? Is your flash really at 0xFC800000, or is
that the virtual address that VxWorks puts it at?
josh
^ permalink raw reply
* Cache enable missing while creating TLBs for PPC440 platform.head_44x.S file.
From: Vineeth _ @ 2009-10-28 13:39 UTC (permalink / raw)
To: Johnny Hung, linuxppc-dev, Wolfgang Denk
Hi,
we are porting Linux 2.6.30 on a ppc440x5 based board.
when we check the kernel code in arch/powerpc/kernel/head_44x.S file @
line number 162,
while creating the TLB for 256MB, the cache enable/disable property is
not set by the kernel ? or are we missing smthing ?
when we gave that particular attribute, things started working. Please
find the kernel code below. We added "PPC44x_TLB_I" attribute to set
the cache, kernel started working.
----arch/powerpc/kernel/head_44x.S
/* Load the kernel PID = 0 */
li r0,0
mtspr SPRN_PID,r0
sync
/* Initialize MMUCR */
li r5,0
mtspr SPRN_MMUCR,r5
sync
/* pageid fields */
clrrwi r3,r3,10 /* Mask off the effective page number */
ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
/* xlat fields */
clrrwi r4,r4,10 /* Mask off the real page number */
/* ERPN is 0 for first 4GB page */
/* attrib fields */
/* Added guarded bit to protect against speculative loads/stores */
li r5,0
ori r5,r5,(PPC44x_TLB_I|PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX
| PPC44x_TLB_G)
/* that cache thing u see above line is added by some malguns there's
some issue */
li r0,63 /* TLB slot 63 */
tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
---------
Is this can be considered as a good patch ?
Thanks
Vineeth _
^ permalink raw reply
* Re: Micrel PHY KSZ8001 on MPC5200B FEC
From: suvidh kankariya @ 2009-10-28 15:19 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <mailman.1198.1256674402.12812.linuxppc-dev@lists.ozlabs.or g>
Romen,
I am sorry for the misguided statement.
I indeed had patched it .
I am copying the patch here. Hope it helps you.
diff --exclude CVS -uNr linux-2.6.30/drivers/net/phy/Kconfig
linux-2.6.30.modified/drivers/net/phy/Kconfig
--- linux-2.6.30/drivers/net/phy/Kconfig 2009-06-09
23:05:27.000000000 -0400
+++ linux-2.6.30.modified/drivers/net/phy/Kconfig 2009-10-09
15:43:09.000000000 -0400
@@ -82,6 +82,12 @@
---help---
Supports the LSI ET1011C PHY.
+config MICREL_PHY
+ tristate "Drivers for MICREL PHYs"
+ depends on PHYLIB
+ ---help---
+ Currently supports the KS8721BL, KSZ8041NL
+
config FIXED_PHY
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB=y
diff --exclude CVS -uNr linux-2.6.30/drivers/net/phy/Makefile
linux-2.6.30.modified/drivers/net/phy/Makefile
--- linux-2.6.30/drivers/net/phy/Makefile 2009-06-09
23:05:27.000000000 -0400
+++ linux-2.6.30.modified/drivers/net/phy/Makefile 2009-10-09
16:07:37.000000000 -0400
@@ -14,6 +14,7 @@
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
+obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
diff --exclude CVS -uNr linux-2.6.30/drivers/net/phy/micrel.c
linux-2.6.30.modified/drivers/net/phy/micrel.c
--- linux-2.6.30/drivers/net/phy/micrel.c 1969-12-31
19:00:00.000000000 -0500
+++ linux-2.6.30.modified/drivers/net/phy/micrel.c 2009-09-23
16:04:53.000000000 -0400
@@ -0,0 +1,129 @@
+ /* drivers/net/phy/micrel.c
+ *
+ * Driver for Micrel PHY
+ * based on drivers/net/phy/marvell.c *
+ *
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#define MII_MICRELL_RXERCR 0x15
+#define MII_MICRELL_ICSR 0x1B
+#define MII_MICRELL_PHYCR 0x1F
+
+
+MODULE_DESCRIPTION("Micrel PHY driver");
+MODULE_AUTHOR("Suvidh Kankariya");
+MODULE_LICENSE("GPL");
+
+
+static int micrel_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if(phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ {
+ err = phy_write(phydev, MII_MICRELL_ICSR, 0xFF00);
+ err = phy_write(phydev, 0, 0x1200); /* control register */
+ }
+ else
+ err = phy_write(phydev, MII_MICRELL_ICSR, 0);
+
+ return err;
+}
+
+static int micrel_config_init(struct phy_device *phydev)
+{
+ printk("Phy config done");
+
+ phy_write(phydev, MII_MICRELL_ICSR, 0);
+ return 0;
+}
+
+
+static int micrel_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_MICRELL_ICSR);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static struct phy_driver ks8721bl_driver = {
+ .phy_id = 0x000221619,
+ .name = "KS8721BL",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = micrel_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = micrel_ack_interrupt,
+ .config_intr = micrel_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+
+
+static struct phy_driver ksz8041nl_driver = {
+ .phy_id = 0x00022151,
+ .name = "KSZ8041NL",
+ .phy_id_mask = 0xfffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = micrel_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = micrel_ack_interrupt,
+ .config_intr = micrel_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init micrel_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&ks8721bl_driver);
+ if (ret)
+ return ret;
+ ret = phy_driver_register(&ksz8041nl_driver);
+ printk("Phy Init done");
+ if (ret)
+ goto err8041;
+
+ return 0;
+ err8041:
+ phy_driver_unregister(&ks8721bl_driver);
+ return ret;
+}
+
+static void __exit micrel_exit(void)
+{
+ phy_driver_unregister(&ks8721bl_driver);
+ phy_driver_unregister(&ksz8041nl_driver);
+}
+
+module_init(micrel_init);
+module_exit(micrel_exit);
Suvidh
>------------------------------
>
>Message: 6
>Date: Tue, 27 Oct 2009 20:54:47 +0100
>From: Roman Fietze <roman.fietze@telemotive.de>
>To: linuxppc-dev@lists.ozlabs.org
>Subject: Re: Micrel PHY KSZ8001 on MPC5200B FEC
>Message-ID: <200910272054.47398.roman.fietze@telemotive.de>
>Content-Type: Text/Plain; charset="iso-8859-1"
>
>Hello Suvidh,
>
>On Tuesday 27 October 2009 17:47:51 suvidh kankariya wrote:
>
> > A driver for micrel phy exists in /drivers/net/phy/micrel.c. in
> > 2.6.30.
>
>Am I somewhat blind, or do you have access to other 2.6.30's than I
>have?
>
>I searched git.kernel.org, git.denx.de and git.secretlab.ca, but could
>not find that file, neither in the current master, nor in older tags
>somewhat related to "2.6.30", nor in any local clone in any version of
>the 2.6 since "He" created the repos.
>
>
> > If you are using older kernel you may want to copy it.
>
>2.6.30 and 2.6.31 from DENX or kernel.org.
>
>
>Roman
>
>--
>Roman Fietze Telemotive AG B?ro M?hlhausen
>Breitwiesen 73347 M?hlhausen
>Tel.: +49(0)7335/18493-45 http://www.telemotive.de
>
>
>------------------------------
^ permalink raw reply
* RE: Accessing flash directly from User Space
From: Jonathan Haws @ 2009-10-28 14:38 UTC (permalink / raw)
To: Josh Boyer; +Cc: Bill Gatliff, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20091028112430.GO22408@zod.rchland.ibm.com>
> On Tue, Oct 27, 2009 at 04:24:53PM -0600, Jonathan Haws wrote:
> >> >>> How can I get that pointer? Unfortunately I cannot simply
> use
> >> the
> >> >>>
> >> >> address of the flash. Is there some magical function call
> that
> >> >> gives me access to that portion of the memory space?
> >> >>
> >> >> $ man 2 mmap
> >> >>
> >> >> You want MAP_SHARED and O_SYNC.
> >> >>
> >> >
> >> >
> >> > To use that I need to have a file descriptor to a device, do I
> >> not? However, I do not have a base flash driver to give me that
> >> file descriptor. Am I missing something with that call?
> >> >
> >>
> >> /dev/mem
> >>
> >Okay, I now have access to the flash memory, however when I write
> to it the writes do not take. I have tried calling msync() on the
> mapping to no avail. I have opened the fd with O_SYNC, but cannot
> get things to work right.
> >
> >Here are the calls:
> >
> > int fd =3D open("/dev/mem", O_SYNC | O_RDWR);
> > uint16_t * flash =3D (uint16_t *)mmap(NULL, NOR_FLASH_SIZE,
> > (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd,
> > NOR_FLASH_BASE_ADRS);
>=20
> What board and CPU are you using? Is your flash really at
> 0xFC800000, or is
> that the virtual address that VxWorks puts it at?
I am using a custom board based on the AMCC Kilauea development board. It =
uses a 405EX CPU. Yes, the flash is really at 0xFC000000.
^ permalink raw reply
* RE: Accessing flash directly from User Space
From: Jonathan Haws @ 2009-10-28 14:45 UTC (permalink / raw)
To: Kenneth Johansson; +Cc: Scott Wood, Bill Gatliff, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1256723805.32158.241.camel@kenjo-laptop>
> On Tue, 2009-10-27 at 16:52 -0600, Jonathan Haws wrote:
> > > Jonathan Haws wrote:
> > > > I had thought about using MTD, but decided against it because
> with
> > > > previous benchmarking that we did with MTD and our custom
> driver,
> > > we
> > > > found that our custom driver was about 10x faster.
> > >
> > > Ouch. Any idea where the slowdown is coming from?
> >
> > From what I remember (I would have to dig up notes to make sure)
> it is something to do with MTD looking for a signal to go high that
> is processed a bunch before MTD even sees it. Our flash produces a
> hardware ready signal that we are triggering off of to move on. MTD
> took much longer to report to us that the hardware was ready.
> >
> > Thanks
> >
>=20
> It would be interesting to know in more detail what is was. If we
> have a
> 10x performance increase hiding from for us I would be very
> interested
> in knowing where it is.
>=20
> Are you using some custom command to the flash that the generic chip
> drivers in Linux is not yet supporting ?
Looking through our notes and talking with the engineer who was performing =
the tests, it was exactly that - MTD was waiting for a signal that was prod=
uced differently than the hardware ready signal. By simply polling the fla=
sh until the hardware ready signal toggled we were able to get a much faste=
r read and write speed. Granted, most of our signals are being sent throug=
h a CPLD, so that may be why MTD did not work as well.
^ permalink raw reply
* Re: [PATCH 1/7] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
From: Andrew Morton @ 2009-10-28 20:11 UTC (permalink / raw)
To: Akinobu Mita
Cc: linux-usb, linux-ia64, linuxppc-dev, Paul Mackerras,
H. Peter Anvin, sparclinux, Lothar Wassmann, x86, linux-altix,
Ingo Molnar, Fenghua Yu, Joerg Roedel, Yevgeny Petrilin,
Thomas Gleixner, Tony Luck, netdev, Greg Kroah-Hartman,
linux-kernel, FUJITA Tomonori, David S. Miller
In-Reply-To: <1256719397-4258-1-git-send-email-akinobu.mita@gmail.com>
Why were these patches resent? What changed?
Everybody who is going to review these patches has already reviewed
them and now they need to review them all again?
^ permalink raw reply
* [PATCH 3/6 v5] Memory probe/release files
From: Nathan Fontenot @ 2009-10-28 20:55 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <4AE8ADCF.6090104@austin.ibm.com>
This patch creates the release sysfs file for memory and updates the
exisiting probe file so both make arch-specific callouts to handle removing
and adding memory to the system. This also creates the powerpc specific stubs
for handling the arch callouts.
The creation and use of these files are governed by the exisitng
CONFIG_ARCH_MEMORY_PROBE and new CONFIG_ARCH_MEMORY_RELEASE config options.
Signed-off-by: Nathan Fontenot <nfont at austin.ibm.com>
---
Index: powerpc/arch/powerpc/mm/mem.c
===================================================================
--- powerpc.orig/arch/powerpc/mm/mem.c 2009-10-28 15:20:36.000000000 -0500
+++ powerpc/arch/powerpc/mm/mem.c 2009-10-28 15:21:47.000000000 -0500
@@ -110,6 +110,26 @@
#ifdef CONFIG_MEMORY_HOTPLUG
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+int arch_memory_release(const char *buf, size_t count)
+{
+ if (ppc_md.memory_release)
+ return ppc_md.memory_release(buf, count);
+
+ return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+int arch_memory_probe(u64 phys_addr)
+{
+ if (ppc_md.memory_probe)
+ return ppc_md.memory_probe(phys_addr);
+
+ return -EINVAL;
+}
+#endif
+
#ifdef CONFIG_NUMA
int memory_add_physaddr_to_nid(u64 start)
{
Index: powerpc/drivers/base/memory.c
===================================================================
--- powerpc.orig/drivers/base/memory.c 2009-10-28 15:20:36.000000000 -0500
+++ powerpc/drivers/base/memory.c 2009-10-28 15:21:47.000000000 -0500
@@ -319,6 +319,10 @@
phys_addr = simple_strtoull(buf, NULL, 0);
+ ret = arch_memory_probe(phys_addr);
+ if (ret)
+ return ret;
+
nid = memory_add_physaddr_to_nid(phys_addr);
ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
@@ -328,19 +332,35 @@
return count;
}
static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
+#endif
-static int memory_probe_init(void)
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+static ssize_t
+memory_release_store(struct class *class, const char *buf, size_t count)
{
- return sysfs_create_file(&memory_sysdev_class.kset.kobj,
- &class_attr_probe.attr);
+ return arch_memory_release(buf, count);
}
-#else
-static inline int memory_probe_init(void)
+static CLASS_ATTR(release, S_IWUSR, NULL, memory_release_store);
+#endif
+
+static int memory_probe_release_init(void)
{
- return 0;
-}
+ int rc = 0;
+
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+ rc = sysfs_create_file(&memory_sysdev_class.kset.kobj,
+ &class_attr_probe.attr);
+#endif
+
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+ if (!rc)
+ rc = sysfs_create_file(&memory_sysdev_class.kset.kobj,
+ &class_attr_release.attr);
#endif
+ return rc;
+}
+
/*
* Note that phys_device is optional. It is here to allow for
* differentiation between which *physical* devices each
@@ -470,7 +490,7 @@
ret = err;
}
- err = memory_probe_init();
+ err = memory_probe_release_init();
if (!ret)
ret = err;
err = block_size_init();
Index: powerpc/arch/powerpc/include/asm/machdep.h
===================================================================
--- powerpc.orig/arch/powerpc/include/asm/machdep.h 2009-10-28 15:20:36.000000000 -0500
+++ powerpc/arch/powerpc/include/asm/machdep.h 2009-10-28 15:21:47.000000000 -0500
@@ -266,6 +266,14 @@
void (*suspend_disable_irqs)(void);
void (*suspend_enable_irqs)(void);
#endif
+
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+ int (*memory_release)(const char *, size_t);
+#endif
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+ int (*memory_probe)(u64);
+#endif
+
};
extern void e500_idle(void);
Index: powerpc/arch/powerpc/Kconfig
===================================================================
--- powerpc.orig/arch/powerpc/Kconfig 2009-10-28 15:20:36.000000000 -0500
+++ powerpc/arch/powerpc/Kconfig 2009-10-28 15:21:47.000000000 -0500
@@ -414,6 +414,10 @@
def_bool y
depends on MEMORY_HOTPLUG
+config ARCH_MEMORY_RELEASE
+ def_bool y
+ depends on MEMORY_HOTPLUG
+
# Some NUMA nodes have memory ranges that span
# other nodes. Even though a pfn is valid and
# between a node's start and end pfns, it may not
Index: powerpc/include/linux/memory_hotplug.h
===================================================================
--- powerpc.orig/include/linux/memory_hotplug.h 2009-10-28 15:20:36.000000000 -0500
+++ powerpc/include/linux/memory_hotplug.h 2009-10-28 15:21:47.000000000 -0500
@@ -86,6 +86,14 @@
}
#endif
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+extern int arch_memory_release(const char *, size_t);
+#endif
+
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+extern int arch_memory_probe(u64);
+#endif
+
#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
/*
* For supporting node-hotadd, we have to allocate a new pgdat.
^ permalink raw reply
* [PATCH 0/6 v5] Kernel handling of Dynamic Logical Partitioning
From: Nathan Fontenot @ 2009-10-28 20:47 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
This is a re-send of the entire patch set with updates made from recent
comments received.
The Dynamic Logical Partitioning (DLPAR) capabilities of the powerpc pseries
platform allows for the addition and removal of resources (i.e. cpus,
memory, pci devices) from a partition. The removal of a resource involves
removing the resource's node from the device tree and then returning the
resource to firmware via the rtas set-indicator call. To add a resource, it
is first obtained from firmware via the rtas set-indicator call and then a
new device tree node is created using the ibm,configure-coinnector rtas call
and added to the device tree.
The following set of patches implements the needed infrastructure to have the
kernel handle the DLPAR addition and removal of memory and cpus (other
DLPAR'able items to follow in future patches). The framework for this is
to create a set of probe/release sysfs files that will facilitate
arch-specific call-outs to handle addition and removal of cpus and memory to
the system.
Patches include in this set:
1/6 - DLPAR infracstructure for powerpc/pseries platform.
2/6 - Move the of_drconf_cell struct to prom.h
3/6 - Create memory probe/release files and the powerpc handlers for them
4/6 - Memory DLPAR handling
5/6 - Create sysfs cpu probe/release files and the powerpc handlers for them
6/6 - CPU DLPAR handling
-Nathan Fontenot
^ permalink raw reply
* [PATCH 2/6 v5] Move of_drconf_cell to prom.h
From: Nathan Fontenot @ 2009-10-28 20:54 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <4AE8ADCF.6090104@austin.ibm.com>
Move the definition of the of_drconf_cell struct from numa.c to prom.h. This
is needed so that we can parse the ibm,dynamic-memory device-tree property
when DLPAR adding and removing memory.
Signed-off-by: Nathan Fontenot <nfont at austin.ibm.com>
---
Index: powerpc/arch/powerpc/include/asm/prom.h
===================================================================
--- powerpc.orig/arch/powerpc/include/asm/prom.h 2009-10-28 15:20:37.000000000 -0500
+++ powerpc/arch/powerpc/include/asm/prom.h 2009-10-28 15:21:44.000000000 -0500
@@ -349,6 +349,18 @@
*/
extern void __iomem *of_iomap(struct device_node *device, int index);
+struct of_drconf_cell {
+ u64 base_addr;
+ u32 drc_index;
+ u32 reserved;
+ u32 aa_index;
+ u32 flags;
+};
+
+#define DRCONF_MEM_ASSIGNED 0x00000008
+#define DRCONF_MEM_AI_INVALID 0x00000040
+#define DRCONF_MEM_RESERVED 0x00000080
+
/*
* NB: This is here while we transition from using asm/prom.h
* to linux/of.h
Index: powerpc/arch/powerpc/mm/numa.c
===================================================================
--- powerpc.orig/arch/powerpc/mm/numa.c 2009-10-28 15:20:37.000000000 -0500
+++ powerpc/arch/powerpc/mm/numa.c 2009-10-28 15:21:44.000000000 -0500
@@ -296,18 +296,6 @@
return result;
}
-struct of_drconf_cell {
- u64 base_addr;
- u32 drc_index;
- u32 reserved;
- u32 aa_index;
- u32 flags;
-};
-
-#define DRCONF_MEM_ASSIGNED 0x00000008
-#define DRCONF_MEM_AI_INVALID 0x00000040
-#define DRCONF_MEM_RESERVED 0x00000080
-
/*
* Read the next lmb list entry from the ibm,dynamic-memory property
* and return the information in the provided of_drconf_cell structure.
^ permalink raw reply
* Re: [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
From: Valentine @ 2009-10-28 21:28 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: olof, linuxppc-dev, paulus
In-Reply-To: <1256761844.26770.2.camel@pasglop>
Benjamin Herrenschmidt wrote:
> On Wed, 2009-10-28 at 22:19 +0300, Valentine wrote:
>
>> I'm just not sure that we need to clear HARDIRQEN here, since we don't
>> really hard-disable the the interrupts.
>
> We do, or rather, we come in with the interrupts hard disabled, no ?
Yes, looks like the interrupts are disabled at this point (before
preempt_schedule_irq) most of the times, but we don't hard-disable them
here. We just soft-disable them to make preempt_schedule_irq happy. Even
if an interrupt fires, it will be hard-disabled and the hardirq flag
will be cleared by the exception handler right away. I just think that
there's no need to clear hardirq flag if we don't clear MSR_EE.
Thanks,
Val.
>
> Ben.
>
>> Thanks,
>> Val.
>>
>>> + TRACE_DISABLE_INTS
>>> +
>>> + /* Call the scheduler with soft IRQs off */
>>> +1: bl .preempt_schedule_irq
>>> +
>>> + /* Hard-disable interrupts again (and update PACA) */
>>> #ifdef CONFIG_PPC_BOOK3E
>>> - wrteei 1
>>> - bl .preempt_schedule
>>> wrteei 0
>>> #else
>>> - ori r10,r10,MSR_EE
>>> - mtmsrd r10,1 /* reenable interrupts */
>>> - bl .preempt_schedule
>>> mfmsr r10
>>> - clrrdi r9,r1,THREAD_SHIFT
>>> - rldicl r10,r10,48,1 /* disable interrupts again */
>>> + rldicl r10,r10,48,1
>>> rotldi r10,r10,16
>>> mtmsrd r10,1
>>> #endif /* CONFIG_PPC_BOOK3E */
>>> + li r0,0
>>> + stb r0,PACAHARDIRQEN(r13)
>>> +
>>> + /* Re-test flags and eventually loop */
>>> + clrrdi r9,r1,THREAD_SHIFT
>>> ld r4,TI_FLAGS(r9)
>>> andi. r0,r4,_TIF_NEED_RESCHED
>>> bne 1b
>>> b restore
>>>
>>> user_work:
>>> -#endif
>>> +#endif /* CONFIG_PREEMPT */
>>> +
>>> /* Enable interrupts */
>>> #ifdef CONFIG_PPC_BOOK3E
>>> wrteei 1
>
>
^ permalink raw reply
* [PATCH 6/6 v5] CPU DLPAR Handling
From: Nathan Fontenot @ 2009-10-28 20:59 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <4AE8ADCF.6090104@austin.ibm.com>
Register the pseries specific handler for the powerpc architecture handlers
for the cpu probe and release files. This also implements the cpu DLPAR
addition and removal of CPUS from the system.
Signed-off-by: Nathan Fontenot <nfont at asutin.ibm.com>
---
Index: powerpc/arch/powerpc/platforms/pseries/dlpar.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pseries/dlpar.c 2009-10-28 15:21:49.000000000 -0500
+++ powerpc/arch/powerpc/platforms/pseries/dlpar.c 2009-10-28 15:21:56.000000000 -0500
@@ -1,11 +1,10 @@
/*
- * dlpar.c - support for dynamic reconfiguration (including PCI
- * Hotplug and Dynamic Logical Partitioning on RPA platforms).
+ * Support for dynamic reconfiguration (including PCI, Memory, and CPU
+ * Hotplug and Dynamic Logical Partitioning on PAPR platforms).
*
* Copyright (C) 2009 Nathan Fontenot
* Copyright (C) 2009 IBM Corporation
*
- *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
@@ -19,7 +18,7 @@
#include <linux/memory_hotplug.h>
#include <linux/sysdev.h>
#include <linux/sysfs.h>
-
+#include <linux/cpu.h>
#include <asm/prom.h>
#include <asm/machdep.h>
@@ -408,6 +407,80 @@
return 0;
}
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+static ssize_t cpu_probe(const char *buf, size_t count)
+{
+ struct device_node *dn;
+ unsigned long drc_index;
+ char *cpu_name;
+ int rc;
+
+ rc = strict_strtoul(buf, 0, &drc_index);
+ if (rc)
+ return -EINVAL;
+
+ rc = acquire_drc(drc_index);
+ if (rc)
+ return -EINVAL;
+
+ dn = configure_connector(drc_index);
+ if (!dn) {
+ release_drc(drc_index);
+ return -EINVAL;
+ }
+
+ /* fixup dn name */
+ cpu_name = kzalloc(strlen(dn->full_name) + strlen("/cpus/") + 1,
+ GFP_KERNEL);
+ if (!cpu_name) {
+ free_cc_nodes(dn);
+ release_drc(drc_index);
+ return -ENOMEM;
+ }
+
+ sprintf(cpu_name, "/cpus/%s", dn->full_name);
+ kfree(dn->full_name);
+ dn->full_name = cpu_name;
+
+ rc = add_device_tree_nodes(dn);
+ if (rc)
+ release_drc(drc_index);
+
+ return rc ? -EINVAL : count;
+}
+
+static ssize_t cpu_release(const char *buf, size_t count)
+{
+ struct device_node *dn;
+ const u32 *drc_index;
+ int rc;
+
+ dn = of_find_node_by_path(buf);
+ if (!dn)
+ return -EINVAL;
+
+ drc_index = of_get_property(dn, "ibm,my-drc-index", NULL);
+ if (!drc_index) {
+ of_node_put(dn);
+ return -EINVAL;
+ }
+
+ rc = release_drc(*drc_index);
+ if (rc) {
+ of_node_put(dn);
+ return -EINVAL;
+ }
+
+ rc = remove_device_tree_nodes(dn);
+ if (rc)
+ acquire_drc(*drc_index);
+
+ of_node_put(dn);
+ return rc ? -EINVAL : count;
+}
+
+#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
+
#ifdef CONFIG_MEMORY_HOTPLUG
static struct property *clone_property(struct property *old_prop)
@@ -591,6 +664,11 @@
ppc_md.memory_probe = memory_probe;
#endif
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+ ppc_md.cpu_release = cpu_release;
+ ppc_md.cpu_probe = cpu_probe;
+#endif
+
return 0;
}
device_initcall(pseries_dlpar_init);
^ permalink raw reply
* [PATCH 5/6 v5] CPU probe/release files
From: Nathan Fontenot @ 2009-10-28 20:58 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <4AE8ADCF.6090104@austin.ibm.com>
Create new probe and release sysfs files to facilitate adding and removing
cpus from the system. This also creates the powerpc specific stubs to handle
the arch callouts from writes to the sysfs files.
The creation and use of these files is regulated by the
CONFIG_ARCH_CPU_PROBE_RELEASE option so that only architectures that need the
capability will have the files created.
Signed-off-by: Nathan Fontenot <nfont at austin.ibm.com>
---
Index: powerpc/drivers/base/cpu.c
===================================================================
--- powerpc.orig/drivers/base/cpu.c 2009-10-28 15:20:34.000000000 -0500
+++ powerpc/drivers/base/cpu.c 2009-10-28 15:21:53.000000000 -0500
@@ -54,6 +54,7 @@
ret = count;
return ret;
}
+
static SYSDEV_ATTR(online, 0644, show_online, store_online);
static void __cpuinit register_cpu_control(struct cpu *cpu)
@@ -72,6 +73,38 @@
per_cpu(cpu_sys_devices, logical_cpu) = NULL;
return;
}
+
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+static ssize_t cpu_probe_store(struct class *class, const char *buf,
+ size_t count)
+{
+ return arch_cpu_probe(buf, count);
+}
+
+static ssize_t cpu_release_store(struct class *class, const char *buf,
+ size_t count)
+{
+ return arch_cpu_release(buf, count);
+}
+
+static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
+static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
+
+int __init cpu_probe_release_init(void)
+{
+ int rc;
+
+ rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+ &class_attr_probe.attr);
+ if (!rc)
+ rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
+ &class_attr_release.attr);
+
+ return rc;
+}
+device_initcall(cpu_probe_release_init);
+#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
+
#else /* ... !CONFIG_HOTPLUG_CPU */
static inline void register_cpu_control(struct cpu *cpu)
{
Index: powerpc/arch/powerpc/include/asm/machdep.h
===================================================================
--- powerpc.orig/arch/powerpc/include/asm/machdep.h 2009-10-28 15:21:47.000000000 -0500
+++ powerpc/arch/powerpc/include/asm/machdep.h 2009-10-28 15:21:53.000000000 -0500
@@ -274,6 +274,11 @@
int (*memory_probe)(u64);
#endif
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+ ssize_t (*cpu_probe)(const char *, size_t);
+ ssize_t (*cpu_release)(const char *, size_t);
+#endif
+
};
extern void e500_idle(void);
Index: powerpc/arch/powerpc/kernel/sysfs.c
===================================================================
--- powerpc.orig/arch/powerpc/kernel/sysfs.c 2009-10-28 15:20:34.000000000 -0500
+++ powerpc/arch/powerpc/kernel/sysfs.c 2009-10-28 15:21:53.000000000 -0500
@@ -461,6 +461,25 @@
cacheinfo_cpu_offline(cpu);
}
+
+#ifdef CONFIG_ARCH_PROBE_RELEASE
+ssize_t arch_cpu_probe(const char *buf, size_t count)
+{
+ if (ppc_md.cpu_probe)
+ return ppc_md.cpu_probe(buf, count);
+
+ return -EINVAL;
+}
+
+ssize_t arch_cpu_release(const char *buf, size_t count)
+{
+ if (ppc_md.cpu_release)
+ return ppc_md.cpu_release(buf, count);
+
+ return -EINVAL;
+}
+#endif /* CONFIG_ARCH_PROBE_RELEASE */
+
#endif /* CONFIG_HOTPLUG_CPU */
static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
Index: powerpc/arch/powerpc/Kconfig
===================================================================
--- powerpc.orig/arch/powerpc/Kconfig 2009-10-28 15:21:47.000000000 -0500
+++ powerpc/arch/powerpc/Kconfig 2009-10-28 15:21:53.000000000 -0500
@@ -320,6 +320,10 @@
Say N if you are unsure.
+config ARCH_CPU_PROBE_RELEASE
+ def_bool y
+ depends on HOTPLUG_CPU
+
config ARCH_ENABLE_MEMORY_HOTPLUG
def_bool y
Index: powerpc/include/linux/cpu.h
===================================================================
--- powerpc.orig/include/linux/cpu.h 2009-10-28 15:20:34.000000000 -0500
+++ powerpc/include/linux/cpu.h 2009-10-28 15:21:53.000000000 -0500
@@ -43,6 +43,10 @@
#ifdef CONFIG_HOTPLUG_CPU
extern void unregister_cpu(struct cpu *cpu);
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+extern ssize_t arch_cpu_probe(const char *, size_t);
+extern ssize_t arch_cpu_release(const char *, size_t);
+#endif
#endif
struct notifier_block;
Index: powerpc/arch/powerpc/kernel/smp.c
===================================================================
--- powerpc.orig/arch/powerpc/kernel/smp.c 2009-10-28 15:20:34.000000000 -0500
+++ powerpc/arch/powerpc/kernel/smp.c 2009-10-28 15:21:53.000000000 -0500
@@ -364,7 +364,24 @@
set_cpu_online(cpu, true);
local_irq_enable();
}
+
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+ssize_t arch_cpu_probe(const char *buf, size_t count)
+{
+ if (ppc_md.cpu_probe)
+ return ppc_md.cpu_probe(buf, count);
+
+ return -EINVAL;
+}
+ssize_t arch_cpu_release(const char *buf, size_t count)
+{
+ if (ppc_md.cpu_release)
+ return ppc_md.cpu_release(buf, count);
+
+ return -EINVAL;
+}
#endif
+#endif /* CONFIG_HOTPLUG_CPU */
static int __devinit cpu_enable(unsigned int cpu)
{
^ permalink raw reply
* [PATCH 4/6 v5] Memory DLPAR Handling
From: Nathan Fontenot @ 2009-10-28 20:57 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <4AE8ADCF.6090104@austin.ibm.com>
This adds the capability to DLPAR add and remove memory from the kernel. The
patch registers handlers for the arch-specific probe and release memory
callouts to handle addition/removal of memory to the system and the associated
device tree updates.
Signed-off-by: Nathan Fontenot <nfont at austin.ibm.com>
---
Index: powerpc/arch/powerpc/platforms/pseries/dlpar.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pseries/dlpar.c 2009-10-28 15:21:38.000000000 -0500
+++ powerpc/arch/powerpc/platforms/pseries/dlpar.c 2009-10-28 15:21:49.000000000 -0500
@@ -16,6 +16,10 @@
#include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
+#include <linux/memory_hotplug.h>
+#include <linux/sysdev.h>
+#include <linux/sysfs.h>
+
#include <asm/prom.h>
#include <asm/machdep.h>
@@ -404,11 +408,189 @@
return 0;
}
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+static struct property *clone_property(struct property *old_prop)
+{
+ struct property *new_prop;
+
+ new_prop = kzalloc((sizeof *new_prop), GFP_KERNEL);
+ if (!new_prop)
+ return NULL;
+
+ new_prop->name = kstrdup(old_prop->name, GFP_KERNEL);
+ new_prop->value = kzalloc(old_prop->length + 1, GFP_KERNEL);
+ if (!new_prop->name || !new_prop->value) {
+ free_property(new_prop);
+ return NULL;
+ }
+
+ memcpy(new_prop->value, old_prop->value, old_prop->length);
+ new_prop->length = old_prop->length;
+
+ return new_prop;
+}
+
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+
+int memory_probe(u64 phys_addr)
+{
+ struct device_node *dn = NULL;
+ struct property *new_prop;
+ struct property *old_prop;
+ struct of_drconf_cell *drmem;
+ const u64 *lmb_size;
+ int num_entries, i;
+ int rc = -EINVAL;
+
+ if (!phys_addr)
+ goto memory_probe_exit;
+
+ dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+ if (!dn)
+ goto memory_probe_exit;
+
+ lmb_size = of_get_property(dn, "ibm,lmb-size", NULL);
+ if (!lmb_size)
+ goto memory_probe_exit;
+
+ old_prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
+ if (!old_prop)
+ goto memory_probe_exit;
+
+ num_entries = *(u32 *)old_prop->value;
+ drmem = (struct of_drconf_cell *)
+ ((char *)old_prop->value + sizeof(u32));
+
+ for (i = 0; i < num_entries; i++) {
+ u64 lmb_end_addr = drmem[i].base_addr + *lmb_size;
+ if (phys_addr >= drmem[i].base_addr
+ && phys_addr < lmb_end_addr)
+ break;
+ }
+
+ if (i >= num_entries)
+ goto memory_probe_exit;
+
+ if (drmem[i].flags & DRCONF_MEM_ASSIGNED) {
+ /* This lmb is already adssigned to the system, nothing to do */
+ rc = 0;
+ goto memory_probe_exit;
+ }
+
+ rc = acquire_drc(drmem[i].drc_index);
+ if (rc) {
+ rc = -EINVAL;
+ goto memory_probe_exit;
+ }
+
+ new_prop = clone_property(old_prop);
+ drmem = (struct of_drconf_cell *)
+ ((char *)new_prop->value + sizeof(u32));
+
+ drmem[i].flags |= DRCONF_MEM_ASSIGNED;
+ rc = prom_update_property(dn, new_prop, old_prop);
+ if (rc) {
+ free_property(new_prop);
+ rc = -EINVAL;
+ goto memory_probe_exit;
+ }
+
+ rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ PSERIES_DRCONF_MEM_ADD,
+ &drmem[i].base_addr);
+ if (rc == NOTIFY_BAD) {
+ prom_update_property(dn, old_prop, new_prop);
+ release_drc(drmem[i].drc_index);
+ rc = -EINVAL;
+ } else
+ rc = 0;
+
+memory_probe_exit:
+ of_node_put(dn);
+ return rc;
+}
+
+#endif /* CONFIG_ARCH_MEMORY_PROBE */
+
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+
+static int memory_release(const char *buf, size_t count)
+{
+ unsigned long drc_index;
+ struct device_node *dn;
+ struct property *new_prop, *old_prop;
+ struct of_drconf_cell *drmem;
+ int num_entries;
+ int i;
+ int rc = -EINVAL;
+
+ rc = strict_strtoul(buf, 0, &drc_index);
+ if (rc)
+ return rc;
+
+ dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+ if (!dn)
+ return rc;
+
+ old_prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
+ if (!old_prop)
+ goto memory_release_exit;
+
+ num_entries = *(u32 *)old_prop->value;
+ drmem = (struct of_drconf_cell *)
+ ((char *)old_prop->value + sizeof(u32));
+
+ for (i = 0; i < num_entries; i++) {
+ if (drmem[i].drc_index == drc_index)
+ break;
+ }
+
+ if (i >= num_entries)
+ goto memory_release_exit;
+
+ new_prop = clone_property(old_prop);
+ drmem = (struct of_drconf_cell *)
+ ((char *)new_prop->value + sizeof(u32));
+
+ drmem[i].flags &= ~DRCONF_MEM_ASSIGNED;
+ rc = prom_update_property(dn, new_prop, old_prop);
+ if (rc) {
+ free_property(new_prop);
+ rc = -EINVAL;
+ goto memory_release_exit;
+ }
+
+ rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ PSERIES_DRCONF_MEM_REMOVE,
+ &drmem[i].base_addr);
+ if (rc != NOTIFY_BAD)
+ rc = release_drc(drc_index);
+
+ if (rc) {
+ prom_update_property(dn, old_prop, new_prop);
+ rc = -EINVAL;
+ }
+
+memory_release_exit:
+ of_node_put(dn);
+ return rc ? rc : count;
+}
+#endif /* CONFIG_ARCH_MEMORY_RELEASE */
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
static int pseries_dlpar_init(void)
{
if (!machine_is(pseries))
return 0;
+#ifdef CONFIG_ARCH_MEMORY_RELEASE
+ ppc_md.memory_release = memory_release;
+#endif
+#ifdef CONFIG_ARCH_MEMORY_PROBE
+ ppc_md.memory_probe = memory_probe;
+#endif
+
return 0;
}
device_initcall(pseries_dlpar_init);
^ permalink raw reply
* RE: Accessing flash directly from User Space [SOLVED]
From: Jonathan Haws @ 2009-10-28 17:44 UTC (permalink / raw)
To: Jonathan Haws, Josh Boyer; +Cc: Bill Gatliff, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <BB99A6BA28709744BF22A68E6D7EB51F0330D36A3D@midas.usurf.usu.edu>
> > On Tue, Oct 27, 2009 at 04:24:53PM -0600, Jonathan Haws wrote:
> > >> >>> How can I get that pointer? Unfortunately I cannot simply
> > use
> > >> the
> > >> >>>
> > >> >> address of the flash. Is there some magical function call
> > that
> > >> >> gives me access to that portion of the memory space?
> > >> >>
> > >> >> $ man 2 mmap
> > >> >>
> > >> >> You want MAP_SHARED and O_SYNC.
> > >> >>
> > >> >
> > >> >
> > >> > To use that I need to have a file descriptor to a device, do
> I
> > >> not? However, I do not have a base flash driver to give me
> that
> > >> file descriptor. Am I missing something with that call?
> > >> >
> > >>
> > >> /dev/mem
> > >>
> > >Okay, I now have access to the flash memory, however when I write
> > to it the writes do not take. I have tried calling msync() on the
> > mapping to no avail. I have opened the fd with O_SYNC, but cannot
> > get things to work right.
> > >
> > >Here are the calls:
> > >
> > > int fd =3D open("/dev/mem", O_SYNC | O_RDWR);
> > > uint16_t * flash =3D (uint16_t *)mmap(NULL, NOR_FLASH_SIZE,
> > > (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd,
> > > NOR_FLASH_BASE_ADRS);
> >
> > What board and CPU are you using? Is your flash really at
> > 0xFC800000, or is
> > that the virtual address that VxWorks puts it at?
>=20
> I am using a custom board based on the AMCC Kilauea development
> board. It uses a 405EX CPU. Yes, the flash is really at
> 0xFC000000.
I have found the problem. It occurred to me in the shower (okay not really=
, but most good ideas happen there).
What was happening is that I was in fact able to write to the correct regis=
ters. However, I would try and write to them in a batch. But the way mmap=
works (at least according to the man page) with MAP_SHARED is that the fil=
e may not be updated until msync() is called. Now, I thought that O_SYNC w=
ould take care of that when I open /dev/mem, but that was not the case.
Anyway, to make a long story short, I inserted an msync() after each assign=
ment to the flash. This resolved my problem and I can now program my flash=
.
Thanks everyone for your help!
Jonathan
^ permalink raw reply
* Re: Cache enable missing while creating TLBs for PPC440 platform.head_44x.S file.
From: Benjamin Herrenschmidt @ 2009-10-28 22:17 UTC (permalink / raw)
To: Vineeth _; +Cc: Johnny Hung, linuxppc-dev, Wolfgang Denk
In-Reply-To: <a9b543570910280639j1ea9038du452249e89215a57e@mail.gmail.com>
On Wed, 2009-10-28 at 19:09 +0530, Vineeth _ wrote:
> Hi,
> we are porting Linux 2.6.30 on a ppc440x5 based board.
> when we check the kernel code in arch/powerpc/kernel/head_44x.S file @
> line number 162,
> while creating the TLB for 256MB, the cache enable/disable property is
> not set by the kernel ? or are we missing smthing ?
> when we gave that particular attribute, things started working. Please
> find the kernel code below. We added "PPC44x_TLB_I" attribute to set
> the cache, kernel started working.
Ugh ?
Why would you want to set I on the kernel memory ? I means "cache
inhibited", which -disables- the cache. You really don't want that. You
must have something else wrong.
Cheers,
Ben.
> ----arch/powerpc/kernel/head_44x.S
>
> /* Load the kernel PID = 0 */
> li r0,0
> mtspr SPRN_PID,r0
> sync
>
> /* Initialize MMUCR */
> li r5,0
> mtspr SPRN_MMUCR,r5
> sync
>
> /* pageid fields */
> clrrwi r3,r3,10 /* Mask off the effective page number */
> ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
>
> /* xlat fields */
> clrrwi r4,r4,10 /* Mask off the real page number */
> /* ERPN is 0 for first 4GB page */
>
> /* attrib fields */
> /* Added guarded bit to protect against speculative loads/stores */
> li r5,0
> ori r5,r5,(PPC44x_TLB_I|PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX
> | PPC44x_TLB_G)
> /* that cache thing u see above line is added by some malguns there's
> some issue */
>
> li r0,63 /* TLB slot 63 */
>
> tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
> tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */
> tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
>
> ---------
>
> Is this can be considered as a good patch ?
>
> Thanks
> Vineeth _
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH 1/6 v5] Kernel DLPAR Infrastructure
From: Nathan Fontenot @ 2009-10-28 20:53 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
In-Reply-To: <4AE8ADCF.6090104@austin.ibm.com>
This patch provides the kernel DLPAR infrastructure in a new filed named
dlpar.c. The functionality provided is for acquiring and releasing a resource
from firmware and the parsing of information returned from the
ibm,configure-connector rtas call. Additionally this exports the pSeries
reconfiguration notifier chain so that it can be invoked when device tree
updates are made.
Signed-off-by: Nathan Fontenot <nfont at austin.ibm.com>
---
Index: powerpc/arch/powerpc/platforms/pseries/dlpar.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ powerpc/arch/powerpc/platforms/pseries/dlpar.c 2009-10-28 15:21:38.000000000 -0500
@@ -0,0 +1,414 @@
+/*
+ * dlpar.c - support for dynamic reconfiguration (including PCI
+ * Hotplug and Dynamic Logical Partitioning on RPA platforms).
+ *
+ * Copyright (C) 2009 Nathan Fontenot
+ * Copyright (C) 2009 IBM Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/notifier.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/uaccess.h>
+#include <asm/rtas.h>
+#include <asm/pSeries_reconfig.h>
+
+#define CFG_CONN_WORK_SIZE 4096
+static char workarea[CFG_CONN_WORK_SIZE];
+static DEFINE_SPINLOCK(workarea_lock);
+
+struct cc_workarea {
+ u32 drc_index;
+ u32 zero;
+ u32 name_offset;
+ u32 prop_length;
+ u32 prop_offset;
+};
+
+static struct property *parse_cc_property(char *workarea)
+{
+ struct property *prop;
+ struct cc_workarea *ccwa;
+ char *name;
+ char *value;
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return NULL;
+
+ ccwa = (struct cc_workarea *)workarea;
+ name = workarea + ccwa->name_offset;
+ prop->name = kzalloc(strlen(name) + 1, GFP_KERNEL);
+ if (!prop->name) {
+ kfree(prop);
+ return NULL;
+ }
+
+ strcpy(prop->name, name);
+
+ prop->length = ccwa->prop_length;
+ value = workarea + ccwa->prop_offset;
+ prop->value = kzalloc(prop->length, GFP_KERNEL);
+ if (!prop->value) {
+ kfree(prop->name);
+ kfree(prop);
+ return NULL;
+ }
+
+ memcpy(prop->value, value, prop->length);
+ return prop;
+}
+
+static void free_property(struct property *prop)
+{
+ kfree(prop->name);
+ kfree(prop->value);
+ kfree(prop);
+}
+
+static struct device_node *parse_cc_node(char *work_area)
+{
+ struct device_node *dn;
+ struct cc_workarea *ccwa;
+ char *name;
+
+ dn = kzalloc(sizeof(*dn), GFP_KERNEL);
+ if (!dn)
+ return NULL;
+
+ ccwa = (struct cc_workarea *)work_area;
+ name = work_area + ccwa->name_offset;
+ dn->full_name = kzalloc(strlen(name) + 1, GFP_KERNEL);
+ if (!dn->full_name) {
+ kfree(dn);
+ return NULL;
+ }
+
+ strcpy(dn->full_name, name);
+ return dn;
+}
+
+static void free_one_cc_node(struct device_node *dn)
+{
+ struct property *prop;
+
+ while (dn->properties) {
+ prop = dn->properties;
+ dn->properties = prop->next;
+ free_property(prop);
+ }
+
+ kfree(dn->full_name);
+ kfree(dn);
+}
+
+static void free_cc_nodes(struct device_node *dn)
+{
+ if (dn->child)
+ free_cc_nodes(dn->child);
+
+ if (dn->sibling)
+ free_cc_nodes(dn->sibling);
+
+ free_one_cc_node(dn);
+}
+
+#define NEXT_SIBLING 1
+#define NEXT_CHILD 2
+#define NEXT_PROPERTY 3
+#define PREV_PARENT 4
+#define MORE_MEMORY 5
+#define CALL_AGAIN -2
+#define ERR_CFG_USE -9003
+
+struct device_node *configure_connector(u32 drc_index)
+{
+ struct device_node *dn;
+ struct device_node *first_dn = NULL;
+ struct device_node *last_dn = NULL;
+ struct property *property;
+ struct property *last_property = NULL;
+ struct cc_workarea *ccwa;
+ int cc_token;
+ int rc;
+
+ cc_token = rtas_token("ibm,configure-connector");
+ if (cc_token == RTAS_UNKNOWN_SERVICE)
+ return NULL;
+
+ spin_lock(&workarea_lock);
+
+ ccwa = (struct cc_workarea *)&workarea[0];
+ ccwa->drc_index = drc_index;
+ ccwa->zero = 0;
+
+ rc = rtas_call(cc_token, 2, 1, NULL, workarea, NULL);
+ while (rc) {
+ switch (rc) {
+ case NEXT_SIBLING:
+ dn = parse_cc_node(workarea);
+ if (!dn)
+ goto cc_error;
+
+ dn->parent = last_dn->parent;
+ last_dn->sibling = dn;
+ last_dn = dn;
+ break;
+
+ case NEXT_CHILD:
+ dn = parse_cc_node(workarea);
+ if (!dn)
+ goto cc_error;
+
+ if (!first_dn)
+ first_dn = dn;
+ else {
+ dn->parent = last_dn;
+ if (last_dn)
+ last_dn->child = dn;
+ }
+
+ last_dn = dn;
+ break;
+
+ case NEXT_PROPERTY:
+ property = parse_cc_property(workarea);
+ if (!property)
+ goto cc_error;
+
+ if (!last_dn->properties)
+ last_dn->properties = property;
+ else
+ last_property->next = property;
+
+ last_property = property;
+ break;
+
+ case PREV_PARENT:
+ last_dn = last_dn->parent;
+ break;
+
+ case CALL_AGAIN:
+ break;
+
+ case MORE_MEMORY:
+ case ERR_CFG_USE:
+ default:
+ printk(KERN_ERR "Unexpected Error (%d) "
+ "returned from configure-connector\n", rc);
+ goto cc_error;
+ }
+
+ rc = rtas_call(cc_token, 2, 1, NULL, workarea, NULL);
+ }
+
+ spin_unlock(&workarea_lock);
+ return first_dn;
+
+cc_error:
+ spin_unlock(&workarea_lock);
+
+ if (first_dn)
+ free_cc_nodes(first_dn);
+
+ return NULL;
+}
+
+static struct device_node *derive_parent(const char *path)
+{
+ struct device_node *parent;
+ char parent_path[128];
+ int parent_path_len;
+
+ parent_path_len = strrchr(path, '/') - path + 1;
+ strlcpy(parent_path, path, parent_path_len);
+
+ parent = of_find_node_by_path(parent_path);
+
+ return parent;
+}
+
+static int add_one_node(struct device_node *dn)
+{
+ struct proc_dir_entry *ent;
+ int rc;
+
+ of_node_set_flag(dn, OF_DYNAMIC);
+ kref_init(&dn->kref);
+ dn->parent = derive_parent(dn->full_name);
+
+ rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ PSERIES_RECONFIG_ADD, dn);
+ if (rc == NOTIFY_BAD) {
+ printk(KERN_ERR "Failed to add device node %s\n",
+ dn->full_name);
+ return -ENOMEM; /* For now, safe to assume kmalloc failure */
+ }
+
+ of_attach_node(dn);
+
+#ifdef CONFIG_PROC_DEVICETREE
+ ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
+ if (ent)
+ proc_device_tree_add_node(dn, ent);
+#endif
+
+ of_node_put(dn->parent);
+ return 0;
+}
+
+int add_device_tree_nodes(struct device_node *dn)
+{
+ struct device_node *child = dn->child;
+ struct device_node *sibling = dn->sibling;
+ int rc;
+
+ dn->child = NULL;
+ dn->sibling = NULL;
+ dn->parent = NULL;
+
+ rc = add_one_node(dn);
+ if (rc)
+ return rc;
+
+ if (child) {
+ rc = add_device_tree_nodes(child);
+ if (rc)
+ return rc;
+ }
+
+ if (sibling)
+ rc = add_device_tree_nodes(sibling);
+
+ return rc;
+}
+
+static int remove_one_node(struct device_node *dn)
+{
+ struct device_node *parent = dn->parent;
+ struct property *prop = dn->properties;
+
+#ifdef CONFIG_PROC_DEVICETREE
+ while (prop) {
+ remove_proc_entry(prop->name, dn->pde);
+ prop = prop->next;
+ }
+
+ if (dn->pde)
+ remove_proc_entry(dn->pde->name, parent->pde);
+#endif
+
+ blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ PSERIES_RECONFIG_REMOVE, dn);
+ of_detach_node(dn);
+ of_node_put(dn); /* Must decrement the refcount */
+
+ return 0;
+}
+
+static int _remove_device_tree_nodes(struct device_node *dn)
+{
+ int rc;
+
+ if (dn->child) {
+ rc = _remove_device_tree_nodes(dn->child);
+ if (rc)
+ return rc;
+ }
+
+ if (dn->sibling) {
+ rc = _remove_device_tree_nodes(dn->sibling);
+ if (rc)
+ return rc;
+ }
+
+ rc = remove_one_node(dn);
+ return rc;
+}
+
+int remove_device_tree_nodes(struct device_node *dn)
+{
+ int rc;
+
+ if (dn->child) {
+ rc = _remove_device_tree_nodes(dn->child);
+ if (rc)
+ return rc;
+ }
+
+ rc = remove_one_node(dn);
+ return rc;
+}
+
+#define DR_ENTITY_SENSE 9003
+#define DR_ENTITY_PRESENT 1
+#define DR_ENTITY_UNUSABLE 2
+#define ALLOCATION_STATE 9003
+#define ALLOC_UNUSABLE 0
+#define ALLOC_USABLE 1
+#define ISOLATION_STATE 9001
+#define ISOLATE 0
+#define UNISOLATE 1
+
+int acquire_drc(u32 drc_index)
+{
+ int dr_status, rc;
+
+ rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status,
+ DR_ENTITY_SENSE, drc_index);
+ if (rc || dr_status != DR_ENTITY_UNUSABLE)
+ return -1;
+
+ rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE);
+ if (rc)
+ return rc;
+
+ rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
+ if (rc) {
+ rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
+ return rc;
+ }
+
+ return 0;
+}
+
+int release_drc(u32 drc_index)
+{
+ int dr_status, rc;
+
+ rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status,
+ DR_ENTITY_SENSE, drc_index);
+ if (rc || dr_status != DR_ENTITY_PRESENT)
+ return -1;
+
+ rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE);
+ if (rc)
+ return rc;
+
+ rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
+ if (rc) {
+ rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int pseries_dlpar_init(void)
+{
+ if (!machine_is(pseries))
+ return 0;
+
+ return 0;
+}
+device_initcall(pseries_dlpar_init);
Index: powerpc/arch/powerpc/platforms/pseries/Makefile
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pseries/Makefile 2009-10-28 15:20:38.000000000 -0500
+++ powerpc/arch/powerpc/platforms/pseries/Makefile 2009-10-28 15:21:38.000000000 -0500
@@ -8,7 +8,7 @@
obj-y := lpar.o hvCall.o nvram.o reconfig.o \
setup.o iommu.o ras.o rtasd.o \
- firmware.o power.o
+ firmware.o power.o dlpar.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
Index: powerpc/arch/powerpc/include/asm/pSeries_reconfig.h
===================================================================
--- powerpc.orig/arch/powerpc/include/asm/pSeries_reconfig.h 2009-10-28 15:20:38.000000000 -0500
+++ powerpc/arch/powerpc/include/asm/pSeries_reconfig.h 2009-10-28 15:21:38.000000000 -0500
@@ -17,6 +17,7 @@
#ifdef CONFIG_PPC_PSERIES
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
+extern struct blocking_notifier_head pSeries_reconfig_chain;
#else /* !CONFIG_PPC_PSERIES */
static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
Index: powerpc/arch/powerpc/platforms/pseries/reconfig.c
===================================================================
--- powerpc.orig/arch/powerpc/platforms/pseries/reconfig.c 2009-10-28 15:20:38.000000000 -0500
+++ powerpc/arch/powerpc/platforms/pseries/reconfig.c 2009-10-28 15:21:38.000000000 -0500
@@ -96,7 +96,7 @@
return parent;
}
-static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
+BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
^ permalink raw reply
* SPRN_SVR for MPC5121e?
From: Wolfram Sang @ 2009-10-28 15:23 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 736 bytes --]
Hiya,
my MPC5121e (Rev2) has PVR/SVR: 0x8086_2010/0x8018_0020 (as mentioned in the manual)
I would assume that Rev1 has something like 0x8018_0010 for SVR. Seeing this
code in the Denx NFC-driver seconds that:
+ rev = (mfspr(SPRN_SVR) >> 4) & 0xF;
+ if (rev != 2) {
+ printk(KERN_ERR DRV_NAME
+ ": SoC revision %u is not supported!\n", rev);
+ return -ENXIO;
+ }
Does someone here have a Rev1 and can ultimately confirm and/or supply the
complete PVR/SVR for Rev1? Couldn't find any hint neither in the manual nor in
the web.
Thanks,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
From: Benjamin Herrenschmidt @ 2009-10-28 21:37 UTC (permalink / raw)
To: Valentine; +Cc: olof, linuxppc-dev, paulus
In-Reply-To: <4AE8B761.3090902@ru.mvista.com>
On Thu, 2009-10-29 at 00:28 +0300, Valentine wrote:
> Benjamin Herrenschmidt wrote:
> > On Wed, 2009-10-28 at 22:19 +0300, Valentine wrote:
> >
> >> I'm just not sure that we need to clear HARDIRQEN here, since we don't
> >> really hard-disable the the interrupts.
> >
> > We do, or rather, we come in with the interrupts hard disabled, no ?
>
> Yes, looks like the interrupts are disabled at this point (before
> preempt_schedule_irq) most of the times, but we don't hard-disable them
> here. We just soft-disable them to make preempt_schedule_irq happy. Even
> if an interrupt fires, it will be hard-disabled and the hardirq flag
> will be cleared by the exception handler right away. I just think that
> there's no need to clear hardirq flag if we don't clear MSR_EE.
My point is that MSR_EE _is_ already clear... isn't it ? So either we
set it back, or we clear HARDIRQEN to reflect it. It will be re-enable
as soon as preempt_schedule_irq() calls local_irq_enable() which is soon
enough anyways.
Also that avoids perf interrupt sneaking in since those act as NMIs in
that regard and -will- get in even when soft disabled.
Cheers,
Ben.
> Thanks,
> Val.
> >
> > Ben.
> >
> >> Thanks,
> >> Val.
> >>
> >>> + TRACE_DISABLE_INTS
> >>> +
> >>> + /* Call the scheduler with soft IRQs off */
> >>> +1: bl .preempt_schedule_irq
> >>> +
> >>> + /* Hard-disable interrupts again (and update PACA) */
> >>> #ifdef CONFIG_PPC_BOOK3E
> >>> - wrteei 1
> >>> - bl .preempt_schedule
> >>> wrteei 0
> >>> #else
> >>> - ori r10,r10,MSR_EE
> >>> - mtmsrd r10,1 /* reenable interrupts */
> >>> - bl .preempt_schedule
> >>> mfmsr r10
> >>> - clrrdi r9,r1,THREAD_SHIFT
> >>> - rldicl r10,r10,48,1 /* disable interrupts again */
> >>> + rldicl r10,r10,48,1
> >>> rotldi r10,r10,16
> >>> mtmsrd r10,1
> >>> #endif /* CONFIG_PPC_BOOK3E */
> >>> + li r0,0
> >>> + stb r0,PACAHARDIRQEN(r13)
> >>> +
> >>> + /* Re-test flags and eventually loop */
> >>> + clrrdi r9,r1,THREAD_SHIFT
> >>> ld r4,TI_FLAGS(r9)
> >>> andi. r0,r4,_TIF_NEED_RESCHED
> >>> bne 1b
> >>> b restore
> >>>
> >>> user_work:
> >>> -#endif
> >>> +#endif /* CONFIG_PREEMPT */
> >>> +
> >>> /* Enable interrupts */
> >>> #ifdef CONFIG_PPC_BOOK3E
> >>> wrteei 1
> >
> >
^ permalink raw reply
* Re: [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
From: Benjamin Herrenschmidt @ 2009-10-28 20:30 UTC (permalink / raw)
To: Valentine; +Cc: olof, linuxppc-dev, paulus
In-Reply-To: <4AE89936.6080803@ru.mvista.com>
On Wed, 2009-10-28 at 22:19 +0300, Valentine wrote:
> I'm just not sure that we need to clear HARDIRQEN here, since we don't
> really hard-disable the the interrupts.
We do, or rather, we come in with the interrupts hard disabled, no ?
Ben.
> Thanks,
> Val.
>
> > + TRACE_DISABLE_INTS
> > +
> > + /* Call the scheduler with soft IRQs off */
> > +1: bl .preempt_schedule_irq
> > +
> > + /* Hard-disable interrupts again (and update PACA) */
> > #ifdef CONFIG_PPC_BOOK3E
> > - wrteei 1
> > - bl .preempt_schedule
> > wrteei 0
> > #else
> > - ori r10,r10,MSR_EE
> > - mtmsrd r10,1 /* reenable interrupts */
> > - bl .preempt_schedule
> > mfmsr r10
> > - clrrdi r9,r1,THREAD_SHIFT
> > - rldicl r10,r10,48,1 /* disable interrupts again */
> > + rldicl r10,r10,48,1
> > rotldi r10,r10,16
> > mtmsrd r10,1
> > #endif /* CONFIG_PPC_BOOK3E */
> > + li r0,0
> > + stb r0,PACAHARDIRQEN(r13)
> > +
> > + /* Re-test flags and eventually loop */
> > + clrrdi r9,r1,THREAD_SHIFT
> > ld r4,TI_FLAGS(r9)
> > andi. r0,r4,_TIF_NEED_RESCHED
> > bne 1b
> > b restore
> >
> > user_work:
> > -#endif
> > +#endif /* CONFIG_PREEMPT */
> > +
> > /* Enable interrupts */
> > #ifdef CONFIG_PPC_BOOK3E
> > wrteei 1
^ permalink raw reply
* Re: [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
From: Valentine @ 2009-10-28 19:19 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: olof, linuxppc-dev, paulus
In-Reply-To: <1256622077.11607.85.camel@pasglop>
Benjamin Herrenschmidt wrote:
>> So I _think_ that the irqs on/off accounting for lockdep isn't quite
>> right. What do you think of this slightly modified version ? I've only
>> done a quick boot test on a G5 with lockdep enabled and a played a bit,
>> nothing shows up so far but it's definitely not conclusive.
>>
>> The main difference is that I call trace_hardirqs_off to "advertise"
>> the fact that we are soft-disabling (it could be a dup, but at this
>> stage this is no big deal, but it's not always, like in syscall return
>> the kernel thinks we have interrupts enabled and could thus get out
>> of sync without that).
>>
>> I also mark the PACA hard disable to reflect the MSR:EE state before
>> calling into preempt_schedule_irq().
>
> Allright, second thought :-)
>
> It's probably simpler to just keep hardirqs off. Code is smaller and
> simpler and the scheduler will re-enable them soon enough anyways.
>
> This version of the patch also spaces the code a bit and adds comments
> which makes them (the code and the patch) more readable.
>
This one seems to work fine on pasemi and another maple-compatible board.
> Cheers,
> Ben.
>
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
>
> Based on an original patch by Valentine Barshak <vbarshak@ru.mvista.com>
>
> Use preempt_schedule_irq to prevent infinite irq-entry and
> eventual stack overflow problems with fast-paced IRQ sources.
>
> This kind of problems has been observed on the PASemi Electra IDE
> controller. We have to make sure we are soft-disabled before calling
> preempt_schedule_irq and hard disable interrupts after that
> to avoid unrecoverable exceptions.
>
> This patch also moves the "clrrdi r9,r1,THREAD_SHIFT" out of
> the #ifdef CONFIG_PPC_BOOK3E scope, since r9 is clobbered
> and has to be restored in both cases.
> ---
> arch/powerpc/kernel/entry_64.S | 41 ++++++++++++++++++++-------------------
> 1 files changed, 21 insertions(+), 20 deletions(-)
>
> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> index f9fd54b..9763267 100644
> --- a/arch/powerpc/kernel/entry_64.S
> +++ b/arch/powerpc/kernel/entry_64.S
> @@ -658,42 +658,43 @@ do_work:
> cmpdi r0,0
> crandc eq,cr1*4+eq,eq
> bne restore
> - /* here we are preempting the current task */
> -1:
> -#ifdef CONFIG_TRACE_IRQFLAGS
> - bl .trace_hardirqs_on
> - /* Note: we just clobbered r10 which used to contain the previous
> - * MSR before the hard-disabling done by the caller of do_work.
> - * We don't have that value anymore, but it doesn't matter as
> - * we will hard-enable unconditionally, we can just reload the
> - * current MSR into r10
> +
> + /* Here we are preempting the current task.
> + *
> + * Ensure interrupts are soft-disabled. We also properly mark
> + * the PACA to reflect the fact that they are hard-disabled
> + * and trace the change
> */
> - mfmsr r10
> -#endif /* CONFIG_TRACE_IRQFLAGS */
> - li r0,1
> + li r0,0
> stb r0,PACASOFTIRQEN(r13)
> stb r0,PACAHARDIRQEN(r13)
I'm just not sure that we need to clear HARDIRQEN here, since we don't
really hard-disable the the interrupts.
Thanks,
Val.
> + TRACE_DISABLE_INTS
> +
> + /* Call the scheduler with soft IRQs off */
> +1: bl .preempt_schedule_irq
> +
> + /* Hard-disable interrupts again (and update PACA) */
> #ifdef CONFIG_PPC_BOOK3E
> - wrteei 1
> - bl .preempt_schedule
> wrteei 0
> #else
> - ori r10,r10,MSR_EE
> - mtmsrd r10,1 /* reenable interrupts */
> - bl .preempt_schedule
> mfmsr r10
> - clrrdi r9,r1,THREAD_SHIFT
> - rldicl r10,r10,48,1 /* disable interrupts again */
> + rldicl r10,r10,48,1
> rotldi r10,r10,16
> mtmsrd r10,1
> #endif /* CONFIG_PPC_BOOK3E */
> + li r0,0
> + stb r0,PACAHARDIRQEN(r13)
> +
> + /* Re-test flags and eventually loop */
> + clrrdi r9,r1,THREAD_SHIFT
> ld r4,TI_FLAGS(r9)
> andi. r0,r4,_TIF_NEED_RESCHED
> bne 1b
> b restore
>
> user_work:
> -#endif
> +#endif /* CONFIG_PREEMPT */
> +
> /* Enable interrupts */
> #ifdef CONFIG_PPC_BOOK3E
> wrteei 1
^ permalink raw reply
* Re: [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
From: Valentine @ 2009-10-28 22:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: olof, linuxppc-dev, paulus
In-Reply-To: <1256765834.26770.6.camel@pasglop>
Benjamin Herrenschmidt wrote:
> On Thu, 2009-10-29 at 00:28 +0300, Valentine wrote:
>> Benjamin Herrenschmidt wrote:
>>> On Wed, 2009-10-28 at 22:19 +0300, Valentine wrote:
>>>
>>>> I'm just not sure that we need to clear HARDIRQEN here, since we don't
>>>> really hard-disable the the interrupts.
>>> We do, or rather, we come in with the interrupts hard disabled, no ?
>> Yes, looks like the interrupts are disabled at this point (before
>> preempt_schedule_irq) most of the times, but we don't hard-disable them
>> here. We just soft-disable them to make preempt_schedule_irq happy. Even
>> if an interrupt fires, it will be hard-disabled and the hardirq flag
>> will be cleared by the exception handler right away. I just think that
>> there's no need to clear hardirq flag if we don't clear MSR_EE.
>
> My point is that MSR_EE _is_ already clear... isn't it ?
Yes, the MSR_EE is cleared before we jump to do_work. I'm OK with
clearing the hardirqenable flag. I just assumed that the hardirq flag
was supposed to reflect the MSR_EE state, so it looked a bit odd
clearing the MSR_EE at one place and then reflecting the change at another.
Anyway, the patch works fine.
Thanks,
Val.
So either we
> set it back, or we clear HARDIRQEN to reflect it. It will be re-enable
> as soon as preempt_schedule_irq() calls local_irq_enable() which is soon
> enough anyways.
>
> Also that avoids perf interrupt sneaking in since those act as NMIs in
> that regard and -will- get in even when soft disabled.
>
> Cheers,
> Ben.
>
>> Thanks,
>> Val.
>>> Ben.
>>>
>>>> Thanks,
>>>> Val.
>>>>
>>>>> + TRACE_DISABLE_INTS
>>>>> +
>>>>> + /* Call the scheduler with soft IRQs off */
>>>>> +1: bl .preempt_schedule_irq
>>>>> +
>>>>> + /* Hard-disable interrupts again (and update PACA) */
>>>>> #ifdef CONFIG_PPC_BOOK3E
>>>>> - wrteei 1
>>>>> - bl .preempt_schedule
>>>>> wrteei 0
>>>>> #else
>>>>> - ori r10,r10,MSR_EE
>>>>> - mtmsrd r10,1 /* reenable interrupts */
>>>>> - bl .preempt_schedule
>>>>> mfmsr r10
>>>>> - clrrdi r9,r1,THREAD_SHIFT
>>>>> - rldicl r10,r10,48,1 /* disable interrupts again */
>>>>> + rldicl r10,r10,48,1
>>>>> rotldi r10,r10,16
>>>>> mtmsrd r10,1
>>>>> #endif /* CONFIG_PPC_BOOK3E */
>>>>> + li r0,0
>>>>> + stb r0,PACAHARDIRQEN(r13)
>>>>> +
>>>>> + /* Re-test flags and eventually loop */
>>>>> + clrrdi r9,r1,THREAD_SHIFT
>>>>> ld r4,TI_FLAGS(r9)
>>>>> andi. r0,r4,_TIF_NEED_RESCHED
>>>>> bne 1b
>>>>> b restore
>>>>>
>>>>> user_work:
>>>>> -#endif
>>>>> +#endif /* CONFIG_PREEMPT */
>>>>> +
>>>>> /* Enable interrupts */
>>>>> #ifdef CONFIG_PPC_BOOK3E
>>>>> wrteei 1
>>>
>
>
^ permalink raw reply
* Re: [PATCH v3] powerpc/ppc64: Use preempt_schedule_irq instead of preempt_schedule
From: Benjamin Herrenschmidt @ 2009-10-29 0:49 UTC (permalink / raw)
To: Valentine; +Cc: olof, linuxppc-dev, paulus
In-Reply-To: <4AE8CA95.7060402@ru.mvista.com>
> Yes, the MSR_EE is cleared before we jump to do_work. I'm OK with
> clearing the hardirqenable flag. I just assumed that the hardirq flag
> was supposed to reflect the MSR_EE state, so it looked a bit odd
> clearing the MSR_EE at one place and then reflecting the change at another.
Yeah well, it is supposed to reflect EE in the "general case", it's just
that in the exception entry/exit, we take shortcuts when turning EE off
for short amount of times without reflecting it in the PACA. This is
why, in this case, since we are going back to C code, I want to have it
"fixed up" to reflect reality.
Cheers,
Ben.
> Anyway, the patch works fine.
>
> Thanks,
> Val.
>
> So either we
> > set it back, or we clear HARDIRQEN to reflect it. It will be re-enable
> > as soon as preempt_schedule_irq() calls local_irq_enable() which is soon
> > enough anyways.
> >
> > Also that avoids perf interrupt sneaking in since those act as NMIs in
> > that regard and -will- get in even when soft disabled.
> >
> > Cheers,
> > Ben.
> >
> >> Thanks,
> >> Val.
> >>> Ben.
> >>>
> >>>> Thanks,
> >>>> Val.
> >>>>
> >>>>> + TRACE_DISABLE_INTS
> >>>>> +
> >>>>> + /* Call the scheduler with soft IRQs off */
> >>>>> +1: bl .preempt_schedule_irq
> >>>>> +
> >>>>> + /* Hard-disable interrupts again (and update PACA) */
> >>>>> #ifdef CONFIG_PPC_BOOK3E
> >>>>> - wrteei 1
> >>>>> - bl .preempt_schedule
> >>>>> wrteei 0
> >>>>> #else
> >>>>> - ori r10,r10,MSR_EE
> >>>>> - mtmsrd r10,1 /* reenable interrupts */
> >>>>> - bl .preempt_schedule
> >>>>> mfmsr r10
> >>>>> - clrrdi r9,r1,THREAD_SHIFT
> >>>>> - rldicl r10,r10,48,1 /* disable interrupts again */
> >>>>> + rldicl r10,r10,48,1
> >>>>> rotldi r10,r10,16
> >>>>> mtmsrd r10,1
> >>>>> #endif /* CONFIG_PPC_BOOK3E */
> >>>>> + li r0,0
> >>>>> + stb r0,PACAHARDIRQEN(r13)
> >>>>> +
> >>>>> + /* Re-test flags and eventually loop */
> >>>>> + clrrdi r9,r1,THREAD_SHIFT
> >>>>> ld r4,TI_FLAGS(r9)
> >>>>> andi. r0,r4,_TIF_NEED_RESCHED
> >>>>> bne 1b
> >>>>> b restore
> >>>>>
> >>>>> user_work:
> >>>>> -#endif
> >>>>> +#endif /* CONFIG_PREEMPT */
> >>>>> +
> >>>>> /* Enable interrupts */
> >>>>> #ifdef CONFIG_PPC_BOOK3E
> >>>>> wrteei 1
> >>>
> >
> >
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox