LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH V2 2/3] powerpc: Add support for swiotlb on 32-bit
From: Becky Bruce @ 2009-05-27 19:11 UTC (permalink / raw)
  To: Ian Campbell
  Cc: FUJITA Tomonori, linuxppc-dev@ozlabs.org, Jeremy Fitzhardinge,
	linux-kernel@vger.kernel.org
In-Reply-To: <1243342307.9295.86.camel@zakaz.uk.xensource.com>


On May 26, 2009, at 7:51 AM, Ian Campbell wrote:

> On Fri, 2009-05-22 at 19:55 -0400, Jeremy Fitzhardinge wrote:
>> Ian Campbell wrote:
>>> On Thu, 2009-05-21 at 14:27 -0400, Becky Bruce wrote:
>>>
>>>> I can work with that, but it's going to be a bit inefficient, as I
>>>> actually need the dma_addr_t, not the phys_addr_t, so I'll have to
>>>> convert.  In every case, this is a conversion I've already done and
>>>> that I need in the calling code as well.
>>>>
>>>
>>> Does
>>>
>>>    dma_addr_t dma_map_range(struct device *hwdev, phys_addr_t addr,
>>>    size_t size);
>>>
>>> work for you?
>>>
>>> If the range does not need mapping then it returns the dma  
>>> address, if
>>> you needed to calculate the dma address anyway to figure out if  
>>> mapping
>>> is required then this is fine. If the range does need mapping then  
>>> it
>>> returns NULL.
>>>
>>
>> My only concern is whether dma_addr_t == 0 is actually equivalent to
>> NULL.  That is, can we be sure that address 0 will never be used?
>
> It seems not, ~0UL might have been an option, but...
>
>> Taking dma_alloc_coherent as a model, we could have something like:
>>
>>    int dma_map_range(struct device *hwdev, phys_addr_t addr, size_t  
>> size, dma_addr_t *dma_addrp);
>>
>>
>> where *dma_addrp is set if the function returns success (bool return
>> type might be clearer).
>
> ... this sounds like a good idea to me.

I agree.  This will work for me as well.

-becky

^ permalink raw reply

* Re: [PATCH V2 2/3] powerpc: Add support for swiotlb on 32-bit
From: Becky Bruce @ 2009-05-27 19:05 UTC (permalink / raw)
  To: FUJITA Tomonori; +Cc: linuxppc-dev, jeremy, linux-kernel, Ian.Campbell
In-Reply-To: <20090522194930E.fujita.tomonori@lab.ntt.co.jp>


On May 22, 2009, at 5:51 AM, FUJITA Tomonori wrote:

> On Thu, 21 May 2009 13:18:54 -0700
> Jeremy Fitzhardinge <jeremy@goop.org> wrote:
>
>> Becky Bruce wrote:
>>> I can work with that, but it's going to be a bit inefficient, as I
>>> actually need the dma_addr_t, not the phys_addr_t, so I'll have to
>>> convert.  In every case, this is a conversion I've already done and
>>> that I need in the calling code as well.  Can we pass in both the
>>> phys_addr_t and the dma_addr_t?
>>
>> The Xen implementation would needs to do the phys to bus conversion  
>> page
>> by page anyway, so it wouldn't help much.  But it also wouldn't hurt.
>>
>> How expensive is the phys-to-bus conversion on power?  Is it worth
>> making the interface more complex for?  Would passing phys+bus mean  
>> that
>> we wouldn't also need to pass dev?
>
> I don't think so. POWERPC needs it.

Hrm, it looks like my response to this got dropped.  Fujita is correct  
- we still need the dev on powerpc because we use it to get device- 
specific information that is used to determining when we need to  
actually bounce.

Cheers,
B

^ permalink raw reply

* Re: [PATCH V2 2/3] powerpc: Add support for swiotlb on 32-bit
From: Becky Bruce @ 2009-05-27 19:05 UTC (permalink / raw)
  To: Ian Campbell
  Cc: FUJITA Tomonori, linuxppc-dev@ozlabs.org, Jeremy Fitzhardinge,
	linux-kernel@vger.kernel.org
In-Reply-To: <1242990702.22654.253.camel@zakaz.uk.xensource.com>


On May 22, 2009, at 6:11 AM, Ian Campbell wrote:
>
>
> BTW do you need swiotlb_bus_to_virt to be __weak or is the fact that  
> it
> is implemented in terms of swiotlb_bus_to_phys sufficient?

The default one in swiotlb calls phys_to_virt on the result of  
swiotlb_bus_to_phys, which only works on lowmem.

