[PATCH] powerpc/mm: Fix hang accessing top of vmalloc space
On pSeries, we always force the IO space to be mapped using 4K pages even with a 64K base page size to cope with some limitations in the HV interface to some devices. However, the SLB miss handler code to discriminate between vmalloc and ioremap space uses a CPU feature section such that the code is nop'ed out when the processor support large pages non-cachable mappings. Thus, we end up always using the ioremap page size for vmalloc segments on such processors, causing a discrepency between the segment and the hash table, and thus a hang continously hashing the page. It works for the first segment of the vmalloc space since that segment is "bolted" in by C code correctly, and thankfully we almost never use the vmalloc space beyond the first segment, but the new percpu code made the bug happen. This fixes it by removing the feature section from the assembly, we now always do the comparison between vmalloc and ioremap. Signed-off-by; Benjamin Herrenschmidt --- Sachin, can you verify that works for you ? diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index bc44dc4..95ce355 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -72,19 +72,17 @@ _GLOBAL(slb_miss_kernel_load_vmemmap) 1: #endif /* CONFIG_SPARSEMEM_VMEMMAP */ - /* vmalloc/ioremap mapping encoding bits, the "li" instructions below -* will be patched by the kernel at boot + /* vmalloc mapping gets the encoding from the PACA as the mapping +* can be demoted from 64K -> 4K dynamically on some machines */ -BEGIN_FTR_SECTION - /* check whether this is in vmalloc or ioremap space */ clrldi r11,r10,48 cmpldi r11,(VMALLOC_SIZE >> 28) - 1 bgt 5f lhz r11,PACAVMALLOCSLLP(r13) b 6f 5: -END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) -_GLOBAL(slb_miss_kernel_load_io) + /* IO mapping */ + _GLOBAL(slb_miss_kernel_load_io) li r11,0 6: BEGIN_FTR_SECTION ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Serial console under current qemu?
Has anybody gotten a serial console to work under current qemu (ala the 0.11.0 release)? I've tried the 2.6.30 and 2.6.31.4 kernels, and in both cases both the bootloader and the kernel's boot messages write to the serial console just fine, but as soon as userspace tries to write to /dev/console the kernel panics with: ieee1394: raw1394: /dev/raw1394 device initialized mice: PS/2 mouse device common for all mice TCP cubic registered NET: Registered protocol family 17 VFS: Mounted root (squashfs filesystem) readonly on device 3:0. Freeing unused kernel memory: 168k init Type exit when done.Unable to handle kernel paging request for data at address 0x0084 Faulting instruction address: 0xc012dc9c Oops: Kernel access of bad area, sig: 11 [#1] PowerMac NIP: c012dc9c LR: c01467c0 CTR: c01467ac REGS: cf831be0 TRAP: 0300 Not tainted (2.6.31.4) MSR: 9032 CR: 42224022 XER: DAR: 0084, DSISR: 4000 TASK = cf82f8f0[1] 'init.sh' THREAD: cf83 GPR00: c01467c0 cf831c90 cf82f8f0 cf82f920 cf824e40 91a8bb6b GPR08: 0001 0001 c01467ac 90778e6b 100834dc 0127e698 1005b940 GPR16: 100859a0 1007d074 100429a4 c02dc614 c0281678 c02dc498 GPR24: 000a cf83 c0321e00 0005 0014 c0321e00 c02dc638 NIP [c012dc9c] tty_wakeup+0x14/0xa0 LR [c01467c0] uart_tasklet_action+0x14/0x24 Call Trace: [cf831c90] [c012dcbc] tty_wakeup+0x34/0xa0 (unreliable) [cf831ca0] [c01467c0] uart_tasklet_action+0x14/0x24 [cf831cb0] [c003123c] tasklet_action+0x80/0x104 [cf831cd0] [c0031368] __do_softirq+0xa8/0x120 [cf831d10] [c0006ea4] do_softirq+0x58/0x5c [cf831d20] [c00311b8] irq_exit+0x98/0x9c [cf831d30] [c0006f44] do_IRQ+0x9c/0xb4 [cf831d50] [c0012b60] ret_from_except+0x0/0x1c --- Exception: 501 at uart_start+0x24/0x38 LR = uart_start+0x20/0x38 [cf831e20] [c0148130] uart_write+0xc0/0xe4 [cf831e50] [c0130bc0] n_tty_write+0x1d4/0x430 [cf831eb0] [c012db30] tty_write+0x188/0x268 [cf831ef0] [c0082314] vfs_write+0xb4/0x188 [cf831f10] [c008287c] sys_write+0x4c/0x90 [cf831f40] [c0012494] ret_from_syscall+0x0/0x40 --- Exception: c01 at 0x48039f8c LR = 0x4804c4bc Instruction dump: 7c0803a6 4e800020 80010024 bba10014 38210020 7c0803a6 4bfffd24 9421fff0 7c0802a6 bfc10008 7c7f1b78 90010014 <80030084> 70090020 4082002c 387f00e0 Kernel panic - not syncing: Fatal exception in interrupt Call Trace: [cf831b10] [c0008d74] show_stack+0x4c/0x16c (unreliable) [cf831b50] [c002b600] panic+0x90/0x160 [cf831ba0] [c0010064] die+0x148/0x154 [cf831bc0] [c0015b34] bad_page_fault+0x90/0xd8 [cf831bd0] [c001294c] handle_page_fault+0x7c/0x80 --- Exception: 300 at tty_wakeup+0x14/0xa0 LR = uart_tasklet_action+0x14/0x24 [cf831c90] [c012dcbc] tty_wakeup+0x34/0xa0 (unreliable) [cf831ca0] [c01467c0] uart_tasklet_action+0x14/0x24 [cf831cb0] [c003123c] tasklet_action+0x80/0x104 [cf831cd0] [c0031368] __do_softirq+0xa8/0x120 [cf831d10] [c0006ea4] do_softirq+0x58/0x5c [cf831d20] [c00311b8] irq_exit+0x98/0x9c [cf831d30] [c0006f44] do_IRQ+0x9c/0xb4 [cf831d50] [c0012b60] ret_from_except+0x0/0x1c --- Exception: 501 at uart_start+0x24/0x38 LR = uart_start+0x20/0x38 [cf831e20] [c0148130] uart_write+0xc0/0xe4 [cf831e50] [c0130bc0] n_tty_write+0x1d4/0x430 [cf831eb0] [c012db30] tty_write+0x188/0x268 [cf831ef0] [c0082314] vfs_write+0xb4/0x188 [cf831f10] [c008287c] sys_write+0x4c/0x90 [cf831f40] [c0012494] ret_from_syscall+0x0/0x40 --- Exception: c01 at 0x48039f8c LR = 0x4804c4bc Rebooting in 1 seconds.. I've reproduced this with my Firmware Linux project (download http://impactlinux.com/fwl/downloads/binaries/system-image-powerpc.tar.bz2 , extract it, run "sed -i 's...@-hda @-hdc @' run-emulator.sh" because qemu's device tree layout changed betwee 0.10.0 and 0.11.0, and then ./run- emulator.sh). I've also reproduced it with debian's kernel .config and root filesystem image, details on that posted here: http://lists.gnu.org/archive/html/qemu-devel/2009-10/msg01056.html (Oddly, with debian's kernel .config -hda sets /dev/hda instead of /dev/hdc, I need to track down why so I can fix it in my project's .config.) The debian image boots fine with a graphics console, it's just trying to use the serial console that panics it. I don't know if this is a qemu device emulation issue, a kernel issue, or maybe something to do with the device tree qemu's openbios is feeding in at boot time? I'm stumped. Er... Help? Pretty please? Rob -- Latency is more important than throughput. It's that simple. - Linus Torvalds ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 2/8] bitmap: Introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
On Fri, Oct 09, 2009 at 04:41:00PM -0700, Andrew Morton wrote: > On Fri, 9 Oct 2009 17:29:15 +0900 > Akinobu Mita wrote: > > > 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 stolen from iommu helper. > > > > I changed the return value of bitmap_find_next_zero_area if there is > > no zero area. > > > > find_next_zero_area in iommu helper: returns -1 > > bitmap_find_next_zero_area: return >= bitmap size > > I'll plan to merge this patch into 2.6.32 so we can trickle all the > other patches into subsystems in an orderly fashion. Sounds good. > > +void bitmap_set(unsigned long *map, int i, int len) > > +{ > > + int end = i + len; > > + > > + while (i < end) { > > + __set_bit(i, map); > > + i++; > > + } > > +} > > This is really inefficient, isn't it? It's a pretty trivial matter to > romp through memory 32 or 64 bits at a time. OK. I'll do > > +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 = (index + align_mask) & ~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); > > This needs documentation, please. It appears that `size' is the size > of the bitmap and `nr' is the number of zeroed bits we're looking for, > but an inattentive programmer could get those reversed. > > Also the semantics of `align_mask' could benefit from spelling out. Is > the alignment with respect to memory boundaries or with respect to > `map' or with respect to map+start or what? OK. I will document it. And I plan to change bitmap_find_next_zero_area() to take the alignment instead of an align_mask as Roland said. > And why does align_mask exist at all? I was a bit surprised to see it > there. In which scenarios will it be non-zero? Because the users of iommu-helper and mlx4 need the alignment requirement for the zero area. arch/powerpc/kernel/iommu.c arch/x86/kernel/amd_iommu.c arch/x86/kernel/pci-gart_64.c drivers/net/mlx4/alloc.c ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [Cbe-oss-dev] [PATCH] spufs: Fix test in spufs_switch_log_read()
Roel, > Or can this test be removed? I'd prefer just to remove the test. Cheers, Jeremy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[Patch] powerpc: Fix memory leak in axon_msi.c
cppcheck found a memory leak in axon_msi, if dcr_base or dcr_len are zero, we have already allocated msic, so we should free it in the error path. Signed-off-by: Eric Sesterhenn Acked-by: Michael Ellerman --- linux/arch/powerpc/platforms/cell/axon_msi.c.orig 2009-10-12 14:48:26.0 +0200 +++ linux/arch/powerpc/platforms/cell/axon_msi.c2009-10-12 14:48:52.0 +0200 @@ -365,7 +365,7 @@ static int axon_msi_probe(struct of_devi printk(KERN_ERR "axon_msi: couldn't parse dcr properties on %s\n", dn->full_name); - goto out; + goto out_free_msic; } msic->dcr_host = dcr_map(dn, dcr_base, dcr_len); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] of/platform: Implement support for dev_pm_ops
On Mon, Oct 12, 2009 at 03:09:53PM -0700, Grant Likely wrote: > On Mon, Oct 12, 2009 at 8:50 AM, Anton Vorontsov > wrote: > > Linux power management subsystem supports vast amount of new PM > > callbacks that are crucial for proper suspend and hibernation support > > in drivers. > > > > This patch implements support for dev_pm_ops, preserving support > > for legacy callbacks. > > > > Signed-off-by: Anton Vorontsov > > Hmmm... I'm not very familiar with the PM callbacks, but change > doesn't look right to me. In particular, a lot of these new hooks > don't do anything remotely of_platform bus specific. For example, > of_platform_pm_prepare() checks if there is drv, drv->pm, and > drv->pm->prepare. If all are true, then it calls drv->pm->prepare(). > I see that the platform bus platform_pm_prepare() function is > absolutely identical. I haven't looked, but I wouldn't be surprised > if other busses do the same. > > I think these simple pm ops should be made library functions that > platform, of_platform and other simple busses can just populate their > pm ops structure with. Some hooks can be made as library functions, but some can't (for example that do of_plaform_driver->suspend(), as opposite to of_platform_driver->driver.suspend(), i.e. the legacy hooks). Also, if you look into PCI bus hooks, you'll see that these hooks aren't pure proxies for drivers, they do real work, so they won't like to reuse or share anything. For OF platfrom bus, we can share these functions with platform: of_platform_pm_suspend_noirq of_platform_pm_resume_noirq of_platform_pm_freeze_noirq of_platform_pm_thaw_noirq of_platform_pm_poweroff_noirq of_platform_pm_restore_noirq These we cannot share: of_platform_pm_suspend of_platform_pm_resume of_platform_pm_freeze of_platform_pm_thaw of_platform_pm_poweroff of_platform_pm_restore I agree that there is some room for improvements in general (e.g. merging platform and of_platform devices/drivers), but it's not as easy as you would like to think. Let's make it in a separate step that don't stop real features from being implemented (e.g. hibernate). For the six functions that we can reuse I can prepare a cleanup patch that we can merge via -mm, or it can just sit and collect needed acks and can be merged via any tree. But please, no cross-tree dependencies for the cruicial features. Thanks, -- Anton Vorontsov email: cbouatmai...@gmail.com irc://irc.freenode.net/bd2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] of/platform: Implement support for dev_pm_ops
On Mon, Oct 12, 2009 at 8:50 AM, Anton Vorontsov wrote: > Linux power management subsystem supports vast amount of new PM > callbacks that are crucial for proper suspend and hibernation support > in drivers. > > This patch implements support for dev_pm_ops, preserving support > for legacy callbacks. > > Signed-off-by: Anton Vorontsov Hmmm... I'm not very familiar with the PM callbacks, but change doesn't look right to me. In particular, a lot of these new hooks don't do anything remotely of_platform bus specific. For example, of_platform_pm_prepare() checks if there is drv, drv->pm, and drv->pm->prepare. If all are true, then it calls drv->pm->prepare(). I see that the platform bus platform_pm_prepare() function is absolutely identical. I haven't looked, but I wouldn't be surprised if other busses do the same. I think these simple pm ops should be made library functions that platform, of_platform and other simple busses can just populate their pm ops structure with. g. > --- > drivers/of/platform.c | 305 > ++--- > 1 files changed, 290 insertions(+), 15 deletions(-) > > diff --git a/drivers/of/platform.c b/drivers/of/platform.c > index 298de0f..d58ade1 100644 > --- a/drivers/of/platform.c > +++ b/drivers/of/platform.c > @@ -65,47 +65,322 @@ static int of_platform_device_remove(struct device *dev) > return 0; > } > > -static int of_platform_device_suspend(struct device *dev, pm_message_t state) > +static void of_platform_device_shutdown(struct device *dev) > { > struct of_device *of_dev = to_of_device(dev); > struct of_platform_driver *drv = to_of_platform_driver(dev->driver); > - int error = 0; > > - if (dev->driver && drv->suspend) > - error = drv->suspend(of_dev, state); > - return error; > + if (dev->driver && drv->shutdown) > + drv->shutdown(of_dev); > } > > -static int of_platform_device_resume(struct device * dev) > +#ifdef CONFIG_PM_SLEEP > + > +static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg) > { > struct of_device *of_dev = to_of_device(dev); > struct of_platform_driver *drv = to_of_platform_driver(dev->driver); > - int error = 0; > + int ret = 0; > > - if (dev->driver && drv->resume) > - error = drv->resume(of_dev); > - return error; > + if (dev->driver && drv->suspend) > + ret = drv->suspend(of_dev, mesg); > + return ret; > } > > -static void of_platform_device_shutdown(struct device *dev) > +static int of_platform_legacy_resume(struct device *dev) > { > struct of_device *of_dev = to_of_device(dev); > struct of_platform_driver *drv = to_of_platform_driver(dev->driver); > + int ret = 0; > > - if (dev->driver && drv->shutdown) > - drv->shutdown(of_dev); > + if (dev->driver && drv->resume) > + ret = drv->resume(of_dev); > + return ret; > +} > + > +static int of_platform_pm_prepare(struct device *dev) > +{ > + struct device_driver *drv = dev->driver; > + int ret = 0; > + > + if (drv && drv->pm && drv->pm->prepare) > + ret = drv->pm->prepare(dev); > + > + return ret; > +} > + > +static void of_platform_pm_complete(struct device *dev) > +{ > + struct device_driver *drv = dev->driver; > + > + if (drv && drv->pm && drv->pm->complete) > + drv->pm->complete(dev); > +} > + > +#ifdef CONFIG_SUSPEND > + > +static int of_platform_pm_suspend(struct device *dev) > +{ > + struct device_driver *drv = dev->driver; > + int ret = 0; > + > + if (!drv) > + return 0; > + > + if (drv->pm) { > + if (drv->pm->suspend) > + ret = drv->pm->suspend(dev); > + } else { > + ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND); > + } > + > + return ret; > } > > +static int of_platform_pm_suspend_noirq(struct device *dev) > +{ > + struct device_driver *drv = dev->driver; > + int ret = 0; > + > + if (!drv) > + return 0; > + > + if (drv->pm) { > + if (drv->pm->suspend_noirq) > + ret = drv->pm->suspend_noirq(dev); > + } > + > + return ret; > +} > + > +static int of_platform_pm_resume(struct device *dev) > +{ > + struct device_driver *drv = dev->driver; > + int ret = 0; > + > + if (!drv) > + return 0; > + > + if (drv->pm) { > + if (drv->pm->resume) > + ret = drv->pm->resume(dev); > + } else { > + ret = of_platform_legacy_resume(dev); > + } > + > + return ret; > +} > + > +static int of_platform_pm_resume_noirq(struct device *dev) > +{ > + struct device_driver *drv = dev->driver; > + int ret = 0; > + > + if (!drv) > + return 0; > + > + if (d
[PATCH 2/2][v4] powerpc: Make the CMM memory hotplug aware
The Collaborative Memory Manager (CMM) module allocates individual pages over time that are not migratable. On a long running system this can severely impact the ability to find enough pages to support a hotplug memory remove operation. This patch adds a memory isolation notifier and a memory hotplug notifier. The memory isolation notifier will return the number of pages found in the range specified. This is used to determine if all of the used pages in a pageblock are owned by the balloon (or other entities in the notifier chain). The hotplug notifier will free pages in the range which is to be removed. The priority of this hotplug notifier is low so that it will be called near last, this helps avoids removing loaned pages in operations that fail due to other handlers. CMM activity will be halted when hotplug remove operations are active and resume activity after a delay period to allow the hypervisor time to adjust. Signed-off-by: Robert Jennings --- Changes since v3: * Changed from atomic to mutex for hotplug state tracking. * Clarified documentation for the new module parameter description. Changes since v2: * None, resent with parent patch to keep them together. arch/powerpc/platforms/pseries/cmm.c | 221 ++- 1 file changed, 215 insertions(+), 6 deletions(-) Index: b/arch/powerpc/platforms/pseries/cmm.c === --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -38,19 +38,28 @@ #include #include #include +#include #include "plpar_wrappers.h" #define CMM_DRIVER_VERSION "1.0.0" #define CMM_DEFAULT_DELAY 1 +#define CMM_HOTPLUG_DELAY 5 #define CMM_DEBUG 0 #define CMM_DISABLE0 #define CMM_OOM_KB 1024 #define CMM_MIN_MEM_MB 256 #define KB2PAGES(_p) ((_p)>>(PAGE_SHIFT-10)) #define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10)) +/* + * The priority level tries to ensure that this notifier is called as + * late as possible to reduce thrashing in the shared memory pool. + */ +#define CMM_MEM_HOTPLUG_PRI1 +#define CMM_MEM_ISOLATE_PRI15 static unsigned int delay = CMM_DEFAULT_DELAY; +static unsigned int hotplug_delay = CMM_HOTPLUG_DELAY; static unsigned int oom_kb = CMM_OOM_KB; static unsigned int cmm_debug = CMM_DEBUG; static unsigned int cmm_disabled = CMM_DISABLE; @@ -65,6 +74,10 @@ MODULE_VERSION(CMM_DRIVER_VERSION); module_param_named(delay, delay, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(delay, "Delay (in seconds) between polls to query hypervisor paging requests. " "[Default=" __stringify(CMM_DEFAULT_DELAY) "]"); +module_param_named(hotplug_delay, hotplug_delay, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(delay, "Delay (in seconds) after memory hotplug remove " +"before loaning resumes. " +"[Default=" __stringify(CMM_HOTPLUG_DELAY) "]"); module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " "[Default=" __stringify(CMM_OOM_KB) "]"); @@ -92,6 +105,9 @@ static unsigned long oom_freed_pages; static struct cmm_page_array *cmm_page_list; static DEFINE_SPINLOCK(cmm_lock); +static DEFINE_MUTEX(hotplug_mutex); +static int hotplug_occurred; /* protected by the hotplug mutex */ + static struct task_struct *cmm_thread_ptr; /** @@ -110,6 +126,17 @@ static long cmm_alloc_pages(long nr) cmm_dbg("Begin request for %ld pages\n", nr); while (nr) { + /* Exit if a hotplug operation is in progress or occurred */ + if (mutex_trylock(&hotplug_mutex)) { + if (hotplug_occurred) { + mutex_unlock(&hotplug_mutex); + break; + } + mutex_unlock(&hotplug_mutex); + } else { + break; + } + addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC); if (!addr) @@ -119,8 +146,10 @@ static long cmm_alloc_pages(long nr) if (!pa || pa->index >= CMM_NR_PAGES) { /* Need a new page for the page list. */ spin_unlock(&cmm_lock); - npa = (struct cmm_page_array *)__get_free_page(GFP_NOIO | __GFP_NOWARN | - __GFP_NORETRY | __GFP_NOMEMALLOC); + npa = (struct cmm_page_array *)__get_free_page( + GFP_NOIO | __GFP_NOWARN | + __GFP_NORETRY | __GFP_NOMEMALLOC | + __GFP_MOVABLE); if (!npa) { pr_info(
Re: [PATCH 2/2][v3] powerpc: Make the CMM memory hotplug aware
* Benjamin Herrenschmidt (b...@kernel.crashing.org) wrote: > On Fri, 2009-10-09 at 15:41 -0500, Robert Jennings wrote: > > The Collaborative Memory Manager (CMM) module allocates individual pages > > over time that are not migratable. On a long running system this can > > severely impact the ability to find enough pages to support a hotplug > > memory remove operation. > > > > This patch adds a memory isolation notifier and a memory hotplug notifier. > > The memory isolation notifier will return the number of pages found > > in the range specified. This is used to determine if all of the used > > pages in a pageblock are owned by the balloon (or other entities in > > the notifier chain). The hotplug notifier will free pages in the range > > which is to be removed. The priority of this hotplug notifier is low > > so that it will be called near last, this helps avoids removing loaned > > pages in operations that fail due to other handlers. > > > > CMM activity will be halted when hotplug remove operations are active > > and resume activity after a delay period to allow the hypervisor time > > to adjust. > > > > Signed-off-by: Robert Jennings > > Do you need me to merge that via the powerpc tree after the relevant > generic parts go in ? This is 2.6.33 material ? I didn't know how this part works honestly, this is the first time I've pushed patches with dependencies like this. Andrew Morton had pulled an earlier version of this and the mm hotplug related changes for 2.6.32. > > +module_param_named(hotplug_delay, hotplug_delay, uint, S_IRUGO | S_IWUSR); > > +MODULE_PARM_DESC(delay, "Delay (in seconds) after memory hotplug remove " > > +"before activity resumes. " > > +"[Default=" __stringify(CMM_HOTPLUG_DELAY) "]"); > > What is the above ? That sounds scary :-) I'm changing this to read "Delay (in seconds) after memory hotplug remove before loaning resumes." in order to clear this us. This is a period where loaning from the balloon is paused after the hotplug completes. This gives the userspace tools time to mark the sections as isolated and unusable with the hypervisor and the hypervisor to take this into account regarding the loaning levels it requests of the OS. > > module_param_named(oom_kb, oom_kb, uint, S_IRUGO | S_IWUSR); > > MODULE_PARM_DESC(oom_kb, "Amount of memory in kb to free on OOM. " > > "[Default=" __stringify(CMM_OOM_KB) "]"); > > @@ -88,6 +101,8 @@ struct cmm_page_array { > > static unsigned long loaned_pages; > > static unsigned long loaned_pages_target; > > static unsigned long oom_freed_pages; > > +static atomic_t hotplug_active = ATOMIC_INIT(0); > > +static atomic_t hotplug_occurred = ATOMIC_INIT(0); > > That sounds like a hand made lock with atomics... rarely a good idea, > tends to miss appropriate barriers etc... > I have changes this so that we have a mutex held during the memory hotplug remove. The hotplug_occurred flag is now and integer protected by the mutex; it is used to provide the delay after the hotplug remove completes. > > static struct cmm_page_array *cmm_page_list; > > static DEFINE_SPINLOCK(cmm_lock); > > @@ -110,6 +125,9 @@ static long cmm_alloc_pages(long nr) > > cmm_dbg("Begin request for %ld pages\n", nr); > > > > while (nr) { > > + if (atomic_read(&hotplug_active)) > > + break; > > + > > Ok so I'm not familiar with that whole memory hotplug stuff, so the code > might be right, but wouldn't the above be racy anyways in case hotplug > just becomes active after this statement ? > > Shouldn't you use a mutex_trylock instead ? That has clearer semantics > and will provide the appropriate memory barriers. I have changed this to use a mutex in the same location. This allows the allocation of pages to terminate early during a hotplug remove operation. If hotplug becomes active after this check in cmm_alloc_pages() one page will be allocated to the balloon, but this page will not belong to the memory range going offline because the pageblock will have already been isolated. After allocating the page we might need to wait on the lock to add the page to the list if hotplug is removing pages from the balloon. After one page is added, cmm_alloc_pages() will exit early when it checks to see if hotplug is active or if it has occurred. I wanted to keep the section locked by cmm_lock small, so that we can safely respond to the hotplug notifier as quickly as possible while minimizing memory pressure. There are no checks in cmm_free_pages() to have it abort early during hotplug memory remove with the rationale that it's good for hotplug to allow the balloon to shrink even if it means holding the cmm_lock a bit longer. > > addr = __get_free_page(GFP_NOIO | __GFP_NOWARN | > >__GFP_NORETRY | __GFP_NOMEMALLOC); > > if (!addr) > > @@ -119,8 +137,10 @@ static long cmm_alloc_pages(long nr) > > if (!pa || pa->i
Re: [v8 PATCH 2/8]: cpuidle: implement a list based approach to register a set of idle routines.
Peter Zijlstra writes: > > So does it make sense to have a set of sets? > > Why not integrate them all into one set to be ruled by this governor > thing? cpuidle is currently optional, that is why the two level hierarchy is there so that you can still have simple idle selection without it. % size drivers/cpuidle/*.o textdata bss dec hex filename 55141416 4469741b3e drivers/cpuidle/built-in.o Adding it unconditionally would add ~7k to everyone who wants idle functions. I think making it unconditional would require putting it on a serious diet first. -Andi -- a...@linux.intel.com -- Speaking for myself only. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 8/8] spi_mpc8xxx: Add support for QE DMA mode and CPM1/CPM2 chips
This patch adds QE buffer descriptors mode support for the spi_mpc8xxx driver, and as a side effect we now support CPM1 and CPM2 SPI controllers. That means that today we support almost all MPC SPI controllers: - MPC834x-style controllers (support PIO mode only); - CPM1 and CPM2 controllers (support DMA mode only); - QE SPI controllers in CPU mode (PIO mode with shift quirks); - QE SPI controllers in buffer descriptors (DMA) mode; The only controller we don't currently support is a newer eSPI (with a dedicated chip selects and a bit different registers map). Signed-off-by: Anton Vorontsov Acked-by: David Brownell --- drivers/spi/Kconfig |3 - drivers/spi/spi_mpc8xxx.c | 540 + 2 files changed, 500 insertions(+), 43 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4b6f7cb..94058c6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -147,9 +147,6 @@ config SPI_MPC8xxx This enables using the Freescale MPC8xxx SPI controllers in master mode. - This driver uses a simple set of shift registers for data (opposed - to the CPM based descriptor model). - config SPI_OMAP_UWIRE tristate "OMAP1 MicroWire" depends on ARCH_OMAP1 diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 80374df..394b658 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -5,6 +5,10 @@ * * Copyright (C) 2006 Polycom, Inc. * + * CPM SPI and QE buffer descriptors mode support: + * Copyright (c) 2009 MontaVista Software, Inc. + * Author: Anton Vorontsov + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -27,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -34,8 +41,19 @@ #include #include +#include +#include #include +/* CPM1 and CPM2 are mutually exclusive. */ +#ifdef CONFIG_CPM1 +#include +#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0) +#else +#include +#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0) +#endif + /* SPI Controller registers */ struct mpc8xxx_spi_reg { u8 res1[0x20]; @@ -47,6 +65,28 @@ struct mpc8xxx_spi_reg { __be32 receive; }; +/* SPI Parameter RAM */ +struct spi_pram { + __be16 rbase; /* Rx Buffer descriptor base address */ + __be16 tbase; /* Tx Buffer descriptor base address */ + u8 rfcr; /* Rx function code */ + u8 tfcr; /* Tx function code */ + __be16 mrblr; /* Max receive buffer length */ + __be32 rstate; /* Internal */ + __be32 rdp;/* Internal */ + __be16 rbptr; /* Internal */ + __be16 rbc;/* Internal */ + __be32 rxtmp; /* Internal */ + __be32 tstate; /* Internal */ + __be32 tdp;/* Internal */ + __be16 tbptr; /* Internal */ + __be16 tbc;/* Internal */ + __be32 txtmp; /* Internal */ + __be32 res;/* Tx temp. */ + __be16 rpbase; /* Relocation pointer (CPM1 only) */ + __be16 res1; /* Reserved */ +}; + /* SPI Controller mode register definitions */ #defineSPMODE_LOOP (1 << 30) #defineSPMODE_CI_INACTIVEHIGH (1 << 29) @@ -75,14 +115,40 @@ struct mpc8xxx_spi_reg { #defineSPIM_NE 0x0200 /* Not empty */ #defineSPIM_NF 0x0100 /* Not full */ +#defineSPIE_TXB0x0200 /* Last char is written to tx fifo */ +#defineSPIE_RXB0x0100 /* Last char is written to rx buf */ + +/* SPCOM register values */ +#defineSPCOM_STR (1 << 23) /* Start transmit */ + +#defineSPI_PRAM_SIZE 0x100 +#defineSPI_MRBLR ((unsigned int)PAGE_SIZE) + /* SPI Controller driver's private data. */ struct mpc8xxx_spi { + struct device *dev; struct mpc8xxx_spi_reg __iomem *base; /* rx & tx bufs from the spi_transfer */ const void *tx; void *rx; + int subblock; + struct spi_pram __iomem *pram; + struct cpm_buf_desc __iomem *tx_bd; + struct cpm_buf_desc __iomem *rx_bd; + + struct spi_transfer *xfer_in_progress; + + /* dma addresses for CPM transfers */ + dma_addr_t tx_dma; + dma_addr_t rx_dma; + bool map_tx_dma; + bool map_rx_dma; + + dma_addr_t dma_dummy_tx; + dma_addr_t dma_dummy_rx; + /* functions to deal with different sized buffers */ void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *); u32(*get_tx) (struct mpc8xxx_spi *); @@ -98,6 +164,10 @@ struct mpc8xxx_spi { unsigned int flags; #define SPI_QE_CPU_MODE(1 << 0) /* QE CPU ("PIO") mode */ +#define SPI_CPM_MODE
[PATCH 7/8] spi_mpc8xxx: Turn qe_mode into flags
Soon there will be more flags introduced in subsequent patches, so let's turn qe_mode into flags. Also introduce mpc8xxx_spi_strmode() and print current SPI mode. Signed-off-by: Anton Vorontsov Acked-by: David Brownell --- drivers/spi/spi_mpc8xxx.c | 30 +++--- include/linux/fsl_devices.h |2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 4b119ea..80374df 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -96,7 +96,8 @@ struct mpc8xxx_spi { u32 rx_shift; /* RX data reg shift when in qe mode */ u32 tx_shift; /* TX data reg shift when in qe mode */ - bool qe_mode; + unsigned int flags; +#define SPI_QE_CPU_MODE(1 << 0) /* QE CPU ("PIO") mode */ struct workqueue_struct *workqueue; struct work_struct work; @@ -235,14 +236,14 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) if (bits_per_word <= 8) { cs->get_rx = mpc8xxx_spi_rx_buf_u8; cs->get_tx = mpc8xxx_spi_tx_buf_u8; - if (mpc8xxx_spi->qe_mode) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { cs->rx_shift = 16; cs->tx_shift = 24; } } else if (bits_per_word <= 16) { cs->get_rx = mpc8xxx_spi_rx_buf_u16; cs->get_tx = mpc8xxx_spi_tx_buf_u16; - if (mpc8xxx_spi->qe_mode) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { cs->rx_shift = 16; cs->tx_shift = 16; } @@ -252,7 +253,8 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) } else return -EINVAL; - if (mpc8xxx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE && + spi->mode & SPI_LSB_FIRST) { cs->tx_shift = 0; if (bits_per_word <= 8) cs->rx_shift = 8; @@ -518,6 +520,13 @@ static void mpc8xxx_spi_cleanup(struct spi_device *spi) kfree(spi->controller_state); } +static const char *mpc8xxx_spi_strmode(unsigned int flags) +{ + if (flags & SPI_QE_CPU_MODE) + return "QE CPU"; + return "CPU"; +} + static struct spi_master * __devinit mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) { @@ -544,14 +553,14 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) master->cleanup = mpc8xxx_spi_cleanup; mpc8xxx_spi = spi_master_get_devdata(master); - mpc8xxx_spi->qe_mode = pdata->qe_mode; mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8; mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8; + mpc8xxx_spi->flags = pdata->flags; mpc8xxx_spi->spibrg = pdata->sysclk; mpc8xxx_spi->rx_shift = 0; mpc8xxx_spi->tx_shift = 0; - if (mpc8xxx_spi->qe_mode) { + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) { mpc8xxx_spi->rx_shift = 16; mpc8xxx_spi->tx_shift = 24; } @@ -584,7 +593,7 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) /* Enable SPI interface */ regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; - if (pdata->qe_mode) + if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) regval |= SPMODE_OP; mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval); @@ -604,9 +613,8 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) if (ret < 0) goto unreg_master; - printk(KERN_INFO - "%s: MPC8xxx SPI Controller driver at 0x%p (irq = %d)\n", - dev_name(dev), mpc8xxx_spi->base, mpc8xxx_spi->irq); + dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base, +mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); return master; @@ -797,7 +805,7 @@ static int __devinit of_mpc8xxx_spi_probe(struct of_device *ofdev, prop = of_get_property(np, "mode", NULL); if (prop && !strcmp(prop, "cpu-qe")) - pdata->qe_mode = 1; + pdata->flags = SPI_QE_CPU_MODE; ret = of_mpc8xxx_spi_get_chipselects(dev); if (ret) diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 43fc95d..39fd946 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -74,7 +74,7 @@ struct spi_device; struct fsl_spi_platform_data { u32 initial_spmode; /* initial SPMODE value */ s16 bus_num; - boolqe_mode; + unsigned int flags; /* board specific information */ u16 max_chipselect; void(*cs_control)(struct spi_
[PATCH 6/8] spi_mpc8xxx: Factor out SPI mode change steps into a call
We'll add more steps soon, so get rid of the duplication. Signed-off-by: Anton Vorontsov Acked-by: David Brownell --- drivers/spi/spi_mpc8xxx.c | 56 +++- 1 files changed, 24 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 518671b..4b119ea 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -155,6 +155,26 @@ MPC83XX_SPI_TX_BUF(u8) MPC83XX_SPI_TX_BUF(u16) MPC83XX_SPI_TX_BUF(u32) +static void mpc8xxx_spi_change_mode(struct spi_device *spi) +{ + struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); + struct spi_mpc8xxx_cs *cs = spi->controller_state; + __be32 __iomem *mode = &mspi->base->mode; + unsigned long flags; + + if (cs->hw_mode == mpc8xxx_spi_read_reg(mode)) + return; + + /* Turn off IRQs locally to minimize time that SPI is disabled. */ + local_irq_save(flags); + + /* Turn off SPI unit prior changing mode */ + mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE); + mpc8xxx_spi_write_reg(mode, cs->hw_mode); + + local_irq_restore(flags); +} + static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) { struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); @@ -168,27 +188,13 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value) } if (value == BITBANG_CS_ACTIVE) { - u32 regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode); - mpc8xxx_spi->rx_shift = cs->rx_shift; mpc8xxx_spi->tx_shift = cs->tx_shift; mpc8xxx_spi->get_rx = cs->get_rx; mpc8xxx_spi->get_tx = cs->get_tx; - if (cs->hw_mode != regval) { - unsigned long flags; - __be32 __iomem *mode = &mpc8xxx_spi->base->mode; - - regval = cs->hw_mode; - /* Turn off IRQs locally to minimize time that -* SPI is disabled -*/ - local_irq_save(flags); - /* Turn off SPI unit prior changing mode */ - mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); - mpc8xxx_spi_write_reg(mode, regval); - local_irq_restore(flags); - } + mpc8xxx_spi_change_mode(spi); + if (pdata->cs_control) pdata->cs_control(spi, pol); } @@ -198,7 +204,6 @@ static int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { struct mpc8xxx_spi *mpc8xxx_spi; - u32 regval; u8 bits_per_word, pm; u32 hz; struct spi_mpc8xxx_cs *cs = spi->controller_state; @@ -286,21 +291,8 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) pm--; cs->hw_mode |= SPMODE_PM(pm); - regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode); - if (cs->hw_mode != regval) { - unsigned long flags; - __be32 __iomem *mode = &mpc8xxx_spi->base->mode; - - regval = cs->hw_mode; - /* Turn off IRQs locally to minimize time -* that SPI is disabled -*/ - local_irq_save(flags); - /* Turn off SPI unit prior changing mode */ - mpc8xxx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); - mpc8xxx_spi_write_reg(mode, regval); - local_irq_restore(flags); - } + + mpc8xxx_spi_change_mode(spi); return 0; } -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 5/8] spi_mpc8xxx: Fix uninitialized variable
This patch fixes the following warning: CC drivers/spi/spi_mpc8xxx.o spi_mpc8xxx.c: In function 'of_mpc8xxx_spi_probe': spi_mpc8xxx.c:681: warning: 'ret' may be used uninitialized in this function Signed-off-by: Anton Vorontsov Acked-by: David Brownell --- drivers/spi/spi_mpc8xxx.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index 0fd0ec4..518671b 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -709,6 +709,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device *dev) gpio = of_get_gpio_flags(np, i, &flags); if (!gpio_is_valid(gpio)) { dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); + ret = gpio; goto err_loop; } -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 4/8] powerpc/qe&cpm: Implement static inline stubs for non-QE/CPM builds
This is needed to avoid ugly #ifdefs in drivers. Also update fsl_qe_udc driver so that now it doesn't define its own versions that cause build breakage when the generic stubs are used. Signed-off-by: Anton Vorontsov Acked-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/cpm.h | 44 +++ arch/powerpc/include/asm/qe.h | 11 - drivers/usb/gadget/fsl_qe_udc.h | 15 - 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index ea3fdb9..0835eb9 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h @@ -3,6 +3,7 @@ #include #include +#include #include /* @@ -131,13 +132,56 @@ typedef struct cpm_buf_desc { #define BD_I2C_START (0x0400) int cpm_muram_init(void); + +#if defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) unsigned long cpm_muram_alloc(unsigned long size, unsigned long align); int cpm_muram_free(unsigned long offset); unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size); void __iomem *cpm_muram_addr(unsigned long offset); unsigned long cpm_muram_offset(void __iomem *addr); dma_addr_t cpm_muram_dma(void __iomem *addr); +#else +static inline unsigned long cpm_muram_alloc(unsigned long size, + unsigned long align) +{ + return -ENOSYS; +} + +static inline int cpm_muram_free(unsigned long offset) +{ + return -ENOSYS; +} + +static inline unsigned long cpm_muram_alloc_fixed(unsigned long offset, + unsigned long size) +{ + return -ENOSYS; +} + +static inline void __iomem *cpm_muram_addr(unsigned long offset) +{ + return NULL; +} + +static inline unsigned long cpm_muram_offset(void __iomem *addr) +{ + return -ENOSYS; +} + +static inline dma_addr_t cpm_muram_dma(void __iomem *addr) +{ + return 0; +} +#endif /* defined(CONFIG_CPM) || defined(CONFIG_QUICC_ENGINE) */ + +#ifdef CONFIG_CPM int cpm_command(u32 command, u8 opcode); +#else +static inline int cpm_command(u32 command, u8 opcode) +{ + return -ENOSYS; +} +#endif /* CONFIG_CPM */ int cpm2_gpiochip_add32(struct device_node *np); diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h index f388f0a..d013d7e 100644 --- a/arch/powerpc/include/asm/qe.h +++ b/arch/powerpc/include/asm/qe.h @@ -145,8 +145,17 @@ static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {} static inline void qe_pin_set_dedicated(struct qe_pin *pin) {} #endif /* CONFIG_QE_GPIO */ -/* QE internal API */ +#ifdef CONFIG_QUICC_ENGINE int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input); +#else +static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, + u32 cmd_input) +{ + return -ENOSYS; +} +#endif /* CONFIG_QUICC_ENGINE */ + +/* QE internal API */ enum qe_clock qe_clock_source(const char *source); unsigned int qe_get_brg_clk(void); int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier); diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index 31b2710..bea5b82 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -419,19 +419,4 @@ struct qe_udc { #define CPM_USB_RESTART_TX_OPCODE 0x0b #define CPM_USB_EP_SHIFT 5 -#ifndef CONFIG_CPM -inline int cpm_command(u32 command, u8 opcode) -{ - return -EOPNOTSUPP; -} -#endif - -#ifndef CONFIG_QUICC_ENGINE -inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, - u32 cmd_input) -{ - return -EOPNOTSUPP; -} -#endif - #endif /* __FSL_QE_UDC_H */ -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/8] powerpc/cpm: Move CPMFCR_* defines into cpm.h
The bits are generic to CPM devices, so let's move them to the common header file, so drivers won't need to privately reintroduce another bunch of the same bits (as we can't include cpm2.h header together with cpm1.h). Signed-off-by: Anton Vorontsov --- arch/powerpc/include/asm/cpm.h | 16 arch/powerpc/include/asm/cpm2.h |8 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index b5f1534..ea3fdb9 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h @@ -27,6 +27,22 @@ struct usb_ctlr { u8 res6[0x22]; } __attribute__ ((packed)); +/* + * Function code bits, usually generic to devices. + */ +#ifdef CONFIG_CPM1 +#define CPMFCR_GBL ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_TC2 ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_DTB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#define CPMFCR_BDB ((u_char)0x00) /* Flag doesn't exist in CPM1 */ +#else +#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ +#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ +#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ +#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ +#endif +#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ + /* Opcodes common to CPM1 and CPM2 */ #define CPM_CR_INIT_TRX((ushort)0x) diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h index 236cfa3..f42e9ba 100644 --- a/arch/powerpc/include/asm/cpm2.h +++ b/arch/powerpc/include/asm/cpm2.h @@ -124,14 +124,6 @@ static inline void cpm2_fastbrg(uint brg, uint rate, int div16) __cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT); } -/* Function code bits, usually generic to devices. -*/ -#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */ -#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */ -#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */ -#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */ -#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */ - /* Parameter RAM offsets from the base. */ #define PROFF_SCC1 ((uint)0x8000) -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RESEND][PATCH 0/8] spi_mpc8xxx: Add support for DMA transfers
Hello Kumar, There are Acks from Greg KH and David Brownell to pass the whole patchset via PowerPC tree. Can you please apply it? Thanks, -- Anton Vorontsov email: cbouatmai...@gmail.com irc://irc.freenode.net/bd2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/8] powerpc/qe&cpm2: Avoid redefinitions in CPM2 and QE headers
struct mcc defined in both immap_qe.h and immap_cpm2.h, so they will conflic when included in a single file. The mcc struct is easy to deal with, since it isn't used in any driver (yet), so let's just rename QE version to qe_mcc. The ucb_ctlr is a bit trickier, since it is used by fsl_qe_udc driver, and the driver supports both CPM and QE UDCs, plus the QE version is used to form a bigger immap struct. I don't want to touch too much of USB code in this series, so for now let's just copy most generic version into the common cpm.h header, later we'll create cpm_usb.h where we'll place common USB structs that are used by QE/CPM UDC and QE Host drivers (FHCI). And as for the structs in qe.h and cpm2.h, just prefix them with qe_ and cpm_. Signed-off-by: Anton Vorontsov --- arch/powerpc/include/asm/cpm.h| 22 ++ arch/powerpc/include/asm/immap_cpm2.h |2 +- arch/powerpc/include/asm/immap_qe.h |8 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/include/asm/cpm.h b/arch/powerpc/include/asm/cpm.h index 24d79e3..b5f1534 100644 --- a/arch/powerpc/include/asm/cpm.h +++ b/arch/powerpc/include/asm/cpm.h @@ -5,6 +5,28 @@ #include #include +/* + * USB Controller pram common to QE and CPM. + */ +struct usb_ctlr { + u8 usb_usmod; + u8 usb_usadr; + u8 usb_uscom; + u8 res1[1]; + __be16 usb_usep[4]; + u8 res2[4]; + __be16 usb_usber; + u8 res3[2]; + __be16 usb_usbmr; + u8 res4[1]; + u8 usb_usbs; + /* Fields down below are QE-only */ + __be16 usb_ussft; + u8 res5[2]; + __be16 usb_usfrn; + u8 res6[0x22]; +} __attribute__ ((packed)); + /* Opcodes common to CPM1 and CPM2 */ #define CPM_CR_INIT_TRX((ushort)0x) diff --git a/arch/powerpc/include/asm/immap_cpm2.h b/arch/powerpc/include/asm/immap_cpm2.h index d4f069b..7c64fda 100644 --- a/arch/powerpc/include/asm/immap_cpm2.h +++ b/arch/powerpc/include/asm/immap_cpm2.h @@ -549,7 +549,7 @@ typedef struct comm_proc { /* USB Controller. */ -typedef struct usb_ctlr { +typedef struct cpm_usb_ctlr { u8 usb_usmod; u8 usb_usadr; u8 usb_uscom; diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h index c346d0b..4e10f50 100644 --- a/arch/powerpc/include/asm/immap_qe.h +++ b/arch/powerpc/include/asm/immap_qe.h @@ -210,7 +210,7 @@ struct sir { } __attribute__ ((packed)); /* USB Controller */ -struct usb_ctlr { +struct qe_usb_ctlr { u8 usb_usmod; u8 usb_usadr; u8 usb_uscom; @@ -229,7 +229,7 @@ struct usb_ctlr { } __attribute__ ((packed)); /* MCC */ -struct mcc { +struct qe_mcc { __be32 mcce; /* MCC event register */ __be32 mccm; /* MCC mask register */ __be32 mccf; /* MCC configuration register */ @@ -431,9 +431,9 @@ struct qe_immap { struct qe_mux qmx;/* QE Multiplexer */ struct qe_timersqet;/* QE Timers */ struct spi spi[0x2]; /* spi */ - struct mcc mcc;/* mcc */ + struct qe_mcc mcc;/* mcc */ struct qe_brg brg;/* brg */ - struct usb_ctlr usb;/* USB */ + struct qe_usb_ctlr usb;/* USB */ struct si1 si1;/* SI */ u8 res11[0x800]; struct sir sir;/* SI Routing Tables */ -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/8] powerpc/cpm: Remove SPI defines and spi structs
When cpm2.h included into spi_mpc8xxx driver, the SPI defines in the header conflict with defines in the driver. We don't need them in the header file, so remove them. Plus remove "struct spi", we'll use a better version in the driver. Signed-off-by: Anton Vorontsov --- arch/powerpc/include/asm/cpm1.h | 45 --- arch/powerpc/include/asm/cpm2.h | 39 - 2 files changed, 0 insertions(+), 84 deletions(-) diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 7685ffd..81b0119 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h @@ -478,51 +478,6 @@ typedef struct iic { charres2[2];/* Reserved */ } iic_t; -/* SPI parameter RAM. -*/ -typedef struct spi { - ushort spi_rbase; /* Rx Buffer descriptor base address */ - ushort spi_tbase; /* Tx Buffer descriptor base address */ - u_char spi_rfcr; /* Rx function code */ - u_char spi_tfcr; /* Tx function code */ - ushort spi_mrblr; /* Max receive buffer length */ - uintspi_rstate; /* Internal */ - uintspi_rdp;/* Internal */ - ushort spi_rbptr; /* Internal */ - ushort spi_rbc;/* Internal */ - uintspi_rxtmp; /* Internal */ - uintspi_tstate; /* Internal */ - uintspi_tdp;/* Internal */ - ushort spi_tbptr; /* Internal */ - ushort spi_tbc;/* Internal */ - uintspi_txtmp; /* Internal */ - uintspi_res; - ushort spi_rpbase; /* Relocation pointer */ - ushort spi_res2; -} spi_t; - -/* SPI Mode register. -*/ -#define SPMODE_LOOP((ushort)0x4000)/* Loopback */ -#define SPMODE_CI ((ushort)0x2000)/* Clock Invert */ -#define SPMODE_CP ((ushort)0x1000)/* Clock Phase */ -#define SPMODE_DIV16 ((ushort)0x0800)/* BRG/16 mode */ -#define SPMODE_REV ((ushort)0x0400)/* Reversed Data */ -#define SPMODE_MSTR((ushort)0x0200)/* SPI Master */ -#define SPMODE_EN ((ushort)0x0100)/* Enable */ -#define SPMODE_LENMSK ((ushort)0x00f0)/* character length */ -#define SPMODE_LEN4((ushort)0x0030)/* 4 bits per char */ -#define SPMODE_LEN8((ushort)0x0070)/* 8 bits per char */ -#define SPMODE_LEN16 ((ushort)0x00f0)/* 16 bits per char */ -#define SPMODE_PMMSK ((ushort)0x000f)/* prescale modulus */ - -/* SPIE fields */ -#define SPIE_MME 0x20 -#define SPIE_TXE 0x10 -#define SPIE_BSY 0x04 -#define SPIE_TXB 0x02 -#define SPIE_RXB 0x01 - /* * RISC Controller Configuration Register definitons */ diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h index 990ff19..236cfa3 100644 --- a/arch/powerpc/include/asm/cpm2.h +++ b/arch/powerpc/include/asm/cpm2.h @@ -654,45 +654,6 @@ typedef struct iic { uintiic_txtmp; /* Internal */ } iic_t; -/* SPI parameter RAM. -*/ -typedef struct spi { - ushort spi_rbase; /* Rx Buffer descriptor base address */ - ushort spi_tbase; /* Tx Buffer descriptor base address */ - u_char spi_rfcr; /* Rx function code */ - u_char spi_tfcr; /* Tx function code */ - ushort spi_mrblr; /* Max receive buffer length */ - uintspi_rstate; /* Internal */ - uintspi_rdp;/* Internal */ - ushort spi_rbptr; /* Internal */ - ushort spi_rbc;/* Internal */ - uintspi_rxtmp; /* Internal */ - uintspi_tstate; /* Internal */ - uintspi_tdp;/* Internal */ - ushort spi_tbptr; /* Internal */ - ushort spi_tbc;/* Internal */ - uintspi_txtmp; /* Internal */ - uintspi_res;/* Tx temp. */ - uintspi_res1[4];/* SDMA temp. */ -} spi_t; - -/* SPI Mode register. -*/ -#define SPMODE_LOOP((ushort)0x4000)/* Loopback */ -#define SPMODE_CI ((ushort)0x2000)/* Clock Invert */ -#define SPMODE_CP ((ushort)0x1000)/* Clock Phase */ -#define SPMODE_DIV16 ((ushort)0x0800)/* BRG/16 mode */ -#define SPMODE_REV ((ushort)0x0400)/* Reversed Data */ -#define SPMODE_MSTR((ushort)0x0200)/* SPI Master */ -#define SPMODE_EN ((ushort)0x0100)/* Enable */ -#define SPMODE_LENMSK ((ushort)0x00f0)/* character length */ -#define SPMODE_PMMSK ((ushort)0x000f)/* prescale modulus */ - -#define SPMODE_LEN(x) x)-1)&0xF)<<4) -#define SPMODE_PM(x) ((x) &0xF) - -#define SPI_EB ((u_char)0x10) /* big endian byte order */ - /* IDMA parameter RAM */ typedef struct idma { -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org
[PATCH] powerpc/8xxx: enable IPsec ESP by default on mpc83xx/mpc85xx
Signed-off-by: Kim Phillips --- arch/powerpc/configs/mpc83xx_defconfig | 15 --- arch/powerpc/configs/mpc85xx_defconfig | 16 arch/powerpc/configs/mpc85xx_smp_defconfig | 16 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig index 4a96cb6..d6d28f2 100644 --- a/arch/powerpc/configs/mpc83xx_defconfig +++ b/arch/powerpc/configs/mpc83xx_defconfig @@ -343,7 +343,8 @@ CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set # CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -358,7 +359,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_ARPD is not set CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set +CONFIG_INET_ESP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set @@ -1591,7 +1592,7 @@ CONFIG_CRYPTO_PCBC=m # # Hash modes # -# CONFIG_CRYPTO_HMAC is not set +CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # @@ -1605,16 +1606,16 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set # # Ciphers # -# CONFIG_CRYPTO_AES is not set +CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index ada5958..35f941c 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig @@ -344,7 +344,7 @@ CONFIG_XFRM_USER=y # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set # CONFIG_XFRM_STATISTICS is not set -CONFIG_NET_KEY=m +CONFIG_NET_KEY=y # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -368,12 +368,12 @@ CONFIG_IP_PIMSM_V2=y CONFIG_ARPD=y # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set +CONFIG_INET_ESP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set CONFIG_INET_TUNNEL=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y @@ -1768,16 +1768,16 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set -CONFIG_CRYPTO_SHA1=m -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set # # Ciphers # -# CONFIG_CRYPTO_AES is not set +CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index db082ce..ab45fd9 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig @@ -348,7 +348,7 @@ CONFIG_XFRM_USER=y # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set # CONFIG_XFRM_STATISTICS is not set -CONFIG_NET_KEY=m +CONFIG_NET_KEY=y # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -372,12 +372,12 @@ CONFIG_IP_PIMSM_V2=y CONFIG_ARPD=y # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set +CONFIG_INET_ESP=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set CONFIG_INET_TUNNEL=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y @@ -1772,16 +1772,16 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set -CONFIG_CRYPTO_SHA1=m -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set # # Ciphers # -# CONFIG_CRYPTO_AES is not set +CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_BLOWFISH is not set -- 1.6.4.4 ___ Linuxppc-dev mailing list Linuxppc-de
Re: [PATCH] * mpc8313erdb.dts: Fixed eTSEC interrupt assignment.
On Wed, 9 Sep 2009 15:28:01 -0500 Kumar Gala wrote: > > On Sep 9, 2009, at 1:22 PM, Scott Wood wrote: > > > On Fri, Sep 04, 2009 at 12:31:25PM +0200, Roland Lezuo wrote: > >> The following patch is needed to correctly assign the IRQs for the > >> gianfar driver on the MPC8313ERDB-revc boards. ERR and TX are swapped > >> as well as the interrupt lines for the two devices. > > > > And it will incorrectly assign them on older revisions of the chip. > > > > We really should have a u-boot fixup based on SVR. Roland, is it possible for you to test this u-boot patch?: >From 44c73137acf20626e930e3f4142e60054d8bd46f Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 12 Oct 2009 10:51:20 -0500 Subject: [PATCH] mpc83xx: mpc8313 - handle erratum IPIC1 (TSEC IRQ number swappage) mpc8313e erratum IPIC1 swapped TSEC interrupt ID numbers on rev. 1 h/w (see AN3545). The base device tree in use has rev. 1 ID numbers, so if on Rev. 2 (and higher) h/w, we fix them up here. Signed-off-by: Kim Phillips --- cpu/mpc83xx/fdt.c | 39 +++ 1 files changed, 39 insertions(+), 0 deletions(-) diff --git a/cpu/mpc83xx/fdt.c b/cpu/mpc83xx/fdt.c index 13443cb..daf73a6 100644 --- a/cpu/mpc83xx/fdt.c +++ b/cpu/mpc83xx/fdt.c @@ -69,6 +69,45 @@ void ft_cpu_setup(void *blob, bd_t *bd) defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) ||\ defined(CONFIG_HAS_ETH4) || defined(CONFIG_HAS_ETH5) fdt_fixup_ethernet(blob); +#ifdef CONFIG_MPC8313 + /* + * mpc8313e erratum IPIC1 swapped TSEC interrupt ID numbers on rev. 1 + * h/w (see AN3545). The base device tree in use has rev. 1 ID numbers, + * so if on Rev. 2 (and higher) h/w, we fix them up here + */ + if (REVID_MAJOR(immr->sysconf.spridr) >= 2) { + int nodeoffset, path; + const char *prop; + + nodeoffset = fdt_path_offset(blob, "/aliases"); + if (nodeoffset >= 0) { +#if defined(CONFIG_HAS_ETH0) + prop = fdt_getprop(blob, nodeoffset, "ethernet0", NULL); + if (prop) { + u32 tmp[] = { 32, 0x8, 33, 0x8, 34, 0x8 }; + + path = fdt_path_offset(blob, prop); + prop = fdt_getprop(blob, path, "interrupts", 0); + if (prop) + fdt_setprop(blob, path, "interrupts", + &tmp, sizeof(tmp)); + } +#endif +#if defined(CONFIG_HAS_ETH1) + prop = fdt_getprop(blob, nodeoffset, "ethernet1", NULL); + if (prop) { + u32 tmp[] = { 35, 0x8, 36, 0x8, 37, 0x8 }; + + path = fdt_path_offset(blob, prop); + prop = fdt_getprop(blob, path, "interrupts", 0); + if (prop) + fdt_setprop(blob, path, "interrupts", + &tmp, sizeof(tmp)); + } +#endif + } + } +#endif #endif do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, -- 1.6.4.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 8/8] gianfar: Add support for hibernation
Thanks to various cleanups and refactorings this is now straightforward: convert the gianfar driver to dev_pm_ops, plus add ->restore() callback that will fully reinitialize MAC internal registers and BDs. Note that I kept legacy suspend/resume callbacks so that this patch doesn't depend on PowerPC changes (i.e. dev_pm_ops support for OF platform drivers). Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 87 +++- 1 files changed, 70 insertions(+), 17 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 634a15b..f714186 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -700,23 +700,24 @@ static int gfar_remove(struct of_device *ofdev) } #ifdef CONFIG_PM -static int gfar_suspend(struct of_device *ofdev, pm_message_t state) + +static int gfar_suspend(struct device *dev) { - struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); - struct net_device *dev = priv->ndev; + struct gfar_private *priv = dev_get_drvdata(dev); + struct net_device *ndev = priv->ndev; unsigned long flags; u32 tempval; int magic_packet = priv->wol_en && (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); - netif_device_detach(dev); + netif_device_detach(ndev); - if (netif_running(dev)) { + if (netif_running(ndev)) { spin_lock_irqsave(&priv->txlock, flags); spin_lock(&priv->rxlock); - gfar_halt_nodisable(dev); + gfar_halt_nodisable(ndev); /* Disable Tx, and Rx if wake-on-LAN is disabled. */ tempval = gfar_read(&priv->regs->maccfg1); @@ -749,17 +750,17 @@ static int gfar_suspend(struct of_device *ofdev, pm_message_t state) return 0; } -static int gfar_resume(struct of_device *ofdev) +static int gfar_resume(struct device *dev) { - struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); - struct net_device *dev = priv->ndev; + struct gfar_private *priv = dev_get_drvdata(dev); + struct net_device *ndev = priv->ndev; unsigned long flags; u32 tempval; int magic_packet = priv->wol_en && (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); - if (!netif_running(dev)) { - netif_device_attach(dev); + if (!netif_running(ndev)) { + netif_device_attach(ndev); return 0; } @@ -777,20 +778,71 @@ static int gfar_resume(struct of_device *ofdev) tempval &= ~MACCFG2_MPEN; gfar_write(&priv->regs->maccfg2, tempval); - gfar_start(dev); + gfar_start(ndev); spin_unlock(&priv->rxlock); spin_unlock_irqrestore(&priv->txlock, flags); - netif_device_attach(dev); + netif_device_attach(ndev); + + napi_enable(&priv->napi); + + return 0; +} + +static int gfar_restore(struct device *dev) +{ + struct gfar_private *priv = dev_get_drvdata(dev); + struct net_device *ndev = priv->ndev; + + if (!netif_running(ndev)) + return 0; + + gfar_init_bds(ndev); + init_registers(ndev); + gfar_set_mac_address(ndev); + gfar_init_mac(ndev); + gfar_start(ndev); + + priv->oldlink = 0; + priv->oldspeed = 0; + priv->oldduplex = -1; + + if (priv->phydev) + phy_start(priv->phydev); + netif_device_attach(ndev); napi_enable(&priv->napi); return 0; } + +static struct dev_pm_ops gfar_pm_ops = { + .suspend = gfar_suspend, + .resume = gfar_resume, + .freeze = gfar_suspend, + .thaw = gfar_resume, + .restore = gfar_restore, +}; + +#define GFAR_PM_OPS (&gfar_pm_ops) + +static int gfar_legacy_suspend(struct of_device *ofdev, pm_message_t state) +{ + return gfar_suspend(&ofdev->dev); +} + +static int gfar_legacy_resume(struct of_device *ofdev) +{ + return gfar_resume(&ofdev->dev); +} + #else -#define gfar_suspend NULL -#define gfar_resume NULL + +#define GFAR_PM_OPS NULL +#define gfar_legacy_suspend NULL +#define gfar_legacy_resume NULL + #endif /* Reads the controller's registers to determine what interface @@ -2362,8 +2414,9 @@ static struct of_platform_driver gfar_driver = { .probe = gfar_probe, .remove = gfar_remove, - .suspend = gfar_suspend, - .resume = gfar_resume, + .suspend = gfar_legacy_suspend, + .resume = gfar_legacy_resume, + .driver.pm = GFAR_PM_OPS, }; static int __init gfar_init(void) -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 7/8] gianfar: Factor out gfar_init_bds() from gfar_alloc_skb_resources()
After hibernation we want to just reinitialize BDs, no need to allocate anything. So, factor out BDs initialization code from gfar_alloc_skb_resourses(). Also, teach gfar_init_bds() to reuse already allocated RX SKBs, i.e. just call gfar_init_rxbdp() if a SKB was already allocated and mapped. Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 96 1 files changed, 56 insertions(+), 40 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 1b32274..634a15b 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -164,19 +164,68 @@ static void gfar_init_rxbdp(struct net_device *dev, struct rxbd8 *bdp, bdp->lstatus = lstatus; } -static int gfar_alloc_skb_resources(struct net_device *ndev) +static int gfar_init_bds(struct net_device *ndev) { + struct gfar_private *priv = netdev_priv(ndev); struct txbd8 *txbdp; struct rxbd8 *rxbdp; + int i; + + /* Initialize some variables in our dev structure */ + priv->num_txbdfree = priv->tx_ring_size; + priv->dirty_tx = priv->cur_tx = priv->tx_bd_base; + priv->cur_rx = priv->rx_bd_base; + priv->skb_curtx = priv->skb_dirtytx = 0; + priv->skb_currx = 0; + + /* Initialize Transmit Descriptor Ring */ + txbdp = priv->tx_bd_base; + for (i = 0; i < priv->tx_ring_size; i++) { + txbdp->lstatus = 0; + txbdp->bufPtr = 0; + txbdp++; + } + + /* Set the last descriptor in the ring to indicate wrap */ + txbdp--; + txbdp->status |= TXBD_WRAP; + + rxbdp = priv->rx_bd_base; + for (i = 0; i < priv->rx_ring_size; i++) { + struct sk_buff *skb = priv->rx_skbuff[i]; + + if (skb) { + gfar_init_rxbdp(ndev, rxbdp, rxbdp->bufPtr); + } else { + skb = gfar_new_skb(ndev); + if (!skb) { + pr_err("%s: Can't allocate RX buffers\n", + ndev->name); + return -ENOMEM; + } + priv->rx_skbuff[i] = skb; + + gfar_new_rxbdp(ndev, rxbdp, skb); + } + + rxbdp++; + } + + return 0; +} + +static int gfar_alloc_skb_resources(struct net_device *ndev) +{ void *vaddr; int i; struct gfar_private *priv = netdev_priv(ndev); struct device *dev = &priv->ofdev->dev; /* Allocate memory for the buffer descriptors */ - vaddr = dma_alloc_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + - sizeof(*rxbdp) * priv->rx_ring_size, - &priv->tx_bd_dma_base, GFP_KERNEL); + vaddr = dma_alloc_coherent(dev, + sizeof(*priv->tx_bd_base) * priv->tx_ring_size + + sizeof(*priv->rx_bd_base) * priv->rx_ring_size, + &priv->tx_bd_dma_base, GFP_KERNEL); if (!vaddr) { if (netif_msg_ifup(priv)) pr_err("%s: Could not allocate buffer descriptors!\n", @@ -187,7 +236,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) priv->tx_bd_base = vaddr; /* Start the rx descriptor ring where the tx ring leaves off */ - vaddr = vaddr + sizeof(*txbdp) * priv->tx_ring_size; + vaddr = vaddr + sizeof(*priv->tx_bd_base) * priv->tx_ring_size; priv->rx_bd_base = vaddr; /* Setup the skbuff rings */ @@ -215,41 +264,8 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) for (i = 0; i < priv->rx_ring_size; i++) priv->rx_skbuff[i] = NULL; - /* Initialize some variables in our dev structure */ - priv->num_txbdfree = priv->tx_ring_size; - priv->dirty_tx = priv->cur_tx = priv->tx_bd_base; - priv->cur_rx = priv->rx_bd_base; - priv->skb_curtx = priv->skb_dirtytx = 0; - priv->skb_currx = 0; - - /* Initialize Transmit Descriptor Ring */ - txbdp = priv->tx_bd_base; - for (i = 0; i < priv->tx_ring_size; i++) { - txbdp->lstatus = 0; - txbdp->bufPtr = 0; - txbdp++; - } - - /* Set the last descriptor in the ring to indicate wrap */ - txbdp--; - txbdp->status |= TXBD_WRAP; - - rxbdp = priv->rx_bd_base; - for (i = 0; i < priv->rx_ring_size; i++) { - struct sk_buff *skb; - - skb = gfar_new_skb(ndev); - if (!skb) { - pr_err("%s: Can't allocate RX buffers\n", ndev->name); - goto cleanup; - } - - priv->rx_skbuff[i] = skb; - - gfar_new_rxbdp(ndev, rxbdp, skb); - - rxbdp++; - } + if (gfar_init_bds(ndev)) + got
[PATCH 6/8] gianfar: Factor out RX BDs initialization from gfar_new_rxbdp()
We want to just reinitialize RX BDs after hibernation, no need to map the skb->data again. So let's factor gfar_init_rxbdp() out of gfar_new_rxbdp(). Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 33 + 1 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 46b0b37..1b32274 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -147,6 +147,23 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_LICENSE("GPL"); +static void gfar_init_rxbdp(struct net_device *dev, struct rxbd8 *bdp, + dma_addr_t buf) +{ + struct gfar_private *priv = netdev_priv(dev); + u32 lstatus; + + bdp->bufPtr = buf; + + lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT); + if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1) + lstatus |= BD_LFLAG(RXBD_WRAP); + + eieio(); + + bdp->lstatus = lstatus; +} + static int gfar_alloc_skb_resources(struct net_device *ndev) { struct txbd8 *txbdp; @@ -1676,19 +1693,11 @@ static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp, struct sk_buff *skb) { struct gfar_private *priv = netdev_priv(dev); - u32 lstatus; - - bdp->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data, - priv->rx_buffer_size, DMA_FROM_DEVICE); - - lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT); + dma_addr_t buf; - if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1) - lstatus |= BD_LFLAG(RXBD_WRAP); - - eieio(); - - bdp->lstatus = lstatus; + buf = dma_map_single(&priv->ofdev->dev, skb->data, +priv->rx_buffer_size, DMA_FROM_DEVICE); + gfar_init_rxbdp(dev, bdp, buf); } -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 5/8] gianfar: Move tbase/rbase initialization to gfar_init_mac()
For hibernation we want to call gfar_init_mac() without need to free/allocate_skb_resources sequence, so save the DMA address into a private struct, and move tbase/rbase initialization to gfar_init_mac(). Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 17 - drivers/net/gianfar.h |1 + 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4dcaaa7..46b0b37 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -151,17 +151,15 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) { struct txbd8 *txbdp; struct rxbd8 *rxbdp; - dma_addr_t addr = 0; void *vaddr; int i; struct gfar_private *priv = netdev_priv(ndev); struct device *dev = &priv->ofdev->dev; - struct gfar __iomem *regs = priv->regs; /* Allocate memory for the buffer descriptors */ vaddr = dma_alloc_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + sizeof(*rxbdp) * priv->rx_ring_size, - &addr, GFP_KERNEL); + &priv->tx_bd_dma_base, GFP_KERNEL); if (!vaddr) { if (netif_msg_ifup(priv)) pr_err("%s: Could not allocate buffer descriptors!\n", @@ -171,14 +169,9 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) priv->tx_bd_base = vaddr; - /* enet DMA only understands physical addresses */ - gfar_write(®s->tbase0, addr); - /* Start the rx descriptor ring where the tx ring leaves off */ - addr = addr + sizeof(*txbdp) * priv->tx_ring_size; vaddr = vaddr + sizeof(*txbdp) * priv->tx_ring_size; priv->rx_bd_base = vaddr; - gfar_write(®s->rbase0, addr); /* Setup the skbuff rings */ priv->tx_skbuff = kmalloc(sizeof(*priv->tx_skbuff) * @@ -256,6 +249,12 @@ static void gfar_init_mac(struct net_device *ndev) u32 tctrl = 0; u32 attrs = 0; + /* enet DMA only understands physical addresses */ + gfar_write(®s->tbase0, priv->tx_bd_dma_base); + gfar_write(®s->rbase0, priv->tx_bd_dma_base + + sizeof(*priv->tx_bd_base) * + priv->tx_ring_size); + /* Configure the coalescing support */ gfar_write(®s->txic, 0); if (priv->txcoalescing) @@ -1060,7 +1059,7 @@ skip_rx_skbuff: dma_free_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + sizeof(*rxbdp) * priv->rx_ring_size, - priv->tx_bd_base, gfar_read(&priv->regs->tbase0)); + priv->tx_bd_base, priv->tx_bd_dma_base); } void gfar_start(struct net_device *dev) diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 2cd9433..05732fa 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -726,6 +726,7 @@ struct gfar_private { unsigned long txic; /* Buffer descriptor pointers */ + dma_addr_t tx_bd_dma_base; struct txbd8 *tx_bd_base; /* First tx buffer descriptor */ struct txbd8 *cur_tx; /* Next free ring entry */ struct txbd8 *dirty_tx; /* First buffer in line -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 4/8] gianfar: Split allocation and initialization steps out of startup_gfar()
Two new functions implemented: gfar_alloc_skb_resources() and gfar_init_mac(). We'll use gfar_init_mac() for restoring after hibernation. The patch just moves the code around, there should be no functional changes. Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 334 ++--- 1 files changed, 176 insertions(+), 158 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ee23431..4dcaaa7 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -147,6 +147,176 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); MODULE_DESCRIPTION("Gianfar Ethernet Driver"); MODULE_LICENSE("GPL"); +static int gfar_alloc_skb_resources(struct net_device *ndev) +{ + struct txbd8 *txbdp; + struct rxbd8 *rxbdp; + dma_addr_t addr = 0; + void *vaddr; + int i; + struct gfar_private *priv = netdev_priv(ndev); + struct device *dev = &priv->ofdev->dev; + struct gfar __iomem *regs = priv->regs; + + /* Allocate memory for the buffer descriptors */ + vaddr = dma_alloc_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + + sizeof(*rxbdp) * priv->rx_ring_size, + &addr, GFP_KERNEL); + if (!vaddr) { + if (netif_msg_ifup(priv)) + pr_err("%s: Could not allocate buffer descriptors!\n", + ndev->name); + return -ENOMEM; + } + + priv->tx_bd_base = vaddr; + + /* enet DMA only understands physical addresses */ + gfar_write(®s->tbase0, addr); + + /* Start the rx descriptor ring where the tx ring leaves off */ + addr = addr + sizeof(*txbdp) * priv->tx_ring_size; + vaddr = vaddr + sizeof(*txbdp) * priv->tx_ring_size; + priv->rx_bd_base = vaddr; + gfar_write(®s->rbase0, addr); + + /* Setup the skbuff rings */ + priv->tx_skbuff = kmalloc(sizeof(*priv->tx_skbuff) * + priv->tx_ring_size, GFP_KERNEL); + if (!priv->tx_skbuff) { + if (netif_msg_ifup(priv)) + pr_err("%s: Could not allocate tx_skbuff\n", + ndev->name); + goto cleanup; + } + + for (i = 0; i < priv->tx_ring_size; i++) + priv->tx_skbuff[i] = NULL; + + priv->rx_skbuff = kmalloc(sizeof(*priv->rx_skbuff) * + priv->rx_ring_size, GFP_KERNEL); + if (!priv->rx_skbuff) { + if (netif_msg_ifup(priv)) + pr_err("%s: Could not allocate rx_skbuff\n", + ndev->name); + goto cleanup; + } + + for (i = 0; i < priv->rx_ring_size; i++) + priv->rx_skbuff[i] = NULL; + + /* Initialize some variables in our dev structure */ + priv->num_txbdfree = priv->tx_ring_size; + priv->dirty_tx = priv->cur_tx = priv->tx_bd_base; + priv->cur_rx = priv->rx_bd_base; + priv->skb_curtx = priv->skb_dirtytx = 0; + priv->skb_currx = 0; + + /* Initialize Transmit Descriptor Ring */ + txbdp = priv->tx_bd_base; + for (i = 0; i < priv->tx_ring_size; i++) { + txbdp->lstatus = 0; + txbdp->bufPtr = 0; + txbdp++; + } + + /* Set the last descriptor in the ring to indicate wrap */ + txbdp--; + txbdp->status |= TXBD_WRAP; + + rxbdp = priv->rx_bd_base; + for (i = 0; i < priv->rx_ring_size; i++) { + struct sk_buff *skb; + + skb = gfar_new_skb(ndev); + if (!skb) { + pr_err("%s: Can't allocate RX buffers\n", ndev->name); + goto cleanup; + } + + priv->rx_skbuff[i] = skb; + + gfar_new_rxbdp(ndev, rxbdp, skb); + + rxbdp++; + } + + return 0; + +cleanup: + free_skb_resources(priv); + return -ENOMEM; +} + +static void gfar_init_mac(struct net_device *ndev) +{ + struct gfar_private *priv = netdev_priv(ndev); + struct gfar __iomem *regs = priv->regs; + u32 rctrl = 0; + u32 tctrl = 0; + u32 attrs = 0; + + /* Configure the coalescing support */ + gfar_write(®s->txic, 0); + if (priv->txcoalescing) + gfar_write(®s->txic, priv->txic); + + gfar_write(®s->rxic, 0); + if (priv->rxcoalescing) + gfar_write(®s->rxic, priv->rxic); + + if (priv->rx_csum_enable) + rctrl |= RCTRL_CHECKSUMMING; + + if (priv->extended_hash) { + rctrl |= RCTRL_EXTHASH; + + gfar_clear_exact_match(ndev); + rctrl |= RCTRL_EMEN; + } + + if (priv->padding) { + rctrl &= ~RCTRL_PAL_MASK; + rctrl |= RCTRL_PADDING(priv->padding); + } + + /* keep vlan related bit
[PATCH 3/8] gianfar: Don't needlessly set the wrap bit for the last RX BD
startup_gfar() sets the wrap bit for the last rxbd just after gfar_new_rxbdp() call, which is issued for all rxbds. And gfar_new_rxbdp() has the following check already: if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1) lstatus |= BD_LFLAG(RXBD_WRAP); So we don't need to set the bit again. Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c |4 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index b7881e6..ee23431 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1028,10 +1028,6 @@ int startup_gfar(struct net_device *ndev) rxbdp++; } - /* Set the last descriptor in the ring to wrap */ - rxbdp--; - rxbdp->status |= RXBD_WRAP; - /* If the device has multiple interrupts, register for * them. Otherwise, only register for the one */ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/8] gianfar: Simplify skb resources freeing code
Remove dma_free_coherent() from stop_gfar() and gfar_start() calls, place it into free_skb_resources(). That makes SKB resources management more understandable, plus free_skb_resources() will be used as a cleanup routine for gfar_alloc_skb_resources() that will be implemented soon. Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 53 +++- 1 files changed, 25 insertions(+), 28 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 8c7322f..b7881e6 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -806,7 +806,6 @@ void gfar_halt(struct net_device *dev) void stop_gfar(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); - struct gfar __iomem *regs = priv->regs; unsigned long flags; phy_stop(priv->phydev); @@ -830,18 +829,13 @@ void stop_gfar(struct net_device *dev) } free_skb_resources(priv); - - dma_free_coherent(&priv->ofdev->dev, - sizeof(struct txbd8)*priv->tx_ring_size - + sizeof(struct rxbd8)*priv->rx_ring_size, - priv->tx_bd_base, - gfar_read(®s->tbase0)); } /* If there are any tx skbs or rx skbs still around, free them. * Then free tx_skbuff and rx_skbuff */ static void free_skb_resources(struct gfar_private *priv) { + struct device *dev = &priv->ofdev->dev; struct rxbd8 *rxbdp; struct txbd8 *txbdp; int i, j; @@ -849,6 +843,9 @@ static void free_skb_resources(struct gfar_private *priv) /* Go through all the buffer descriptors and free their data buffers */ txbdp = priv->tx_bd_base; + if (!priv->tx_skbuff) + goto skip_tx_skbuff; + for (i = 0; i < priv->tx_ring_size; i++) { if (!priv->tx_skbuff[i]) continue; @@ -867,30 +864,33 @@ static void free_skb_resources(struct gfar_private *priv) } kfree(priv->tx_skbuff); +skip_tx_skbuff: rxbdp = priv->rx_bd_base; - /* rx_skbuff is not guaranteed to be allocated, so only -* free it and its contents if it is allocated */ - if(priv->rx_skbuff != NULL) { - for (i = 0; i < priv->rx_ring_size; i++) { - if (priv->rx_skbuff[i]) { - dma_unmap_single(&priv->ofdev->dev, rxbdp->bufPtr, - priv->rx_buffer_size, - DMA_FROM_DEVICE); - - dev_kfree_skb_any(priv->rx_skbuff[i]); - priv->rx_skbuff[i] = NULL; - } - - rxbdp->lstatus = 0; - rxbdp->bufPtr = 0; + if (!priv->rx_skbuff) + goto skip_rx_skbuff; - rxbdp++; + for (i = 0; i < priv->rx_ring_size; i++) { + if (priv->rx_skbuff[i]) { + dma_unmap_single(&priv->ofdev->dev, rxbdp->bufPtr, +priv->rx_buffer_size, + DMA_FROM_DEVICE); + dev_kfree_skb_any(priv->rx_skbuff[i]); + priv->rx_skbuff[i] = NULL; } - kfree(priv->rx_skbuff); + rxbdp->lstatus = 0; + rxbdp->bufPtr = 0; + rxbdp++; } + + kfree(priv->rx_skbuff); +skip_rx_skbuff: + + dma_free_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + + sizeof(*rxbdp) * priv->rx_ring_size, + priv->tx_bd_base, gfar_read(&priv->regs->tbase0)); } void gfar_start(struct net_device *dev) @@ -1148,11 +1148,8 @@ tx_irq_fail: err_irq_fail: err_rxalloc_fail: rx_skb_fail: - free_skb_resources(priv); tx_skb_fail: - dma_free_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + - sizeof(*rxbdp) * priv->rx_ring_size, - priv->tx_bd_base, gfar_read(®s->tbase0)); + free_skb_resources(priv); return err; } -- 1.6.3.3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/8] gianfar: Some cleanups for startup_gfar()
We're going to split the startup_gfar() into 3 separate functions, so let's cleanup the code a little bit so that cosmetic changes won't distract attention from logical ones. - Remove needless casts (e.g. (struct sk_buff **)kmalloc()); - Turn 'unsigned long vaddr;' into 'void *vaddr', to avoid casting; - Add new 'struct device *dev' variable as a shorthand for '&priv->ofdev->dev' that is used all over the place, also rename 'struct net_device *dev' to 'struct net_device *ndev'; - Turn printk(KERN_ERR ...) to pr_err(...), which is shorter; - Don't return bogus -1 (i.e. -EPERM) when request_irq() fails; - Turn '&priv->regs->' to just '®s->'. Signed-off-by: Anton Vorontsov --- drivers/net/gianfar.c | 143 ++--- 1 files changed, 64 insertions(+), 79 deletions(-) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 5bf31f1..8c7322f 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -925,16 +925,17 @@ void gfar_start(struct net_device *dev) } /* Bring the controller up and running */ -int startup_gfar(struct net_device *dev) +int startup_gfar(struct net_device *ndev) { struct txbd8 *txbdp; struct rxbd8 *rxbdp; dma_addr_t addr = 0; - unsigned long vaddr; + void *vaddr; int i; - struct gfar_private *priv = netdev_priv(dev); + struct gfar_private *priv = netdev_priv(ndev); + struct device *dev = &priv->ofdev->dev; struct gfar __iomem *regs = priv->regs; - int err = 0; + int err; u32 rctrl = 0; u32 tctrl = 0; u32 attrs = 0; @@ -942,38 +943,34 @@ int startup_gfar(struct net_device *dev) gfar_write(®s->imask, IMASK_INIT_CLEAR); /* Allocate memory for the buffer descriptors */ - vaddr = (unsigned long) dma_alloc_coherent(&priv->ofdev->dev, - sizeof (struct txbd8) * priv->tx_ring_size + - sizeof (struct rxbd8) * priv->rx_ring_size, - &addr, GFP_KERNEL); - - if (vaddr == 0) { + vaddr = dma_alloc_coherent(dev, sizeof(*txbdp) * priv->tx_ring_size + + sizeof(*rxbdp) * priv->rx_ring_size, + &addr, GFP_KERNEL); + if (!vaddr) { if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n", - dev->name); + pr_err("%s: Could not allocate buffer descriptors!\n", + ndev->name); return -ENOMEM; } - priv->tx_bd_base = (struct txbd8 *) vaddr; + priv->tx_bd_base = vaddr; /* enet DMA only understands physical addresses */ gfar_write(®s->tbase0, addr); /* Start the rx descriptor ring where the tx ring leaves off */ - addr = addr + sizeof (struct txbd8) * priv->tx_ring_size; - vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size; - priv->rx_bd_base = (struct rxbd8 *) vaddr; + addr = addr + sizeof(*txbdp) * priv->tx_ring_size; + vaddr = vaddr + sizeof(*txbdp) * priv->tx_ring_size; + priv->rx_bd_base = vaddr; gfar_write(®s->rbase0, addr); /* Setup the skbuff rings */ - priv->tx_skbuff = - (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) * - priv->tx_ring_size, GFP_KERNEL); - - if (NULL == priv->tx_skbuff) { + priv->tx_skbuff = kmalloc(sizeof(*priv->tx_skbuff) * + priv->tx_ring_size, GFP_KERNEL); + if (!priv->tx_skbuff) { if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate tx_skbuff\n", - dev->name); + pr_err("%s: Could not allocate tx_skbuff\n", + ndev->name); err = -ENOMEM; goto tx_skb_fail; } @@ -981,14 +978,12 @@ int startup_gfar(struct net_device *dev) for (i = 0; i < priv->tx_ring_size; i++) priv->tx_skbuff[i] = NULL; - priv->rx_skbuff = - (struct sk_buff **) kmalloc(sizeof (struct sk_buff *) * - priv->rx_ring_size, GFP_KERNEL); - - if (NULL == priv->rx_skbuff) { + priv->rx_skbuff = kmalloc(sizeof(*priv->rx_skbuff) * + priv->rx_ring_size, GFP_KERNEL); + if (!priv->rx_skbuff) { if (netif_msg_ifup(priv)) - printk(KERN_ERR "%s: Could not allocate rx_skbuff\n", - dev->name); + pr_err("%s: Could not allocate rx_skbuff\n", + ndev->name); err = -ENOMEM; goto rx_skb_fail; } @@ -1019,18 +1014,16 @@ int startup_gfar(struct ne
[PATCH 0/8] gianfar: Add support for hibernation
Hi all, Here are few patches that add support for hibernation for gianfar driver. Technically, we could just do gfar_close() and then gfar_enet_open() sequence to restore gianfar functionality after hibernation, but close/open does so many unneeded things (e.g. BDs buffers freeing and allocation, IRQ freeing and requesting), that I felt it would be much better to cleanup and refactor some code to make the hibernation [and not only hibernation] code a little bit prettier. Patches on the way... Thanks, -- Anton Vorontsov email: cbouatmai...@gmail.com irc://irc.freenode.net/bd2 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] of/platform: Implement support for dev_pm_ops
Linux power management subsystem supports vast amount of new PM callbacks that are crucial for proper suspend and hibernation support in drivers. This patch implements support for dev_pm_ops, preserving support for legacy callbacks. Signed-off-by: Anton Vorontsov --- drivers/of/platform.c | 305 ++--- 1 files changed, 290 insertions(+), 15 deletions(-) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 298de0f..d58ade1 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -65,47 +65,322 @@ static int of_platform_device_remove(struct device *dev) return 0; } -static int of_platform_device_suspend(struct device *dev, pm_message_t state) +static void of_platform_device_shutdown(struct device *dev) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); - int error = 0; - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; + if (dev->driver && drv->shutdown) + drv->shutdown(of_dev); } -static int of_platform_device_resume(struct device * dev) +#ifdef CONFIG_PM_SLEEP + +static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); - int error = 0; + int ret = 0; - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; + if (dev->driver && drv->suspend) + ret = drv->suspend(of_dev, mesg); + return ret; } -static void of_platform_device_shutdown(struct device *dev) +static int of_platform_legacy_resume(struct device *dev) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); + int ret = 0; - if (dev->driver && drv->shutdown) - drv->shutdown(of_dev); + if (dev->driver && drv->resume) + ret = drv->resume(of_dev); + return ret; +} + +static int of_platform_pm_prepare(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (drv && drv->pm && drv->pm->prepare) + ret = drv->pm->prepare(dev); + + return ret; +} + +static void of_platform_pm_complete(struct device *dev) +{ + struct device_driver *drv = dev->driver; + + if (drv && drv->pm && drv->pm->complete) + drv->pm->complete(dev); +} + +#ifdef CONFIG_SUSPEND + +static int of_platform_pm_suspend(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend) + ret = drv->pm->suspend(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND); + } + + return ret; } +static int of_platform_pm_suspend_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend_noirq) + ret = drv->pm->suspend_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_resume(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume) + ret = drv->pm->resume(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_resume_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume_noirq) + ret = drv->pm->resume_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_SUSPEND */ + +#define of_platform_pm_suspend NULL +#define of_platform_pm_resume NULL +#define of_platform_pm_suspend_noirq NULL +#define of_platform_pm_resume_noirqNULL + +#endif /* !CONFIG_SUSPEND */ + +#ifdef CONFIG_HIBERNATION + +static int of_platform_pm_freeze(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze) + ret = drv->pm->freeze(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_FREEZE); + } + + return ret; +} + +static int of_platform_pm_freeze_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) +
Re: Linux seamless booting
Yes, that's what we're currently using, but the problem is a little broader: I should answer to CAN messages in at most 100-200ms from powerup, and that can be done in u-boot. However, handing CAN transmission control over to Linux is quite complicated nowadays, since it would involve passing structures in memory and hacking through device init. It'd be nice to have a framework with which u-boot could hand-over devices to Linux in a clean and defined way. We were thinking about starting some kind of development in that direction, but with very little resources, so I was looking for someone who had looked at the same problem. Thanks, Matteo Roberto Guerra ha scritto: Did you try "setenv bootdelay 0" in uboot? On Mon, Oct 12, 2009 at 7:07 AM, Fortini Matteo wrote: Hi all, we've been working on a PPC512x board booting with u-boot + linux 2.6.24.6, and one major issue for our application is boot time. Right now, we went down to less than 6s boot time (i.e. time from power off to launch of the user app), even with some drivers installed, i.e.: * CAN bus * GPU on PCI bus * USB host * UBI with r/o squashfs root and r/w ubifs configuration filesystem mounted from a NOR flash memory. This time could be enough for the high-level application (we're showing a splash screen in about 2-3s so it's ok if the main app takes a little longer to come up), but the whole system is connected to others via CAN and we can't afford the "black out" period between u-boot and linux. Some other operating systems (e.g. QNX) have this "seamless booting" function, in which drivers are started in stages, so that a (minimal) functionality can be given in milliseconds, and more functionalities come up as time goes by. Is there a way to support something similar with the u-boot -> linux solution? Thank you, Matteo ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev . ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: linux booting fails on ppc440x5 with SRAM
Hi Wolfgang, The link says about the initialization of the SDRAM; Does it applicable in our case, where we have SRAM on our board. Does the initialization means just clearing the memory in case of SRAM ? We tried clearing the memory before the operation which doesnt work too. We are creating a TLB of 16MB for the SRAM which is not cachable. -Vineeth On Fri, Oct 9, 2009 at 5:03 PM, Wolfgang Denk wrote: > Dear Vineeth _, > > In message you > wrote: >> We ported the uboot Memory test and tested the 15MB ram and it was >> successful.interestingly we have only 16MB SRAM in our board.We used 1 > > Such a memory test means nothing. The only thing you can learn from it > is that basic read and write accesses are working. You don;t get any > information about the behaviour for burst mode accesses from such a > test. See the FAQ at > http://www.denx.de/wiki/view/DULG/LinuxCrashesRandomly and at > http://www.denx.de/wiki/DULG/UBootCrashAfterRelocation > > Best regards, > > Wolfgang Denk > > -- > DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany > Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: w...@denx.de > I mean, I . . . think to understand you, I just don't know what you > are saying ... - Terry Pratchett, _Soul Music_ > ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: Linux seamless booting
Did you try "setenv bootdelay 0" in uboot? On Mon, Oct 12, 2009 at 7:07 AM, Fortini Matteo wrote: > Hi all, > we've been working on a PPC512x board booting with u-boot + linux 2.6.24.6, > and one major issue for our application is boot time. > > Right now, we went down to less than 6s boot time (i.e. time from power off > to launch of the user app), even with some drivers installed, i.e.: > > * CAN bus > * GPU on PCI bus > * USB host > * UBI > > with r/o squashfs root and r/w ubifs configuration filesystem mounted from a > NOR flash memory. > > This time could be enough for the high-level application (we're showing a > splash screen in about 2-3s so it's ok if the main app takes a little longer > to come up), but the whole system is connected to others via CAN and we > can't afford the "black out" period between u-boot and linux. > > Some other operating systems (e.g. QNX) have this "seamless booting" > function, in which drivers are started in stages, so that a (minimal) > functionality can be given in milliseconds, and more functionalities come up > as time goes by. > > Is there a way to support something similar with the u-boot -> linux > solution? > > Thank you, > Matteo > ___ > Linuxppc-dev mailing list > Linuxppc-dev@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/linuxppc-dev > ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] spufs: Fix test in spufs_switch_log_read()
size_t len cannot be less than 0. Signed-off-by: Roel Kluin --- Or can this test be removed? diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 884e8bc..d4f304f 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -2494,7 +2494,7 @@ static ssize_t spufs_switch_log_read(struct file *file, char __user *buf, struct spu_context *ctx = SPUFS_I(inode)->i_ctx; int error = 0, cnt = 0; - if (!buf || len < 0) + if (!buf || (ssize_t)len < 0) return -EINVAL; error = spu_acquire(ctx); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] powerpc/40x: Cleanups for HCU4 board
On Fri, Oct 09, 2009 at 09:47:38PM +0200, Niklaus Giger wrote: >- hcu4.dts: Added definitions for 2 CAN (Intel 82527) >- hcu4.c: Some code for CPLD (special HW clock) and 2 CAN (Intel 82527) Same comments here as in the HCU5 patch. Drop the device_type for cpld and can, and use compatible properties please. josh ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/1] powerpc/40x: Add new PPC440EPx based board HCU5 of Netstal Maschinen
On Fri, Oct 09, 2009 at 10:11:05AM +0200, Niklaus Giger wrote: >Adds support for a HCU5 PPC405EPx based board from Netstal Maschinen AG. Should be 440EPx, no? Also, the subject should probably be "powerpc/44x". These are minor things, not really a big deal. Overall, nice patch. See below for a few more comments. >+ UART0: ser...@ef600300 { >+ device_type = "serial"; >+ compatible = "ns16550"; >+ reg = <0xef600300 0x0008>; >+ virtual-reg = <0xef600300>; >+ clock-frequency = <0>; /* Filled in by U-Boot */ >+ current-speed = <0>; /* Filled in by U-Boot */ I've been considering dropping the current-speed property entirely in most 4xx boards. Given that you have a bootargs specified in chosen that explicitly tells the kernel to use 115200, do you think you could drop this property and see how things work? >+ interrupt-parent = <&UIC0>; >+ interrupts = <0x0 0x4>; >+ }; >+ >+ IIC0: i...@ef600700 { >+ #address-cells = <1>; >+ #size-cells = <0>; >+ compatible = "ibm,iic-440epx", "ibm,iic"; >+ reg = <0xef600700 0x0014>; >+ interrupt-parent = <&UIC0>; >+ interrupts = <0x2 0x4>; >+ }; >+ >+ IIC1: i...@ef600800 { >+ #address-cells = <1>; >+ #size-cells = <0>; >+ compatible = "ibm,iic-440epx", "ibm,iic"; >+ reg = <0xef600800 0x0014>; >+ interrupt-parent = <&UIC0>; >+ interrupts = <0x7 0x4>; >+ }; >+ >+ >+ ZMII0: emac-z...@ef600d00 { >+ compatible = "ibm,zmii-440epx", "ibm,zmii"; >+ reg = <0xef600d00 0x000c>; >+ }; >+ >+ SMII0: emac-s...@ef601000 { >+ compatible = "ibm,smii-440epx", >"ibm,smmii"; >+ reg = <0xef601000 0x0008>; >+ has-mdio; >+ }; >+ >+ EMAC0: ether...@ef600e00 { >+ device_type = "network"; >+ compatible = "ibm,emac-440epx", "ibm,emac4"; >+ interrupt-parent = <&EMAC0>; >+ interrupts = <0x0 0x1>; >+ #interrupt-cells = <1>; >+ #address-cells = <0>; >+ #size-cells = <0>; >+ interrupt-map = + /*Wake*/ 0x1 &UIC1 0x1d 0x4>; >+ reg = <0xef600e00 0x0074>; >+ local-mac-address = []; >+ mal-device = <&MAL0>; >+ mal-tx-channel = <0>; >+ mal-rx-channel = <0>; >+ cell-index = <0>; >+ max-frame-size = <9000>; >+ rx-fifo-size = <4096>; >+ tx-fifo-size = <2048>; >+ phy-mode = "smii"; >+ phy-map = <1>; >+ zmii-device = <&ZMII0>; >+ zmii-channel = <0>; >+ has-inverted-stacr-oc; >+ has-new-stacr-staopc; >+ }; >+ >+ CPLD: c...@0xcd00 { >+ reg = <0xcd00 0x0100>; >+ interval = "1000"; >+ device_type = "cpld"; Should drop the device_type. >+ interrupt-parent = <&UIC1>; >+ interrupts = <28 8>; /* 8 is IRQ_TYPE_LEVEL_LOW >*/ >+ }; >+ >+ /* The HCU5 has two Intel CAN SCC82527 controllers */ >+ CAN1: c...@0xc800 { >+ device_type = "can1"; Same comment here and for the one below as well. >+ compatible = "intel,82527"; >+ reg = <0xc80 0x0100>; >+ interrupt-parent = <&UIC2>; >+ interrupts = <3 8>; /* 8 is IRQ_TYPE_LEVEL_LOW >*/ >+ }; >+ >+ CAN2: c...@0xc8000100 { >+
Linux seamless booting
Hi all, we've been working on a PPC512x board booting with u-boot + linux 2.6.24.6, and one major issue for our application is boot time. Right now, we went down to less than 6s boot time (i.e. time from power off to launch of the user app), even with some drivers installed, i.e.: * CAN bus * GPU on PCI bus * USB host * UBI with r/o squashfs root and r/w ubifs configuration filesystem mounted from a NOR flash memory. This time could be enough for the high-level application (we're showing a splash screen in about 2-3s so it's ok if the main app takes a little longer to come up), but the whole system is connected to others via CAN and we can't afford the "black out" period between u-boot and linux. Some other operating systems (e.g. QNX) have this "seamless booting" function, in which drivers are started in stages, so that a (minimal) functionality can be given in milliseconds, and more functionalities come up as time goes by. Is there a way to support something similar with the u-boot -> linux solution? Thank you, Matteo ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [v8 PATCH 1/8]: cpuidle: cleanup drivers/cpuidle/cpuidle.c
* Arun R B [2009-10-08 15:19:42]: > * Arun R Bharadwaj [2009-10-08 15:18:28]: > > This patch cleans up drivers/cpuidle/cpuidle.c > Earlier cpuidle assumed pm_idle as the default idle loop. Break that > assumption and make it more generic. cpuidle_idle_call() which is the > main idle loop of cpuidle is to be called by architectures which have > registered to cpuidle. > > Remove routines cpuidle_install/uninstall_idle_handler() which are not > needed anymore. > > [snip] /** > - * cpuidle_install_idle_handler - installs the cpuidle idle loop handler > - */ > -void cpuidle_install_idle_handler(void) > -{ > - if (enabled_devices && (pm_idle != cpuidle_idle_call)) { > - /* Make sure all changes finished before we switch to new idle > */ > - smp_wmb(); > - pm_idle = cpuidle_idle_call; > - } > -} > - > -/** > - * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler > - */ > -void cpuidle_uninstall_idle_handler(void) > -{ > - if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) { > - pm_idle = pm_idle_old; > - cpuidle_kick_cpus(); > - } > -} > - I see the routines above being called in from cpuidle_pause/resume_and_lock/unlock below and they are entries from ACPI on ACPI_PROCESSOR_NOTIFY_POWER and from the hotplug path, could you test them to make sure they are not broken. We also seem to be missing a cpuidle_kick_cpus() in cpuidle_pause_and_lock() [snip] -- Balbir ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] pasemi_mac: ethtool set settings support
From: Olof Johansson Date: Tue, 6 Oct 2009 11:11:23 -0500 > On Mon, Oct 05, 2009 at 05:31:24PM +0400, Valentine Barshak wrote: >> Add ethtool set settings to pasemi_mac_ethtool. >> >> Signed-off-by: Valentine Barshak > > Acked-by: Olof Johansson Applied to net-next-2.6, thanks. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [v8 PATCH 0/8]: cpuidle: Cleanup cpuidle/ Introduce cpuidle to POWER
* Arun R B [2009-10-08 15:18:28]: > Hi > > Please consider this for inclusion into the testing tree. > > This patchset introduces cpuidle infrastructure to POWER, prototyping > for pSeries, and also does a major refactoring of current x86 idle > power management and a cleanup of cpuidle infrastructure. > > Earlier discussions on the same can be found at: > > v7 --> http://lkml.org/lkml/2009/10/6/278 > v6 --> http://lkml.org/lkml/2009/9/22/180 > v5 --> http://lkml.org/lkml/2009/9/22/26 > v4 --> http://lkml.org/lkml/2009/9/1/133 > v3 --> http://lkml.org/lkml/2009/8/27/124 > v2 --> http://lkml.org/lkml/2009/8/26/233 > v1 --> http://lkml.org/lkml/2009/8/19/150 > > I looked at the changes and they are beginning to look very good. Some minor comments about comments in the individual patches. -- Balbir ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] powerpc: Fix hypervisor TLB batching
On Mon, 2009-10-12 at 18:47 +1100, Anton Blanchard wrote: > Profiling of a page fault scalability microbenchmark shows flush_hash_range > is not calling the batch hpte invalidate hcall (H_BULK_REMOVE). > > It turns out we have a duplicate firmware feature for hcall-bulk and the > current setup code stops after finding the first match. This meant we never > batch and always do individual invalidates. > > The patch below removes the duplicate and shifts FW_FEATURE_CMO to close > the gap. With the patch applied the single threaded page fault rate improves > from 217169 to 238755 per second on a POWER5 test box, a 10% improvement. > > Signed-off-by: Anton Blanchard > --- Good catch ! Ben. > Index: linux.trees.git/arch/powerpc/include/asm/firmware.h > === > --- linux.trees.git.orig/arch/powerpc/include/asm/firmware.h 2009-10-12 > 18:11:56.0 +1100 > +++ linux.trees.git/arch/powerpc/include/asm/firmware.h 2009-10-12 > 18:21:20.0 +1100 > @@ -37,7 +37,7 @@ > #define FW_FEATURE_VIO ASM_CONST(0x4000) > #define FW_FEATURE_RDMA ASM_CONST(0x8000) > #define FW_FEATURE_LLAN ASM_CONST(0x0001) > -#define FW_FEATURE_BULK ASM_CONST(0x0002) > +#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0002) > #define FW_FEATURE_XDABR ASM_CONST(0x0004) > #define FW_FEATURE_MULTITCE ASM_CONST(0x0008) > #define FW_FEATURE_SPLPARASM_CONST(0x0010) > @@ -45,8 +45,7 @@ > #define FW_FEATURE_LPAR ASM_CONST(0x0040) > #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0080) > #define FW_FEATURE_BEAT ASM_CONST(0x0100) > -#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0200) > -#define FW_FEATURE_CMO ASM_CONST(0x0400) > +#define FW_FEATURE_CMO ASM_CONST(0x0200) > > #ifndef __ASSEMBLY__ > > @@ -58,8 +57,9 @@ enum { > FW_FEATURE_PERF | FW_FEATURE_DUMP | FW_FEATURE_INTERRUPT | > FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ | > FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | > - FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE | > - FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO, > + FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR | > + FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | > + FW_FEATURE_CMO, > FW_FEATURE_PSERIES_ALWAYS = 0, > FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, > FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, > Index: linux.trees.git/arch/powerpc/platforms/pseries/firmware.c > === > --- linux.trees.git.orig/arch/powerpc/platforms/pseries/firmware.c > 2009-10-12 18:08:37.0 +1100 > +++ linux.trees.git/arch/powerpc/platforms/pseries/firmware.c 2009-10-12 > 18:12:54.0 +1100 > @@ -51,11 +51,10 @@ firmware_features_table[FIRMWARE_MAX_FEA > {FW_FEATURE_VIO,"hcall-vio"}, > {FW_FEATURE_RDMA, "hcall-rdma"}, > {FW_FEATURE_LLAN, "hcall-lLAN"}, > - {FW_FEATURE_BULK, "hcall-bulk"}, > + {FW_FEATURE_BULK_REMOVE,"hcall-bulk"}, > {FW_FEATURE_XDABR, "hcall-xdabr"}, > {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, > {FW_FEATURE_SPLPAR, "hcall-splpar"}, > - {FW_FEATURE_BULK_REMOVE,"hcall-bulk"}, > }; > > /* Build up the firmware features bitmask using the contents of ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] powerpc: Fix hypervisor TLB batching
Profiling of a page fault scalability microbenchmark shows flush_hash_range is not calling the batch hpte invalidate hcall (H_BULK_REMOVE). It turns out we have a duplicate firmware feature for hcall-bulk and the current setup code stops after finding the first match. This meant we never batch and always do individual invalidates. The patch below removes the duplicate and shifts FW_FEATURE_CMO to close the gap. With the patch applied the single threaded page fault rate improves from 217169 to 238755 per second on a POWER5 test box, a 10% improvement. Signed-off-by: Anton Blanchard --- Index: linux.trees.git/arch/powerpc/include/asm/firmware.h === --- linux.trees.git.orig/arch/powerpc/include/asm/firmware.h2009-10-12 18:11:56.0 +1100 +++ linux.trees.git/arch/powerpc/include/asm/firmware.h 2009-10-12 18:21:20.0 +1100 @@ -37,7 +37,7 @@ #define FW_FEATURE_VIO ASM_CONST(0x4000) #define FW_FEATURE_RDMAASM_CONST(0x8000) #define FW_FEATURE_LLANASM_CONST(0x0001) -#define FW_FEATURE_BULKASM_CONST(0x0002) +#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0002) #define FW_FEATURE_XDABR ASM_CONST(0x0004) #define FW_FEATURE_MULTITCEASM_CONST(0x0008) #define FW_FEATURE_SPLPAR ASM_CONST(0x0010) @@ -45,8 +45,7 @@ #define FW_FEATURE_LPARASM_CONST(0x0040) #define FW_FEATURE_PS3_LV1 ASM_CONST(0x0080) #define FW_FEATURE_BEATASM_CONST(0x0100) -#define FW_FEATURE_BULK_REMOVE ASM_CONST(0x0200) -#define FW_FEATURE_CMO ASM_CONST(0x0400) +#define FW_FEATURE_CMO ASM_CONST(0x0200) #ifndef __ASSEMBLY__ @@ -58,8 +57,9 @@ enum { FW_FEATURE_PERF | FW_FEATURE_DUMP | FW_FEATURE_INTERRUPT | FW_FEATURE_MIGRATE | FW_FEATURE_PERFMON | FW_FEATURE_CRQ | FW_FEATURE_VIO | FW_FEATURE_RDMA | FW_FEATURE_LLAN | - FW_FEATURE_BULK | FW_FEATURE_XDABR | FW_FEATURE_MULTITCE | - FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | FW_FEATURE_CMO, + FW_FEATURE_BULK_REMOVE | FW_FEATURE_XDABR | + FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR | + FW_FEATURE_CMO, FW_FEATURE_PSERIES_ALWAYS = 0, FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, Index: linux.trees.git/arch/powerpc/platforms/pseries/firmware.c === --- linux.trees.git.orig/arch/powerpc/platforms/pseries/firmware.c 2009-10-12 18:08:37.0 +1100 +++ linux.trees.git/arch/powerpc/platforms/pseries/firmware.c 2009-10-12 18:12:54.0 +1100 @@ -51,11 +51,10 @@ firmware_features_table[FIRMWARE_MAX_FEA {FW_FEATURE_VIO,"hcall-vio"}, {FW_FEATURE_RDMA, "hcall-rdma"}, {FW_FEATURE_LLAN, "hcall-lLAN"}, - {FW_FEATURE_BULK, "hcall-bulk"}, + {FW_FEATURE_BULK_REMOVE,"hcall-bulk"}, {FW_FEATURE_XDABR, "hcall-xdabr"}, {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, {FW_FEATURE_SPLPAR, "hcall-splpar"}, - {FW_FEATURE_BULK_REMOVE,"hcall-bulk"}, }; /* Build up the firmware features bitmask using the contents of ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 6/8] 8xx: Add missing Guarded setting in DTLB Error.
Benjamin Herrenschmidt wrote on 12/10/2009 07:46:14: > > On Mon, 2009-10-12 at 07:36 +0200, Joakim Tjernlund wrote: > > Benjamin Herrenschmidt wrote on 12/10/2009 > > 00:44:56: > > > On Mon, 2009-10-12 at 00:19 +0200, Joakim Tjernlund wrote: > > > > > > > > I hear you, I can remove DTLB error with an add on patch later if that > > > > is OK? > > > > I cannot remove the DARFix though, when I move that to do_page_fault(), > > > > I get > > > > duplicate TLB hits on the same insn. It is like when > > > > transfer_to_handler() > > > > executes rfi, the cpu restarts the the faulting insn instead of jumping > > > > to the page fault handler, not always but often. > > > > > > I'm not sure what you mean here ... > > > > Just that I need to keep the DAR fix for dcbX insn in the DTLB handler. If > > I try > > to move it to do_page_fault() I get a lot more DTLB errors for dcbX insn. > > I'm not sure why (ie, I didn't get your explanation about rfi and > restarting the faulting insn etc...) but ok, I don't mind having > the DAR fixup remain in the asm. It's the whole logic that looks > at the PTE and does things with it that I feel has no room in there :-) OK, I will send a removal patch too. > > BTW. Maybe the do_page_fault() thing comes from the fact that we > also go there via ITLB Error which doesn't set the DAR and > that's normal ? I had that idea to, but no. These have different traps numbers and address is set to SRR0 for ITLB and to DAR for DTLB. I test for DTLB trap number before doing anything. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] 8xx: Remove DIRTY pte handling in DTLB Error.
There is no need to do set the DIRTY bit directly in DTLB Error. Trap to do_page_fault() and let the generic MM code do the work. --- Ben, here it is :) arch/powerpc/kernel/head_8xx.S | 95 1 files changed, 0 insertions(+), 95 deletions(-) diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index db5207e..cb94f46 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -500,92 +500,6 @@ DataTLBError: cmpwi cr0, r10, 0x00f0 beq-FixDAR /* must be a buggy dcbX, icbi insn. */ DARFix:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */ - mfspr r11, SPRN_DSISR - /* As the DAR fixup may clear store we may have all 3 states zero. -* Make sure only 0x0200(store) falls down into DIRTY handling -*/ - andis. r11, r11, 0x4a00/* !translation, protection or store */ - srwir11, r11, 16 - cmpwi cr0, r11, 0x0200/* just store ? */ - bne 2f - /* Only Change bit left now, do it here as it is faster -* than trapping to the C fault handler. - */ - - /* The EA of a data TLB miss is automatically stored in the MD_EPN -* register. The EA of a data TLB error is automatically stored in -* the DAR, but not the MD_EPN register. We must copy the 20 most -* significant bits of the EA from the DAR to MD_EPN before we -* start walking the page tables. We also need to copy the CASID -* value from the M_CASID register. -* Addendum: The EA of a data TLB error is _supposed_ to be stored -* in DAR, but it seems that this doesn't happen in some cases, such -* as when the error is due to a dcbi instruction to a page with a -* TLB that doesn't have the changed bit set. In such cases, there -* does not appear to be any way to recover the EA of the error -* since it is neither in DAR nor MD_EPN. As a workaround, the -* _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs -* are initialized in mapin_ram(). This will avoid the problem, -* assuming we only use the dcbi instruction on kernel addresses. -*/ - - /* DAR is in r10 already */ - rlwinm r11, r10, 0, 0, 19 - ori r11, r11, MD_EVALID - mfspr r10, SPRN_M_CASID - rlwimi r11, r10, 0, 28, 31 - DO_8xx_CPU6(0x3780, r3) - mtspr SPRN_MD_EPN, r11 - - mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ - - /* If we are faulting a kernel address, we have to use the -* kernel page tables. -*/ - andi. r11, r10, 0x0800 - beq 3f - lis r11, swapper_pg_...@h - ori r11, r11, swapper_pg_...@l - rlwimi r10, r11, 0, 2, 19 -3: - lwz r11, 0(r10) /* Get the level 1 entry */ - rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ - beq 2f /* If zero, bail */ - - /* We have a pte table, so fetch the pte from the table. -*/ - ori r11, r11, 1 /* Set valid bit in physical L2 page */ - DO_8xx_CPU6(0x3b80, r3) - mtspr SPRN_MD_TWC, r11/* Load pte table base address */ - mfspr r10, SPRN_MD_TWC/* and get the pte address */ - lwz r10, 0(r10) /* Get the pte */ - /* Insert the Guarded flag into the TWC from the Linux PTE. -* It is bit 27 of both the Linux PTE and the TWC -*/ - rlwimi r11, r10, 0, 27, 27 - /* Insert the WriteThru flag into the TWC from the Linux PTE. -* It is bit 25 in the Linux PTE and bit 30 in the TWC -*/ - rlwimi r11, r10, 32-5, 30, 30 - DO_8xx_CPU6(0x3b80, r3) - mtspr SPRN_MD_TWC, r11 - mfspr r11, SPRN_MD_TWC/* get the pte address again */ - - ori r10, r10, _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HWWRITE - stw r10, 0(r11) /* and update pte in table */ - xorir10, r10, _PAGE_RW /* RW bit is inverted */ - - /* The Linux PTE won't go exactly into the MMU TLB. -* Software indicator bits 22 and 28 must be clear. -* Software indicator bits 24, 25, 26, and 27 must be -* set. All other Linux PTE bits control the behavior -* of the MMU. -*/ - li r11, 0x00f0 - mtspr SPRN_DAR,r11/* Tag DAR */ - rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ - DO_8xx_CPU6(0x3d80, r3) - mtspr SPRN_MD_RPN, r10/* Update TLB entry */ mfspr r10, SPRN_M_TW /* Restore registers */ lwz r11, 0(r0) @@ -594,15 +508,6 @@ DARFix:/* Return from dcbx instruction bug workaround, r10 holds value of DAR * #ifdef CONFIG_8xx_CPU6 lwz r3, 8(r0) #endif - rfi -2: - mfspr r10, SPRN_M_TW /* Res