>
>
> I have an appointment all afternoon and it's a bank holiday on Monday
> but here is my WIP patch as an example of what I'm thinking. Obviously
> some cleanups are still very much required:
>      * The Xen specific stuff in arch/x86/include/asm/dma-mapping.h
>        clearly needs to be properly abstracted away (I just stuck it
>        there for testing).
>      * swiotlb_phys_to_bus and swiotlb_bus_to_phys need to move to
>        arch/*/include/asm/dma-mapping.h instead of being __weak
>      * Maybe swiotlb_bus_to_virt can become static again.
>      * Need to finish auditing the handful of non-swiotlb users of
>        is_buffer_dma_capable.
>      * It might be possible to implement swiolb_dma_mapping_error
>        and/or swiotlb_dma_supported in terms of dma_map_range.
>      * Minor detail: it doesn't actually work at the moment ;-)

Minor detail :)

I'm in the same boat- been offline most of the week and will continue  
to be offline (I'm sneaking in an hour here to read emails!!!!) until  
sometime next week.   I'm in the middle of a big lab construction and  
move project.  I'll take a look as soon as I can - thanks!

-Becky

>
>
> Ian.
>
> diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/ 
> asm/dma-mapping.h
> index 36c0009..026667f 100644
> --- a/arch/ia64/include/asm/dma-mapping.h
> +++ b/arch/ia64/include/asm/dma-mapping.h
> @@ -174,4 +174,12 @@ dma_cache_sync (struct device *dev, void  
> *vaddr, size_t size,
>
> #define dma_is_consistent(d, h)	(1)	/* all we do is coherent  
> memory... */
>
> +static inline dma_addr_t dma_map_range(struct device *dev, u64 mask,
> +				       phys_addr_t addr, size_t size)
> +{
> +	if (addr + size <= mask)
> +		return addr;
> +	return 0;
> +}
> +
> #endif /* _ASM_IA64_DMA_MAPPING_H */
> diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/ 
> asm/dma-mapping.h
> index 916cbb6..b2813ab 100644
> --- a/arch/x86/include/asm/dma-mapping.h
> +++ b/arch/x86/include/asm/dma-mapping.h
> @@ -309,4 +309,20 @@ static inline void dma_free_coherent(struct  
> device *dev, size_t size,
> 		ops->free_coherent(dev, size, vaddr, bus);
> }
>
> +static inline dma_addr_t dma_map_range(struct device *dev, u64 mask,
> +				       phys_addr_t addr, size_t size)
> +{
> +	dma_addr_t dma_addr;
> +#ifdef CONFIG_XEN
> +	extern int xen_range_needs_mapping(phys_addr_t paddr, size_t size);
> +	if (xen_pv_domain() && xen_range_needs_mapping(addr, size))
> +		return 0;
> +#endif
> +
> +	dma_addr = swiotlb_phys_to_bus(dev, addr);
> +	if (dma_addr + size <= mask)
> +		return 0;
> +	return dma_addr;
> +}
> +
> #endif
> diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
> index 2fffc22..c2b4196 100644
> --- a/arch/x86/kernel/pci-dma.c
> +++ b/arch/x86/kernel/pci-dma.c
> @@ -145,8 +145,8 @@ again:
> 	if (!page)
> 		return NULL;
>
> -	addr = page_to_phys(page);
> -	if (!is_buffer_dma_capable(dma_mask, addr, size)) {
> +	addr = dma_map_range(dev, dma_mask, page_to_phys(page), size);
> +	if (!(addr == 0)) {
> 		__free_pages(page, get_order(size));
>
> 		if (dma_mask < DMA_BIT_MASK(32) && !(flag & GFP_DMA)) {
> diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci- 
> gart_64.c
> index 1e8920d..6a55770 100644
> --- a/arch/x86/kernel/pci-gart_64.c
> +++ b/arch/x86/kernel/pci-gart_64.c
> @@ -191,13 +191,13 @@ static inline int
> need_iommu(struct device *dev, unsigned long addr, size_t size)
> {
> 	return force_iommu ||
> -		!is_buffer_dma_capable(*dev->dma_mask, addr, size);
> +		dma_map_range(dev, *dev->dma_mask, addr, size) == 0;
> }
>
> static inline int
> nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
> {
> -	return !is_buffer_dma_capable(*dev->dma_mask, addr, size);
> +	return dma_map_range(dev, *dev->dma_mask, addr, size) == 0;
> }
>
> /* Map a single continuous physical area into the IOMMU.
> diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
> index 71d412a..712ce59 100644
> --- a/arch/x86/kernel/pci-nommu.c
> +++ b/arch/x86/kernel/pci-nommu.c
> @@ -12,13 +12,13 @@
> #include <asm/dma.h>
>
> static int
> -check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t  
> size)
> +check_addr(char *name, struct device *hwdev, phys_addr_t phys,  
> size_t size)
> {
> -	if (hwdev && !is_buffer_dma_capable(*hwdev->dma_mask, bus, size)) {
> +	if (hwdev && dma_map_range(hwdev, *hwdev->dma_mask, phys, size) ==  
> 0) {
> 		if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
> 			printk(KERN_ERR
> 			    "nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
> -				name, (long long)bus, size,
> +				name, (long long)phys, size,
> 				(long long)*hwdev->dma_mask);
> 		return 0;
> 	}
> @@ -30,12 +30,12 @@ static dma_addr_t nommu_map_page(struct device  
> *dev, struct page *page,
> 				 enum dma_data_direction dir,
> 				 struct dma_attrs *attrs)
> {
> -	dma_addr_t bus = page_to_phys(page) + offset;
> +	phys_addr_t phys = page_to_phys(page) + offset;
> 	WARN_ON(size == 0);
> -	if (!check_addr("map_single", dev, bus, size))
> +	if (!check_addr("map_single", dev, phys, size))
> 		return bad_dma_address;
> 	flush_write_buffers();
> -	return bus;
> +	return phys;
> }
>
> /* Map a set of buffers described by scatterlist in streaming
> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> index 8083b6a..85dafa1 100644
> --- a/include/linux/dma-mapping.h
> +++ b/include/linux/dma-mapping.h
> @@ -96,11 +96,6 @@ static inline int is_device_dma_capable(struct  
> device *dev)
> 	return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
> }
>
> -static inline int is_buffer_dma_capable(u64 mask, dma_addr_t addr,  
> size_t size)
> -{
> -	return addr + size <= mask;
> -}
> -
> #ifdef CONFIG_HAS_DMA
> #include <asm/dma-mapping.h>
> #else
> diff --git a/lib/swiotlb.c b/lib/swiotlb.c
> index cec5f62..4fd5185 100644
> --- a/lib/swiotlb.c
> +++ b/lib/swiotlb.c
> @@ -147,17 +147,6 @@ void * __weak swiotlb_bus_to_virt(struct device  
> *hwdev, dma_addr_t address)
> 	return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
> }
>
> -int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
> -					       dma_addr_t addr, size_t size)
> -{
> -	return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
> -}
> -
> -int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr,  
> size_t size)
> -{
> -	return 0;
> -}
> -
> static void swiotlb_print_info(unsigned long bytes)
> {
> 	phys_addr_t pstart, pend;
> @@ -318,17 +307,6 @@ cleanup1:
> 	return -ENOMEM;
> }
>
> -static inline int
> -address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t  
> size)
> -{
> -	return swiotlb_arch_address_needs_mapping(hwdev, addr, size);
> -}
> -
> -static inline int range_needs_mapping(phys_addr_t paddr, size_t size)
> -{
> -	return swiotlb_force || swiotlb_arch_range_needs_mapping(paddr,  
> size);
> -}
> -
> static int is_swiotlb_buffer(char *addr)
> {
> 	return addr >= io_tlb_start && addr < io_tlb_end;
> @@ -555,18 +533,17 @@ void *
> swiotlb_alloc_coherent(struct device *hwdev, size_t size,
> 		       dma_addr_t *dma_handle, gfp_t flags)
> {
> -	dma_addr_t dev_addr;
> +	phys_addr_t phys;
> 	void *ret;
> 	int order = get_order(size);
> 	u64 dma_mask = DMA_BIT_MASK(32);
> +	dma_addr_t dma_addr;
>
> 	if (hwdev && hwdev->coherent_dma_mask)
> 		dma_mask = hwdev->coherent_dma_mask;
>
> 	ret = (void *)__get_free_pages(flags, order);
> -	if (ret &&
> -	    !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(hwdev,  
> ret),
> -				   size)) {
> +	if (ret && dma_map_range(hwdev, dma_mask, virt_to_phys(ret), size)  
> == 0) {
> 		/*
> 		 * The allocated memory isn't reachable by the device.
> 		 */
> @@ -585,19 +562,20 @@ swiotlb_alloc_coherent(struct device *hwdev,  
> size_t size,
> 	}
>
> 	memset(ret, 0, size);
> -	dev_addr = swiotlb_virt_to_bus(hwdev, ret);
> +	phys = virt_to_phys(ret);
>
> 	/* Confirm address can be DMA'd by device */
> -	if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
> -		printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
> +	dma_addr = dma_map_range(hwdev, dma_mask, phys, size);
> +	if (dma_addr == 0) {
> +		printk("hwdev DMA mask = 0x%016Lx, physical addr = 0x%016Lx\n",
> 		       (unsigned long long)dma_mask,
> -		       (unsigned long long)dev_addr);
> +		       (unsigned long long)phys);
>
> 		/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
> 		do_unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
> 		return NULL;
> 	}
> -	*dma_handle = dev_addr;
> +	*dma_handle = dma_addr;
> 	return ret;
> }
> EXPORT_SYMBOL(swiotlb_alloc_coherent);
> @@ -649,7 +627,7 @@ dma_addr_t swiotlb_map_page(struct device *dev,  
> struct page *page,
> 			    struct dma_attrs *attrs)
> {
> 	phys_addr_t phys = page_to_phys(page) + offset;
> -	dma_addr_t dev_addr = swiotlb_phys_to_bus(dev, phys);
> +	dma_addr_t dma_addr;
> 	void *map;
>
> 	BUG_ON(dir == DMA_NONE);
> @@ -658,9 +636,9 @@ dma_addr_t swiotlb_map_page(struct device *dev,  
> struct page *page,
> 	 * we can safely return the device addr and not worry about bounce
> 	 * buffering it.
> 	 */
> -	if (!address_needs_mapping(dev, dev_addr, size) &&
> -	    !range_needs_mapping(phys, size))
> -		return dev_addr;
> +	dma_addr = dma_map_range(dev, dma_get_mask(dev), phys, size);
> +	if (dma_addr && !swiotlb_force)
> +		return dma_addr;
>
> 	/*
> 	 * Oh well, have to allocate and map a bounce buffer.
> @@ -671,15 +649,14 @@ dma_addr_t swiotlb_map_page(struct device  
> *dev, struct page *page,
> 		map = io_tlb_overflow_buffer;
> 	}
>
> -	dev_addr = swiotlb_virt_to_bus(dev, map);
> -
> 	/*
> 	 * Ensure that the address returned is DMA'ble
> 	 */
> -	if (address_needs_mapping(dev, dev_addr, size))
> +	dma_addr = dma_map_range(dev, dma_get_mask(dev),  
> virt_to_phys(map), size);
> +	if (dma_addr == 0)
> 		panic("map_single: bounce buffer is not DMA'ble");
>
> -	return dev_addr;
> +	return dma_addr;
> }
> EXPORT_SYMBOL_GPL(swiotlb_map_page);
>
> @@ -820,10 +797,8 @@ swiotlb_map_sg_attrs(struct device *hwdev,  
> struct scatterlist *sgl, int nelems,
>
> 	for_each_sg(sgl, sg, nelems, i) {
> 		phys_addr_t paddr = sg_phys(sg);
> -		dma_addr_t dev_addr = swiotlb_phys_to_bus(hwdev, paddr);
> -
> -		if (range_needs_mapping(paddr, sg->length) ||
> -		    address_needs_mapping(hwdev, dev_addr, sg->length)) {
> +		dma_addr_t dma_addr = dma_map_range(hwdev, dma_get_mask(hwdev),  
> paddr, sg->length);
> +		if (dma_addr == 0 || swiotlb_force) {
> 			void *map = map_single(hwdev, sg_phys(sg),
> 					       sg->length, dir);
> 			if (!map) {
> @@ -835,9 +810,9 @@ swiotlb_map_sg_attrs(struct device *hwdev,  
> struct scatterlist *sgl, int nelems,
> 				sgl[0].dma_length = 0;
> 				return 0;
> 			}
> -			sg->dma_address = swiotlb_virt_to_bus(hwdev, map);
> -		} else
> -			sg->dma_address = dev_addr;
> +			dma_addr = dma_map_range(hwdev, dma_get_mask(hwdev),  
> virt_to_phys(map), sg->length);
> +		}
> +		sg->dma_address = dma_addr;
> 		sg->dma_length = sg->length;
> 	}
> 	return nelems;
>

^ permalink raw reply

* [PATCH v3] powerpc: add ioremap_early() for mapping IO regions before MMU_init()
From: Grant Likely @ 2009-05-27 18:55 UTC (permalink / raw)
  To: linuxppc-dev, benh, scottwood, galak

From: Grant Likely <grant.likely@secretlab.ca>

ioremap_early() is useful for things like mapping SoC internally registers
and early debug output because it allows mappings to devices to be setup
early in the boot process where they are needed.  It also give a
performance boost since BAT mapped registers don't get flushed out of
the TLB.

Without ioremap_early(), early mappings are set up in an ad-hoc manner
and they get lost when the MMU is set up.  Drivers then have to perform
hacky fixups to transition over to new mappings.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

new in v3:
- Rebased onto Ben's dma_alloc_coherent changes
- Fixed alignment to match region size

 arch/powerpc/include/asm/io.h                |    8 +
 arch/powerpc/kernel/setup_32.c               |    4 
 arch/powerpc/mm/init_32.c                    |    3 
 arch/powerpc/mm/mmu_decl.h                   |    7 +
 arch/powerpc/mm/pgtable_32.c                 |   12 +
 arch/powerpc/mm/ppc_mmu_32.c                 |  210 +++++++++++++++++++++++---
 arch/powerpc/platforms/52xx/mpc52xx_common.c |   13 ++
 arch/powerpc/sysdev/cpm_common.c             |    2 
 8 files changed, 228 insertions(+), 31 deletions(-)


diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 001f2f1..10183e2 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -624,6 +624,12 @@ static inline void iosync(void)
  *
  * * iounmap undoes such a mapping and can be hooked
  *
+ * * ioremap_early is for setting up mapping regions during early boot.  Useful
+ *   for console devices or mapping an entire region of SoC internal registers.
+ *   ioremap_early becomes usable at machine_init() time.  Care must be taken
+ *   when using this routine because it can consume limited resources like BAT
+ *   registers.
+ *
  * * __ioremap_at (and the pending __iounmap_at) are low level functions to
  *   create hand-made mappings for use only by the PCI code and cannot
  *   currently be hooked. Must be page aligned.
@@ -647,6 +653,8 @@ extern void __iomem *ioremap_flags(phys_addr_t address, unsigned long size,
 
 extern void iounmap(volatile void __iomem *addr);
 
+extern void __iomem *ioremap_early(phys_addr_t addr, unsigned long size);
+
 extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
 			       unsigned long flags);
 extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size,
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 9e1ca74..c1c0442 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -41,6 +41,7 @@
 #include <asm/mmu_context.h>
 
 #include "setup.h"
+#include "mm/mmu_decl.h"
 
 #define DBG(fmt...)
 
@@ -118,6 +119,9 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  */
 notrace void __init machine_init(unsigned long dt_ptr)
 {
+	/* Get ready to allocate IO virtual address regions */
+	ioremap_init();
+
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 3de6a0d..806c237 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -168,9 +168,6 @@ void __init MMU_init(void)
 		ppc_md.progress("MMU:mapin", 0x301);
 	mapin_ram();
 
-	/* Initialize early top-down ioremap allocator */
-	ioremap_bot = IOREMAP_TOP;
-
 	/* Map in I/O resources */
 	if (ppc_md.progress)
 		ppc_md.progress("MMU:setio", 0x302);
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index d1f9c62..6be30fe 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -86,11 +86,14 @@ struct tlbcam {
 
 extern void mapin_ram(void);
 extern int map_page(unsigned long va, phys_addr_t pa, int flags);
-extern void setbat(int index, unsigned long virt, phys_addr_t phys,
-		   unsigned int size, int flags);
+extern int setbat(unsigned long virt, phys_addr_t phys, unsigned int size,
+		  int flags);
+extern int loadbat(unsigned long virt, phys_addr_t phys, unsigned int size,
+		   int flags);
 extern void settlbcam(int index, unsigned long virt, phys_addr_t phys,
 		      unsigned int size, int flags, unsigned int pid);
 extern void invalidate_tlbcam_entry(int index);
+extern void ioremap_init(void); /* called by machine_init() */
 
 extern int __map_without_bats;
 extern unsigned long ioremap_base;
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 5422169..508fb91 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -51,8 +51,6 @@ extern char etext[], _stext[];
 #ifdef HAVE_BATS
 extern phys_addr_t v_mapped_by_bats(unsigned long va);
 extern unsigned long p_mapped_by_bats(phys_addr_t pa);
-void setbat(int index, unsigned long virt, phys_addr_t phys,
-	    unsigned int size, int flags);
 
 #else /* !HAVE_BATS */
 #define v_mapped_by_bats(x)	(0UL)
@@ -126,6 +124,16 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 	return ptepage;
 }
 
+/**
+ * ioremap_init - Initialize early top-down ioremap allocator
+ */
+void __init ioremap_init(void)
+{
+	if (ioremap_bot)
+		return;
+	ioremap_bot = IOREMAP_TOP;
+}
+
 void __iomem *
 ioremap(phys_addr_t addr, unsigned long size)
 {
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 2d2a87e..01acd2e 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -72,38 +72,41 @@ unsigned long p_mapped_by_bats(phys_addr_t pa)
 	return 0;
 }
 
+/**
+ * mmu_mapin_ram - Map as much of RAM as possible into kernel space using BATs
+ */
 unsigned long __init mmu_mapin_ram(void)
 {
 	unsigned long tot, bl, done;
-	unsigned long max_size = (256<<20);
+	int rc;
 
 	if (__map_without_bats) {
-		printk(KERN_DEBUG "RAM mapped without BATs\n");
+		pr_debug("RAM mapped without BATs\n");
 		return 0;
 	}
 
-	/* Set up BAT2 and if necessary BAT3 to cover RAM. */
-
-	/* Make sure we don't map a block larger than the
-	   smallest alignment of the physical address. */
+	/* Set up BATs to cover RAM. */
 	tot = total_lowmem;
-	for (bl = 128<<10; bl < max_size; bl <<= 1) {
-		if (bl * 2 > tot)
+	done = 0;
+	while (done < tot) {
+		/* determine the smallest block size need to map the region.
+		 * Don't use a BAT mapping if the remaining region is less
+		 * that 128k */
+		if (tot - done <= 128<<10)
 			break;
-	}
-
-	setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X);
-	done = (unsigned long)bat_addrs[2].limit - PAGE_OFFSET + 1;
-	if ((done < tot) && !bat_addrs[3].limit) {
-		/* use BAT3 to cover a bit more */
-		tot -= done;
-		for (bl = 128<<10; bl < max_size; bl <<= 1)
-			if (bl * 2 > tot)
+		for (bl = 128<<10; bl < (256<<20); bl <<= 1)
+			if ((bl * 2) > (tot - done))
 				break;
-		setbat(3, PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
-		done = (unsigned long)bat_addrs[3].limit - PAGE_OFFSET + 1;
+
+		/* Allocate the BAT and recalculate amount of RAM mapped */
+		rc = setbat(PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
+		if (rc < 0)
+			break;
+		done = (unsigned long)bat_addrs[rc].limit - PAGE_OFFSET + 1;
 	}
 
+	if (done == 0)
+		pr_crit("Weird; No BATs available for RAM.\n");
 	return done;
 }
 
@@ -112,12 +115,29 @@ unsigned long __init mmu_mapin_ram(void)
  * The parameters are not checked; in particular size must be a power
  * of 2 between 128k and 256M.
  */
-void __init setbat(int index, unsigned long virt, phys_addr_t phys,
-		   unsigned int size, int flags)
+int __init setbat(unsigned long virt, phys_addr_t phys,
+		  unsigned int size, int flags)
 {
 	unsigned int bl;
-	int wimgxpp;
-	struct ppc_bat *bat = BATS[index];
+	int wimgxpp, index, nr_bats;
+	struct ppc_bat *bat;
+
+	/* Find a free BAT
+	 *
+	 * Special case; Keep the first entry in reserve for mapping RAM.
+	 * Otherwise the too many other users can prevent RAM from getting
+	 * mapped at all with a BAT.
+	 */
+	index = (flags == PAGE_KERNEL_X) ? 0 : 1;
+	nr_bats = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
+	for (; index < nr_bats; index++) {
+		if ((BATS[index][0].batu == 0) && (BATS[index][1].batu == 0))
+			break;
+	}
+	if (index == nr_bats)
+		return -1;
+
+	bat = BATS[index];
 
 	if ((flags & _PAGE_NO_CACHE) ||
 	    (cpu_has_feature(CPU_FTR_NEED_COHERENT) == 0))
@@ -156,6 +176,150 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
 	bat_addrs[index].start = virt;
 	bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1;
 	bat_addrs[index].phys = phys;
+	return index;
+}
+
+/**
+ * loadbat - Set up and configure one of the I/D BAT register pairs.
+ * @virt - virtual address, 128k aligned
+ * @phys - physical address, 128k aligned
+ * @size - size of mapping
+ * @flags - region attribute flags
+ *
+ * Uses setbat() to allocate a BAT pair and immediately writes the
+ * configuration into the BAT registers (instead of waiting for load_up_mmu)
+ */
+int __init loadbat(unsigned long virt, phys_addr_t phys,
+		   unsigned int size, int flags)
+{
+	struct ppc_bat *bat;
+	int i;
+
+	i = setbat(virt, phys, size, flags);
+	if (i < 0)
+		return i;
+	bat = BATS[i];
+
+	/* BATs must be set with a switch statement because there is no way
+	 * to paramaterize mtspr/mfspr instructions.
+	 *
+	 * Note: BAT0 is not handled here because early boot code depends
+	 * on BAT0 for mapping first 16M of RAM.  setbat() keeps BAT0 in
+	 * reserve for mapping main memory anyway, so this is okay.
+	 */
+	switch (i) {
+	case 1:
+		mtspr(SPRN_IBAT1U, bat[0].batu);
+		mtspr(SPRN_IBAT1L, bat[0].batl);
+		mtspr(SPRN_DBAT1U, bat[1].batu);
+		mtspr(SPRN_DBAT1L, bat[1].batl);
+		break;
+	case 2:
+		mtspr(SPRN_IBAT2U, bat[0].batu);
+		mtspr(SPRN_IBAT2L, bat[0].batl);
+		mtspr(SPRN_DBAT2U, bat[1].batu);
+		mtspr(SPRN_DBAT2L, bat[1].batl);
+		break;
+	case 3:
+		mtspr(SPRN_IBAT3U, bat[0].batu);
+		mtspr(SPRN_IBAT3L, bat[0].batl);
+		mtspr(SPRN_DBAT3U, bat[1].batu);
+		mtspr(SPRN_DBAT3L, bat[1].batl);
+		break;
+	case 4:
+		mtspr(SPRN_IBAT4U, bat[0].batu);
+		mtspr(SPRN_IBAT4L, bat[0].batl);
+		mtspr(SPRN_DBAT4U, bat[1].batu);
+		mtspr(SPRN_DBAT4L, bat[1].batl);
+		break;
+	case 5:
+		mtspr(SPRN_IBAT5U, bat[0].batu);
+		mtspr(SPRN_IBAT5L, bat[0].batl);
+		mtspr(SPRN_DBAT5U, bat[1].batu);
+		mtspr(SPRN_DBAT5L, bat[1].batl);
+		break;
+	case 6:
+		mtspr(SPRN_IBAT6U, bat[0].batu);
+		mtspr(SPRN_IBAT6L, bat[0].batl);
+		mtspr(SPRN_DBAT6U, bat[1].batu);
+		mtspr(SPRN_DBAT6L, bat[1].batl);
+		break;
+	case 7:
+		mtspr(SPRN_IBAT7U, bat[0].batu);
+		mtspr(SPRN_IBAT7L, bat[0].batl);
+		mtspr(SPRN_DBAT7U, bat[1].batu);
+		mtspr(SPRN_DBAT7L, bat[1].batl);
+		break;
+	}
+
+	return i;
+}
+
+/**
+ * ioremap_early - Allow large persistant IO regions to be mapped early.
+ * @addr: physical address of region
+ * @size: size of region
+ *
+ * This routine uses setbat() to set up IO ranges before the MMU is
+ * fully configured.
+ *
+ * This routine can be called really early, before MMU_init() is called.  It
+ * is useful for setting up early debug output consoles and frequently
+ * accessed IO regions, like the internally memory mapped registers (IMMR)
+ * in an SoC.  Ranges mapped with this function persist even after MMU_init()
+ * is called and the MMU is turned on 'for real.'
+ *
+ * The region mapped is large (minimum size of 128k) and virtual mapping must
+ * be aligned against this boundary.  Therefore, to avoid fragmentation all
+ * calls to ioremap_early() are best made before any calls to ioremap
+ * for smaller regions.
+ */
+void __iomem * __init
+ioremap_early(phys_addr_t addr, unsigned long size)
+{
+	unsigned long v, p, bl;
+	int i;
+
+	/* Be loud and annoying if someone calls this too late.
+	 * No need to crash the kernel though */
+	WARN_ON(mem_init_done);
+	if (mem_init_done)
+		return NULL;
+
+	/* Make sure request is sane */
+	if (size == 0)
+		return NULL;
+
+	/* If the region is already block mapped, then there is nothing
+	 * to do; just return the mapped address */
+	v = p_mapped_by_bats(addr);
+	if (v)
+		return (void __iomem *)v;
+
+	/* Align region size */
+	for (bl = 128<<10; bl < (256<<20); bl <<= 1) {
+		p = _ALIGN_DOWN(addr, bl); /* BATs align on 128k boundaries */
+		size = ALIGN(addr - p + size, bl);
+		if (bl >= size)
+			break;
+	}
+
+	/* Complain loudly if too much is requested */
+	if (bl >= (256<<20)) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/* Allocate the aligned virtual base address.  ALIGN_DOWN is used
+	 * to ensure no overlaps occur with normal 4k ioremaps. */
+	ioremap_bot = _ALIGN_DOWN(ioremap_bot, bl) - size;
+
+	/* Set up a BAT for this IO region */
+	i = loadbat(ioremap_bot, p, size, PAGE_KERNEL_NCG);
+	if (i < 0)
+		return NULL;
+
+	return (void __iomem *) (ioremap_bot + (addr - p));
 }
 
 /*
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 8e3dd5a..2c49148 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -146,7 +146,20 @@ static struct of_device_id mpc52xx_cdm_ids[] __initdata = {
 void __init
 mpc52xx_map_common_devices(void)
 {
+	const struct of_device_id immr_ids[] = {
+		{ .compatible = "fsl,mpc5200-immr", },
+		{ .compatible = "fsl,mpc5200b-immr", },
+		{ .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
+		{ .type = "builtin", .compatible = "mpc5200", }, /* efika */
+		{}
+	};
 	struct device_node *np;
+	struct resource res;
+
+	/* Pre-map the whole register space using a BAT entry */
+	np = of_find_matching_node(NULL, immr_ids);
+	if (np && (of_address_to_resource(np, 0, &res) == 0))
+		ioremap_early(res.start, res.end - res.start + 1);
 
 	/* mpc52xx_wdt is mapped here and used in mpc52xx_restart,
 	 * possibly from a interrupt context. wdt is only implement
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index e4b6d66..370723e 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -56,7 +56,7 @@ void __init udbg_init_cpm(void)
 {
 	if (cpm_udbg_txdesc) {
 #ifdef CONFIG_CPM2
-		setbat(1, 0xf0000000, 0xf0000000, 1024*1024, PAGE_KERNEL_NCG);
+		setbat(0xf0000000, 0xf0000000, 1024*1024, PAGE_KERNEL_NCG);
 #endif
 		udbg_putc = udbg_putc_cpm;
 	}

^ permalink raw reply related

* [PATCH] v2: Display processor virtualization resource allocations in lparcfg
From: Nathan Fontenot @ 2009-05-27 14:41 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <4A1C2E10.9020109@austin.ibm.com>

This patch updates the output from /proc/ppc64/lparcfg to display the
processor virtualization resource allocations for a shared processor
partition.

This information is already gathered via the h_get_ppp call, we just
have to make sure that the ibm,partition-performance-parameters-level
property is >= 1 to ensure that the information is valid.

Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---

Index: linux-2.6/arch/powerpc/kernel/lparcfg.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/lparcfg.c	2009-05-21 10:24:57.000000000 -0500
+++ linux-2.6/arch/powerpc/kernel/lparcfg.c	2009-05-27 08:27:34.000000000 -0500
@@ -169,6 +169,9 @@
 	u8	unallocated_weight;
 	u16	active_procs_in_pool;
 	u16	active_system_procs;
+	u16	phys_platform_procs;
+	u32	max_proc_cap_avail;
+	u32	entitled_proc_cap_avail;
 };
 
 /*
@@ -190,13 +193,18 @@
  *            XX - Unallocated Variable Processor Capacity Weight.
  *              XXXX - Active processors in Physical Processor Pool.
  *                  XXXX  - Processors active on platform.
+ *  R8 (QQQQRRRRRRSSSSSS). if ibm,partition-performance-parameters-level >= 1
+ *	XXXX - Physical platform procs allocated to virtualization.
+ *	    XXXXXX - Max procs capacity % available to the partitions pool.
+ *	          XXXXXX - Entitled procs capacity % available to the
+ *			   partitions pool.
  */
 static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
 {
 	unsigned long rc;
-	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
 
-	rc = plpar_hcall(H_GET_PPP, retbuf);
+	rc = plpar_hcall9(H_GET_PPP, retbuf);
 
 	ppp_data->entitlement = retbuf[0];
 	ppp_data->unallocated_entitlement = retbuf[1];
@@ -210,6 +218,10 @@
 	ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff;
 	ppp_data->active_system_procs = retbuf[3] & 0xffff;
 
+	ppp_data->phys_platform_procs = retbuf[4] >> 6 * 8;
+	ppp_data->max_proc_cap_avail = (retbuf[4] >> 3 * 8) & 0xffffff;
+	ppp_data->entitled_proc_cap_avail = retbuf[4] & 0xffffff;
+
 	return rc;
 }
 
@@ -234,6 +246,8 @@
 static void parse_ppp_data(struct seq_file *m)
 {
 	struct hvcall_ppp_data ppp_data;
+	struct device_node *root;
+	const int *perf_level;
 	int rc;
 
 	rc = h_get_ppp(&ppp_data);
@@ -267,6 +281,28 @@
 	seq_printf(m, "capped=%d\n", ppp_data.capped);
 	seq_printf(m, "unallocated_capacity=%lld\n",
 		   ppp_data.unallocated_entitlement);
+
+	/* The last bits of information returned from h_get_ppp are only
+	 * valid if the ibm,partition-performance-parameters-level
+	 * property is >= 1.
+	 */
+	root = of_find_node_by_path("/");
+	if (root) {
+		perf_level = of_get_property(root,
+				"ibm,partition-performance-parameters-level",
+					     NULL);
+		if (perf_level && (*perf_level >= 1)) {
+			seq_printf(m,
+			    "physical_procs_allocated_to_virtualization=%d\n",
+				   ppp_data.phys_platform_procs);
+			seq_printf(m, "max_proc_capacity_available=%d\n",
+				   ppp_data.max_proc_cap_avail);
+			seq_printf(m, "entitled_proc_capacity_available=%d\n",
+				   ppp_data.entitled_proc_cap_avail);
+		}
+
+		of_node_put(root);
+	}
 }
 
 /**

^ permalink raw reply

* Re: [PATCH] Display processor virtualization resource allocations in lparcfg
From: Nathan Fontenot @ 2009-05-27 14:30 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev
In-Reply-To: <1243386862.18971.41.camel@concordia>

Michael Ellerman wrote:
>> +	root = of_find_node_by_path("/");
>> +	if (root) {
>> +		perf_level = of_get_property(root,
>> +				"ibm,partition-performance-parameters-level",
>> +					     NULL);
> 
> What if there is no such property?

Yes, that would cause this code to do some bad things.  Updated patch on its way.

> 
>> +		if (*perf_level >= 1) {
>> +			seq_printf(m,
>> +			    "physical_procs_allocated_to_virtualization=%d\n",
>> +				   ppp_data.phys_platform_procs);
>> +			seq_printf(m, "max_proc_capacity_available=%d\n",
>> +				   ppp_data.max_proc_cap_avail);
>> +			seq_printf(m, "entitled_proc_capacity_available=%d\n",
>> +				   ppp_data.entitled_proc_cap_avail);
>> +		}
>> +
>> +		of_node_put(root);
>> +	}
> 
> cheers

-Nathan

^ permalink raw reply

* Re: [alsa-devel] [PATCH V2] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Timur Tabi @ 2009-05-27 11:39 UTC (permalink / raw)
  To: Jon Smirl; +Cc: linuxppc-dev, alsa-devel, broonie
In-Reply-To: <20090527043018.4667.94590.stgit@terra>

On Tue, May 26, 2009 at 11:30 PM, Jon Smirl <jonsmirl@gmail.com> wrote:
> The function signature for spin_event_timeout() has changed in version V9.
> Adjust the mpc5200 AC97 driver to use the new function.
> v2 - switch back to udelay() for fixed timeouts.
>
> Signed-off-by: Jon Smirl <jonsmirl@gmail.com>

Acked-by: Timur Tabi <timur@freescale.com>

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: Net: ucc_geth ethernet driver optimization space
From: Li Yang @ 2009-05-27 10:36 UTC (permalink / raw)
  To: Liu Dave-R63238; +Cc: netdev, linux-kernel, linuxppc-dev
In-Reply-To: <D7CCA83BB0796C49BC0BB53B6AB1208934920A@zch01exm21.fsl.freescale.net>

On Wed, May 27, 2009 at 1:08 PM, Liu Dave-R63238 <DaveLiu@freescale.com> wr=
ote:
> Guys,
>
> The ucc_geth ethernet driver have dozens of strong sync read/write
> operation, such as in_be32/16/8, out_be32/16/8.
>
> all of them is sync read/write, it is very expensive for performance.
>

Totally agree.  That's one of my concerns right from the beginning.

> For the critical patch, we can remove some unnecessary in_be(x),
> out_be(x) with normal memory operation, and keep some necessary
> memory barrier.
>
> eg: BD access in the interrupt handler and start_xmit.
>
> The BD operation only need the memory barrier between length/buffer
> and status.
>
> struct buffer descriptor {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0u16 status;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0u16 length;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0u32 buffer;
> } __attribute__ ((packed));
>
> struct buffer descriptor *BD;
>
> BD->length =3D xxxx;
> BD->buffer =3D yyyy;
> wmb();
> BD->status =3D zzzz;

The BD can reside either in memory or memory mapped region, which
makes the case more complex.

MMIO accesses need to use IO accessors for the sparse checking.  We
might make use of the __raw_*() accessors, but I'm not sure if it's
suitable for non-PCI buses on powerpc.  And also we need to pay
special attention to the problem described here:
http://lwn.net/Articles/198988/

- Leo

^ permalink raw reply

* Re: [GIT PULL] fsldma driver fixes
From: Li Yang @ 2009-05-27  8:24 UTC (permalink / raw)
  To: Dan Williams; +Cc: linuxppc-dev Development, lkml, Ira Snyder
In-Reply-To: <e9c3a7c20905261659v5d785df3w646efd4cbba2e6dd@mail.gmail.com>

On Wed, May 27, 2009 at 7:59 AM, Dan Williams <dan.j.williams@intel.com> wr=
ote:
> On Fri, May 22, 2009 at 3:47 AM, Li Yang <leoli@freescale.com> wrote:
>> Hi Dan,
>>
>> Here are fixes for Freescale DMA engine driver.
>>
>> Thanks,
>> - Leo
>>
>>
>> The following changes since commit 5805977e63a36ad56594a623f3bd2bebcb7db=
233:
>> =C2=A0Linus Torvalds (1):
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0Merge branch 'for-linus' of git://git.kernel.=
org/.../jbarnes/drm-2.6
>>
>> are available in the git repository at:
>>
>> =C2=A0git://git.kernel.org/pub/scm/linux/kernel/git/leo/fsl-soc.git fsld=
ma
>>
>> Ira Snyder (4):
>> =C2=A0 =C2=A0 =C2=A0fsldma: fix "DMA halt timeout!" errors
>> =C2=A0 =C2=A0 =C2=A0fsldma: fix infinite loop on multi-descriptor DMA ch=
ain completion
>> =C2=A0 =C2=A0 =C2=A0fsldma: snooping is not enabled for last entry in de=
scriptor chain
>> =C2=A0 =C2=A0 =C2=A0fsldma: fix memory leak on error path in fsl_dma_pre=
p_memcpy()
>>
>> Li Yang (1):
>> =C2=A0 =C2=A0 =C2=A0fsldma: update mailling list address in MAINTAINERS
>>
>> Roel Kluin (1):
>> =C2=A0 =C2=A0 =C2=A0fsldma: fix check on potential fdev->chan[] overflow
>>
>
> Pulled, thanks. =C2=A0These all look like 2.6.30 candidates, right?

Yes, they are pure fixes.

- Leo

^ permalink raw reply

* Re: [U-Boot] [PATCH 1/2] 83xx: Replace CONFIG_MPC83XX with CONFIG_MPC83xx
From: Stefan Roese @ 2009-05-27  7:08 UTC (permalink / raw)
  To: u-boot; +Cc: linuxppc-dev, Wolfgang Denk, Peter Tyser
In-Reply-To: <20090526183834.76345105.kim.phillips@freescale.com>

On Wednesday 27 May 2009 01:38:34 Kim Phillips wrote:
> > > If others would prefer standardizing on uppercase, I can submit new
> > > patches for 85xx, 5xxx, 86xx, etc.  This would be still be inconsistent
> > > with Linux though, which is a bit annoying.
> >
> > It seems Linux uses 8?xx with very few exceptions (CONFIG_SND_VIA82XX*
> > and CONFIG_EDAC_MPC85XX), so let's do the same here.
>
> so linux is inconsistent too.
>
> I'm a fan of a more self-consistent CONFIG_MPC85XX_MDS over mixed-case
> names like linux' CONFIG_MPC85xx_MDS.
>
> I wonder if the linux ppc guys would accept a
> s/CONFIG_MPC8?xx/CONFIG_MPC8?XX/g rename patch for linux...

Just to add my 0.02$ as well, I prefer the lower case version CONFIG_8?xx. 
It's used for 4xx this way as well in Linux and U-Boot. Perhaps I'm just used 
to reading it this way...

Best regards,
Stefan

=====================================================================
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de
=====================================================================

^ permalink raw reply

* Re: Net: ucc_geth ethernet driver optimization space
From: Joakim Tjernlund @ 2009-05-27  6:49 UTC (permalink / raw)
  To: Liu Dave-R63238
  Cc: linuxppc-dev, netdev, linux-kernel,
	linuxppc-dev-bounces+joakim.tjernlund=transmode.se
In-Reply-To: <D7CCA83BB0796C49BC0BB53B6AB1208934920A@zch01exm21.fsl.freescale.net>



linuxppc-dev-bounces+joakim.tjernlund=transmode.se@ozlabs.org wrote on 27/05/2009 07:08:07:
>
> Guys,
>
> The ucc_geth ethernet driver have dozens of strong sync read/write
> operation, such as in_be32/16/8, out_be32/16/8.
>
> all of them is sync read/write, it is very expensive for performance.
>
> For the critical patch, we can remove some unnecessary in_be(x),
> out_be(x) with normal memory operation, and keep some necessary
> memory barrier.
>
> eg: BD access in the interrupt handler and start_xmit.
>
> The BD operation only need the memory barrier between length/buffer
> and status.
>
> struct buffer descriptor {
>    u16 status;
>    u16 length;
>    u32 buffer;
> } __attribute__ ((packed));
>
> struct buffer descriptor *BD;
>
> BD->length = xxxx;
> BD->buffer = yyyy;
> wmb();
> BD->status = zzzz;
>
> For powerpc, eieio is enough for 60x, mbar 1 is enough for e500.
> Of couse, also need the memory clobber to avoid the compiler
> reorder between them.
>
> Thanks, Dave

Yes, pretty please :)

You might want to combine status and length into one U32 though:
BD->buffer = yyyy;
wmb();
BD->stat_len = zzzz << 16 | xxxx;

  Jocke

^ permalink raw reply

* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2009-05-27  6:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list

Hi Linus

And here's the rest of the fixes I was talking about. Hopefully that
should bring back all non-coherent DMA platforms into proper working
conditions. It's a bit invasive so late in the process but it's been
reasonably well tested for a few days.

The following changes since commit cd86a536c81e9300d984327517548ca0652eebf9:
  Linus Torvalds (1):
        Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/.../tip/linux-2.6-tip

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge

Benjamin Herrenschmidt (4):
      Revert "powerpc: Rework dma-noncoherent to use generic vmalloc layer"
      powerpc: Move dma-noncoherent.c from arch/powerpc/lib to arch/powerpc/mm
      powerpc: Minor cleanups of kernel virt address space definitions
      powerpc: Fix up dma_alloc_coherent() on platforms without cache coherency.

 arch/powerpc/Kconfig                     |   12 +
 arch/powerpc/include/asm/dma-mapping.h   |    6 +-
 arch/powerpc/include/asm/fixmap.h        |    4 +-
 arch/powerpc/include/asm/pgtable-ppc32.h |   26 ++-
 arch/powerpc/kernel/dma.c                |    2 +-
 arch/powerpc/lib/Makefile                |    1 -
 arch/powerpc/lib/dma-noncoherent.c       |  237 ------------------
 arch/powerpc/mm/Makefile                 |    1 +
 arch/powerpc/mm/dma-noncoherent.c        |  400 ++++++++++++++++++++++++++++++
 arch/powerpc/mm/init_32.c                |    8 +-
 arch/powerpc/mm/mem.c                    |   17 ++
 arch/powerpc/mm/pgtable_32.c             |    2 -
 12 files changed, 463 insertions(+), 253 deletions(-)
 delete mode 100644 arch/powerpc/lib/dma-noncoherent.c
 create mode 100644 arch/powerpc/mm/dma-noncoherent.c

^ permalink raw reply

* Net: ucc_geth ethernet driver optimization space
From: Liu Dave-R63238 @ 2009-05-27  5:08 UTC (permalink / raw)
  To: netdev; +Cc: linuxppc-dev, linux-kernel

Guys,

The ucc_geth ethernet driver have dozens of strong sync read/write
operation, such as in_be32/16/8, out_be32/16/8.

all of them is sync read/write, it is very expensive for performance.

For the critical patch, we can remove some unnecessary in_be(x),
out_be(x) with normal memory operation, and keep some necessary
memory barrier.

eg: BD access in the interrupt handler and start_xmit.

The BD operation only need the memory barrier between length/buffer
and status.

struct buffer descriptor {
	u16 status;
	u16 length;
	u32 buffer;
} __attribute__ ((packed));

struct buffer descriptor *BD;

BD->length =3D xxxx;
BD->buffer =3D yyyy;
wmb();
BD->status =3D zzzz;

For powerpc, eieio is enough for 60x, mbar 1 is enough for e500.
Of couse, also need the memory clobber to avoid the compiler
reorder between them.

Thanks, Dave

^ permalink raw reply

* [PATCH V3] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Jon Smirl @ 2009-05-27  5:06 UTC (permalink / raw)
  To: grant.likely, linuxppc-dev, alsa-devel, broonie, timur

The function signature for spin_event_timeout() has changed in version V9.
Adjust the mpc5200 AC97 driver to use the new function.
v2 - switch back to udelay() for fixed timeouts.
v3 - forgot about driver being market broken, fix typo

Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
 sound/soc/fsl/mpc5200_psc_ac97.c |   30 ++++++++++++++----------------
 1 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 9f2df15..794a247 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -31,13 +31,13 @@ static struct psc_dma *psc_dma;
 
 static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
-	int rc;
+	int status;
 	unsigned int val;
 
 	/* Wait for command send status zero = ready */
-	spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
-				MPC52xx_PSC_SR_CMDSEND), 100, 0, rc);
-	if (rc == 0) {
+	status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
+				MPC52xx_PSC_SR_CMDSEND), 100, 0);
+	if (status == 0) {
 		pr_err("timeout on ac97 bus (rdy)\n");
 		return -ENODEV;
 	}
@@ -45,9 +45,9 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 	out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
 
 	/* Wait for the answer */
-	spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &
-				MPC52xx_PSC_SR_DATA_VAL), 100, 0, rc);
-	if (rc == 0) {
+	status = spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &
+				MPC52xx_PSC_SR_DATA_VAL), 100, 0);
+	if (status == 0) {
 		pr_err("timeout on ac97 read (val) %x\n",
 				in_be16(&psc_dma->psc_regs->sr_csr.status));
 		return -ENODEV;
@@ -66,12 +66,12 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 static void psc_ac97_write(struct snd_ac97 *ac97,
 				unsigned short reg, unsigned short val)
 {
-	int rc;
+	int status;
 
 	/* Wait for command status zero = ready */
-	spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
-				MPC52xx_PSC_SR_CMDSEND), 100, 0, rc);
-	if (rc == 0) {
+	status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
+				MPC52xx_PSC_SR_CMDSEND), 100, 0);
+	if (status == 0) {
 		pr_err("timeout on ac97 bus (write)\n");
 		return;
 	}
@@ -82,24 +82,22 @@ static void psc_ac97_write(struct snd_ac97 *ac97,
 
 static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
 {
-	int rc;
 	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
 
 	out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);
-	spin_event_timeout(0, 3, 0, rc);
+	udelay(3);
 	out_be32(&regs->sicr, psc_dma->sicr);
 }
 
 static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
 {
-	int rc;
 	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
 
 	/* Do a cold reset */
 	out_8(&regs->op1, MPC52xx_PSC_OP_RES);
-	spin_event_timeout(0, 10, 0, rc);
+	udelay(10);
 	out_8(&regs->op0, MPC52xx_PSC_OP_RES);
-	spin_event_timeout(0, 50, 0, rc);
+	udelay(50);
 	psc_ac97_warm_reset(ac97);
 }
 

^ permalink raw reply related

* Re: [PATCH] net/ucc_geth: allow to set mac address on running device
From: David Miller @ 2009-05-27  4:42 UTC (permalink / raw)
  To: kexin.hao; +Cc: linuxppc-dev, leoli, linux-kernel, netdev
In-Reply-To: <1243388936.13410.4.camel@kevin>

From: Kevin Hao <kexin.hao@windriver.com>
Date: Wed, 27 May 2009 09:48:56 +0800

> Inspired by the patch for 8139too (bda6a15a).
> 
> Currently we can't set mac address on a running ucc_geth device.
> But this is needed when you use this device as a bonding slave in
> bonding device in balance-alb mode. So add this feature for ucc_geth
> device.
> 
> Signed-off-by: Kevin Hao <kexin.hao@windriver.com>

I applied this patch already, there is no need to post it again.

^ permalink raw reply

* [PATCH V2] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Jon Smirl @ 2009-05-27  4:30 UTC (permalink / raw)
  To: grant.likely, linuxppc-dev, alsa-devel, broonie, timur

The function signature for spin_event_timeout() has changed in version V9.
Adjust the mpc5200 AC97 driver to use the new function.
v2 - switch back to udelay() for fixed timeouts.

Signed-off-by: Jon Smirl <jonsmirl@gmail.com>
---
 sound/soc/fsl/mpc5200_psc_ac97.c |   30 ++++++++++++++----------------
 1 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 9f2df15..4342b51 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -31,13 +31,13 @@ static struct psc_dma *psc_dma;
 
 static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
-	int rc;
+	int status;
 	unsigned int val;
 
 	/* Wait for command send status zero = ready */
-	spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
-				MPC52xx_PSC_SR_CMDSEND), 100, 0, rc);
-	if (rc == 0) {
+	status= spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
+				MPC52xx_PSC_SR_CMDSEND), 100, 0);
+	if (status == 0) {
 		pr_err("timeout on ac97 bus (rdy)\n");
 		return -ENODEV;
 	}
@@ -45,9 +45,9 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 	out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
 
 	/* Wait for the answer */
-	spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &
-				MPC52xx_PSC_SR_DATA_VAL), 100, 0, rc);
-	if (rc == 0) {
+	status = spin_event_timeout((in_be16(&psc_dma->psc_regs->sr_csr.status) &
+				MPC52xx_PSC_SR_DATA_VAL), 100, 0);
+	if (status == 0) {
 		pr_err("timeout on ac97 read (val) %x\n",
 				in_be16(&psc_dma->psc_regs->sr_csr.status));
 		return -ENODEV;
@@ -66,12 +66,12 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 static void psc_ac97_write(struct snd_ac97 *ac97,
 				unsigned short reg, unsigned short val)
 {
-	int rc;
+	int status;
 
 	/* Wait for command status zero = ready */
-	spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
-				MPC52xx_PSC_SR_CMDSEND), 100, 0, rc);
-	if (rc == 0) {
+	status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
+				MPC52xx_PSC_SR_CMDSEND), 100, 0);
+	if (status == 0) {
 		pr_err("timeout on ac97 bus (write)\n");
 		return;
 	}
@@ -82,24 +82,22 @@ static void psc_ac97_write(struct snd_ac97 *ac97,
 
 static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
 {
-	int rc;
 	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
 
 	out_be32(&regs->sicr, psc_dma->sicr | MPC52xx_PSC_SICR_AWR);
-	spin_event_timeout(0, 3, 0, rc);
+	udelay(3);
 	out_be32(&regs->sicr, psc_dma->sicr);
 }
 
 static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
 {
-	int rc;
 	struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
 
 	/* Do a cold reset */
 	out_8(&regs->op1, MPC52xx_PSC_OP_RES);
-	spin_event_timeout(0, 10, 0, rc);
+	udelay(10);
 	out_8(&regs->op0, MPC52xx_PSC_OP_RES);
-	spin_event_timeout(0, 50, 0, rc);
+	udelat(50);
 	psc_ac97_warm_reset(ac97);
 }
 

^ permalink raw reply related

* Re: [alsa-devel] [PATCH] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Grant Likely @ 2009-05-27  4:00 UTC (permalink / raw)
  To: Jon Smirl; +Cc: linuxppc-dev, alsa-devel, Timur Tabi, broonie
In-Reply-To: <fa686aa40905262048ma2d5e12s907c489974343280@mail.gmail.com>

On Tue, May 26, 2009 at 9:48 PM, Grant Likely <grant.likely@secretlab.ca> w=
rote:
> First, udelay just burns time, and if the delay is too large, then the
> it is wasting time that could be used for something else. =A0That being
> said, it needs to be balanced with the context switch overhead. =A0If
> the udelay() is less than double the context switch time, then the
> overhead is greater than the time spent spinning.

BTW, lmbench lat_ctx test case tells me that context switch latency is
measured somewhere around 30 to 60 us for user space processes
sleeping on a file descriptor.  That will be lower for kernel threads
since there is no syscall overhead to account for.

g.

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

^ permalink raw reply

* Re: [alsa-devel] [PATCH] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Grant Likely @ 2009-05-27  3:49 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev, alsa-devel, broonie
In-Reply-To: <ed82fe3e0905262012r58f8a750lab9cb1bf3b9a989@mail.gmail.com>

On Tue, May 26, 2009 at 9:12 PM, Timur Tabi <timur@freescale.com> wrote:
> On Tue, May 26, 2009 at 8:01 PM, Jon Smirl <jonsmirl@gmail.com> wrote:
>
>> Then why did you need to make your routine that calls cpu_relax()?
>
> That gets called only if delay =3D=3D 0. =A0udelay(0) is a no-op, so if t=
he
> caller specifies no delay, then I need to manually call cpu_relax().
>
>> I don't know what goes on in the guts of HMT_low() and cpu_relax(),
>> when you guys decide which one I should use let me know and I can
>> adjust the patch.
>
> Grant, I don't see any reason why "udelay(50)" is unacceptable.

It's not.  See my last email.

g.

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

^ permalink raw reply

* Re: [PATCH] net/ucc_geth: allow to set mac address on running device
From: David Miller @ 2009-05-27  3:49 UTC (permalink / raw)
  To: kexin.hao; +Cc: linuxppc-dev, leoli, linux-kernel, netdev
In-Reply-To: <1243388936.13410.4.camel@kevin>

From: Kevin Hao <kexin.hao@windriver.com>
Date: Wed, 27 May 2009 09:48:56 +0800

> Inspired by the patch for 8139too (bda6a15a).
> 
> Currently we can't set mac address on a running ucc_geth device.
> But this is needed when you use this device as a bonding slave in
> bonding device in balance-alb mode. So add this feature for ucc_geth
> device.
> 
> Signed-off-by: Kevin Hao <kexin.hao@windriver.com>

Applied to net-next-2.6, thanks.

^ permalink raw reply

* Re: [alsa-devel] [PATCH] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Grant Likely @ 2009-05-27  3:48 UTC (permalink / raw)
  To: Jon Smirl; +Cc: linuxppc-dev, alsa-devel, Timur Tabi, broonie
In-Reply-To: <9e4733910905261744j3589ace8wd427ef8a5998eccf@mail.gmail.com>

On Tue, May 26, 2009 at 6:44 PM, Jon Smirl <jonsmirl@gmail.com> wrote:
> On Tue, May 26, 2009 at 8:38 PM, Timur Tabi <timur@freescale.com> wrote:
>> On Tue, May 26, 2009 at 7:25 PM, Jon Smirl <jonsmirl@gmail.com> wrote:
>>
>>> - =A0 =A0 =A0 spin_event_timeout(0, 10, 0, rc);
>>> + =A0 =A0 =A0 spin_event_timeout(0, 10, 0);
>>> =A0 =A0 =A0 =A0out_8(&regs->op0, MPC52xx_PSC_OP_RES);
>>> - =A0 =A0 =A0 spin_event_timeout(0, 50, 0, rc);
>>> + =A0 =A0 =A0 spin_event_timeout(0, 50, 0);
>>
>> Jon, I'm still hoping you'll explain why you're not using udelay() here.
>
> Because Grant didn't want me doing udelay(50) just to delay things in
> order to give the AC97 controller time to initialize. Your function
> lets me loop on cpu_relax() for 50us.

No, you misunderstand.  My issue is that udelay is far too coarse
grained for what you want.  ie. If your are using udelay(1) in your
loop, and your event changes state in 1.01us, then you're still going
to burn a full 2us of time.  If you can loop over cpu_relax() instead,
then less time will get burned.

For a hard 50us delay, with no early exit condition, udelay() is the
correct function.

HOWEVER; I'm distrustful of *any* spins, and would rather see sleeps
instead of spins wherever possible.  There are two reasons for this:

First, udelay just burns time, and if the delay is too large, then the
it is wasting time that could be used for something else.  That being
said, it needs to be balanced with the context switch overhead.  If
the udelay() is less than double the context switch time, then the
overhead is greater than the time spent spinning.

Second, udelay() with IRQs disabled cause unbounded latencies.  Even
if it is less efficient, I'd rather see mutexes+msleep() than
spin_lock_irqsave()+udelay().  Of course, this only works in
non-atomic contexts.  If the code is atomic, then you have no choice.

There is no blanket rule here; but as the time delay requirement gets
larger, the greater the benefit to overall system responsiveness by
using sleep instead of delay.  I'm not going to make a hard statement
about how it should be done right now.  It's a fiddly area and it can
be tweaked after the driver is merged.

However, Timur is absolutely right.  A spin without an early exit
condition should simply be a udelay().

> I have to delay 50us because ALSA tries to access the hardware
> immediately after the function returns.

Does the code run in atomic context?

g.

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

^ permalink raw reply

* Re: [PATCH net] gianfar: fix babbling rx error event bug
From: David Miller @ 2009-05-27  3:48 UTC (permalink / raw)
  To: Xiaotian.Feng; +Cc: netdev, linux-kernel, linuxppc-dev
In-Reply-To: <1243389156-1668-1-git-send-email-Xiaotian.Feng@windriver.com>

From: Xiaotian Feng <Xiaotian.Feng@windriver.com>
Date: Wed, 27 May 2009 09:52:36 +0800

> Gianfar interrupt handler uses IEVENT_ERR_MASK to check and handle errors.
> Babbling RX error (IEVENT_BABR) should be included in IEVENT_ERROR_MASK.
> Otherwise if BABR is raised, it never gets handled nor cleared, and an
> interrupt storm results. This has been observed to happen on sending a
> burst of ethernet frames to a gianfar based board.
> 
> Signed-off-by: Xiaotian Feng <xiaotian.feng@windriver.com>

Patch applied, thanks.

^ permalink raw reply

* Re: [alsa-devel] [PATCH] Modify mpc5200 AC97 driver to use V9 of spin_event_timeout()
From: Timur Tabi @ 2009-05-27  3:12 UTC (permalink / raw)
  To: Jon Smirl; +Cc: linuxppc-dev, alsa-devel, broonie
In-Reply-To: <9e4733910905261801p130f50afie2c50d5723192d44@mail.gmail.com>

On Tue, May 26, 2009 at 8:01 PM, Jon Smirl <jonsmirl@gmail.com> wrote:

> Then why did you need to make your routine that calls cpu_relax()?

That gets called only if delay == 0.  udelay(0) is a no-op, so if the
caller specifies no delay, then I need to manually call cpu_relax().

> I don't know what goes on in the guts of HMT_low() and cpu_relax(),
> when you guys decide which one I should use let me know and I can
> adjust the patch.

Grant, I don't see any reason why "udelay(50)" is unacceptable.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* [PATCH] powerpc/85xx: add nor flash partitions for mpc8569mds
From: Kevin Hao @ 2009-05-27  2:05 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Haiying Wang

Add 4 partitions in nor flash. Also fix nor flash
bank width bug.

Signed-off-by: Kevin Hao <kexin.hao@windriver.com>
---
 arch/powerpc/boot/dts/mpc8569mds.dts |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts
index 39c2927..1f98990 100644
--- a/arch/powerpc/boot/dts/mpc8569mds.dts
+++ b/arch/powerpc/boot/dts/mpc8569mds.dts
@@ -70,8 +70,30 @@
 			#size-cells = <1>;
 			compatible = "cfi-flash";
 			reg = <0x0 0x0 0x02000000>;
-			bank-width = <2>;
+			bank-width = <1>;
 			device-width = <1>;
+			partition@0 {
+				label = "ramdisk";
+				reg = <0x00000000 0x01c00000>;
+			};
+			partition@1c00000 {
+				label = "kernel";
+				reg = <0x01c00000 0x002e0000>;
+			};
+			partiton@1ee0000 {
+				label = "dtb";
+				reg = <0x01ee0000 0x00020000>;
+			};
+			partition@1f00000 {
+				label = "firmware";
+				reg = <0x01f00000 0x00080000>;
+				read-only;
+			};
+			partition@1f80000 {
+				label = "u-boot";
+				reg = <0x01f80000 0x00080000>;
+				read-only;
+			};
 		};
 
 		bcsr@1,0 {
-- 
1.6.0.4.771.gef3b3

^ permalink raw reply related

* [PATCH net] gianfar: fix babbling rx error event bug
From: Xiaotian Feng @ 2009-05-27  1:52 UTC (permalink / raw)
  To: galak, davem, netdev; +Cc: linuxppc-dev, linux-kernel

Gianfar interrupt handler uses IEVENT_ERR_MASK to check and handle errors.
Babbling RX error (IEVENT_BABR) should be included in IEVENT_ERROR_MASK.
Otherwise if BABR is raised, it never gets handled nor cleared, and an
interrupt storm results. This has been observed to happen on sending a
burst of ethernet frames to a gianfar based board.

Signed-off-by: Xiaotian Feng <xiaotian.feng@windriver.com>
---
 drivers/net/gianfar.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 0642d52..cf35296 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -259,7 +259,7 @@ extern const char gfar_driver_version[];
 (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
  IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
  | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
- | IEVENT_MAG)
+ | IEVENT_MAG | IEVENT_BABR)
 
 #define IMASK_INIT_CLEAR	0x00000000
 #define IMASK_BABR              0x80000000
-- 
1.5.5.1

^ permalink raw reply related

* [PATCH] net/ucc_geth: allow to set mac address on running device
From: Kevin Hao @ 2009-05-27  1:48 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, leoli, netdev

Inspired by the patch for 8139too (bda6a15a).

Currently we can't set mac address on a running ucc_geth device.
But this is needed when you use this device as a bonding slave in
bonding device in balance-alb mode. So add this feature for ucc_geth
device.

Signed-off-by: Kevin Hao <kexin.hao@windriver.com>
---
 drivers/net/ucc_geth.c |   33 ++++++++++++++++++++++++++++++++-
 1 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 9dd16c9..3c595d7 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3339,6 +3339,37 @@ static void ucc_netpoll(struct net_device *dev)
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 
+static int ucc_geth_set_mac_addr(struct net_device *dev, void *p)
+{
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	/*
+	 * If device is not running, we will set mac addr register
+	 * when opening the device.
+	 */
+	if (!netif_running(dev))
+		return 0;
+
+	spin_lock_irq(&ugeth->lock);
+	init_mac_station_addr_regs(dev->dev_addr[0],
+				   dev->dev_addr[1],
+				   dev->dev_addr[2],
+				   dev->dev_addr[3],
+				   dev->dev_addr[4],
+				   dev->dev_addr[5],
+				   &ugeth->ug_regs->macstnaddr1,
+				   &ugeth->ug_regs->macstnaddr2);
+	spin_unlock_irq(&ugeth->lock);
+
+	return 0;
+}
+
 /* Called when something needs to use the ethernet device */
 /* Returns 0 for success. */
 static int ucc_geth_open(struct net_device *dev)
@@ -3515,7 +3546,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
 	.ndo_stop		= ucc_geth_close,
 	.ndo_start_xmit		= ucc_geth_start_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_set_mac_address	= ucc_geth_set_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_multicast_list	= ucc_geth_set_multi,
 	.ndo_tx_timeout		= ucc_geth_timeout,
-- 
1.6.0.4.771.gef3b3

^ permalink raw reply related


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