LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 15/15] ppc/vio: ensure dma_coherent_mask is set
From: Benjamin Herrenschmidt @ 2010-11-29  1:02 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <1284573958-8397-16-git-send-email-nacc@us.ibm.com>

On Wed, 2010-09-15 at 11:05 -0700, Nishanth Aravamudan wrote:
> Without this change drivers, such as ibmvscsi, fail to load with the
> previous change.
> ---

So you broke bisection... fold the patch instead or invert them

Cheers,
Ben.

>  arch/powerpc/kernel/vio.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
> index 3c3083f..e8d73de 100644
> --- a/arch/powerpc/kernel/vio.c
> +++ b/arch/powerpc/kernel/vio.c
> @@ -1259,6 +1259,9 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
>  	viodev->dev.parent = &vio_bus_device.dev;
>  	viodev->dev.bus = &vio_bus_type;
>  	viodev->dev.release = vio_dev_release;
> +        /* needed to ensure proper operation of coherent allocations
> +         * later, in case driver doesn't set it explicitly */
> +        dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
>  
>  	/* register with generic device framework */
>  	if (device_register(&viodev->dev)) {

^ permalink raw reply

* Re: [PATCH 3/5] fpga: add basic CARMA board support
From: Stephen Neuendorffer @ 2010-11-29  3:35 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-kernel, Ira W. Snyder
In-Reply-To: <1290991094.32570.213.camel@pasglop>

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

On Sun, Nov 28, 2010 at 4:38 PM, Benjamin Herrenschmidt <
benh@kernel.crashing.org> wrote:

> On Wed, 2010-09-08 at 09:41 -0700, Ira W. Snyder wrote:
> > This adds basic support for the system controller FPGA on the OVRO CARMA
> > board. This patch only adds infrastructure that will be used by later
> > drivers.
>
> Oh and another comment ...
>
> I'm not sure about drivers/fpga ... in the end, one would expect such a
> directory to contain stuff to manipulate FPGAs in the sense of
> downloading bitfiles, instanciating devices (device-tree manipulation ?)
> etc...
>
> From what I see in your code, the fact that these are FPGAs is almost
> irrelevant, you are providing support for "carma" devices, and such are
> no different than some other platform device, they just happen to be
> implemented as FPGAs. Or am I missing something ?
>
> Cheers,
> Ben.
>
>
Generally, I agree with this: There doesn't seem to be anything generic
about
the FPGA support you are adding, it seems very specific to the CARMA
hardware.

I'm generally not opposed to drivers/fpga: I think that colocating drivers
for things
that are basically FPGA compute platforms isn't necessarily a bad idea, but
I think it would be better if those devices were colocated because they
shared
some FPGA-oriented infrastructure, which this doesn't seem to do.
Currently,
generic infrastructure has been going into drivers/char, and drivers
themselves have
been going wherever they seem best.  Really what you have is 2 character
devices: one
for configuration, and one for access.

Steve

[-- Attachment #2: Type: text/html, Size: 2129 bytes --]

^ permalink raw reply

* Re: [PATCH V2 2/3] powerpc: Poll VPA for topology changes and update NUMA maps
From: Benjamin Herrenschmidt @ 2010-11-29  3:44 UTC (permalink / raw)
  To: Jesse Larrew; +Cc: markn, pmac, tbreeds, lkessler, mjwolf, linuxppc-dev
In-Reply-To: <20101109232501.17098.55112.sendpatchset@manic8ball.ltc.austin.ibm.com>

On Tue, 2010-11-09 at 16:25 -0700, Jesse Larrew wrote:
> From: Jesse Larrew <jlarrew@linux.vnet.ibm.com>
> 
> This patch sets a timer during boot that will periodically poll the
> associativity change counters in the VPA. When a change in 
> associativity is detected, it retrieves the new associativity domain 
> information via the H_HOME_NODE_ASSOCIATIVITY hcall and updates the 
> NUMA node maps and sysfs entries accordingly. Note that since the 
> ibm,associativity device tree property does not exist on configurations 
> with both NUMA and SPLPAR enabled, no device tree updates are necessary.
> 
> Signed-off-by: Jesse Larrew <jlarrew@linux.vnet.ibm.com>
> ---

No fundamental objection, just quick nits before I merge:
> +
> +/* Vrtual Processor Home Node (VPHN) support */
> +#define VPHN_NR_CHANGE_CTRS (8)
> +static u8 vphn_cpu_change_counts[NR_CPUS][VPHN_NR_CHANGE_CTRS];
> +static cpumask_t cpu_associativity_changes_mask;
> +static void topology_work_fn(struct work_struct *work);
> +static DECLARE_WORK(topology_work, topology_work_fn);

Remove the prototype for topology_work_fn() and puts the DECLARE_WORK
right below the function itself.

> +static void topology_timer_fn(unsigned long ignored);
> +static struct timer_list topology_timer =
> +	TIMER_INITIALIZER(topology_timer_fn, 0, 0);

Same deal.

> +static void set_topology_timer(void);
> +int stop_topology_update(void);
> +
> +/*
> + * Store the current values of the associativity change counters in the
> + * hypervisor.
> + */
> +static void setup_cpu_associativity_change_counters(void)
> +{
> +	int cpu = 0;
> +
> +	for_each_possible_cpu(cpu) {
> +		int i = 0;
> +		u8 *counts = vphn_cpu_change_counts[cpu];
> +		volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts;
> +
> +		for (i = 0; i < VPHN_NR_CHANGE_CTRS; i++) {
> +			counts[i] = hypervisor_counts[i];
> +		}
> +	}
> +
> +	return;
> +}
> +
> +/*
> + * The hypervisor maintains a set of 8 associativity change counters in
> + * the VPA of each cpu that correspond to the associativity levels in the
> + * ibm,associativity-reference-points property. When an associativity
> + * level changes, the corresponding counter is incremented.
> + *
> + * Set a bit in cpu_associativity_changes_mask for each cpu whose home
> + * node associativity levels have changed.
> + */
> +static void update_cpu_associativity_changes_mask(void)
> +{
> +	int cpu = 0;
> +	cpumask_t *changes = &cpu_associativity_changes_mask;
> +
> +	cpumask_clear(changes);
> +
> +	for_each_possible_cpu(cpu) {
> +		int i;
> +		u8 *counts = vphn_cpu_change_counts[cpu];
> +		volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts;
> +
> +		for (i = 0; i < VPHN_NR_CHANGE_CTRS; i++) {
> +			if (hypervisor_counts[i] > counts[i]) {
> +				counts[i] = hypervisor_counts[i];
> +
> +				if (!(cpumask_test_cpu(cpu, changes)))
> +					cpumask_set_cpu(cpu, changes);
> +			}
> +		}

This is a tad sub-optimal. I'd just set a local variable, and
after the inside loop set the cpumask bit when that variable is set.

Also, keep another variable that accumulate all bits set and return
its value so you don't have to re-check the mask in the caller.

cpumask operations can be expensive.
 
> +	}
> +
> +	return;

You don't need a return; at the end of a function.

> +}
> +
> +/* 6 64-bit registers unpacked into 12 32-bit associativity values */
> +#define VPHN_ASSOC_BUFSIZE (6*sizeof(u64)/sizeof(u32))
> +
> +/*
> + * Convert the associativity domain numbers returned from the hypervisor
> + * to the sequence they would appear in the ibm,associativity property.
> + */
> +static int vphn_unpack_associativity(const long *packed, unsigned int *unpacked)
> +{
> +	int i = 0;
> +	int nr_assoc_doms = 0;
> +	const u16 *field = (const u16*) packed;
> +
> +#define VPHN_FIELD_UNUSED	(0xffff)
> +#define VPHN_FIELD_MSB		(0x8000)
> +#define VPHN_FIELD_MASK		(~VPHN_FIELD_MSB)
> +
> +	for (i = 0; i < VPHN_ASSOC_BUFSIZE; i++) {
> +		if (*field == VPHN_FIELD_UNUSED) {
> +			/* All significant fields processed, and remaining
> +			 * fields contain the reserved value of all 1's.
> +			 * Just store them.
> +			 */
> +			unpacked[i] = *((u32*)field);
> +			field += 2;
> +		}
> +		else if (*field & VPHN_FIELD_MSB) {
> +			/* Data is in the lower 15 bits of this field */
> +			unpacked[i] = *field & VPHN_FIELD_MASK;
> +			field++;
> +			nr_assoc_doms++;
> +		}
> +		else {
> +			/* Data is in the lower 15 bits of this field
> +			 * concatenated with the next 16 bit field
> +			 */
> +			unpacked[i] = *((u32*)field);
> +			field += 2;
> +			nr_assoc_doms++;
> +		}
> +	}
> +
> +	return nr_assoc_doms;
> +}
> +
> +/*
> + * Retrieve the new associativity information for a virtual processor's
> + * home node.
> + */
> +static long hcall_vphn(unsigned long cpu, unsigned int *associativity)
> +{
> +	long rc = 0;
> +	long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
> +	u64 flags = 1;
> +	int hwcpu = get_hard_smp_processor_id(cpu);
> +
> +	rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
> +	vphn_unpack_associativity(retbuf, associativity);
> +
> +	return rc;
> +}
> +
> +static long
> +vphn_get_associativity(unsigned long cpu, unsigned int *associativity)
> +{

Nowadays, we prefer keeping the "static long" and the function name on
the same line. If you really want to avoid >80 col (I don't care myself
much as long as you stick below 100) then move the second argument down
one line.

> +	long rc = 0;
> +
> +	rc = hcall_vphn(cpu, associativity);
> +
> +	switch (rc) {
> +	case H_FUNCTION:
> +		printk(KERN_INFO
> +			"VPHN is not supported. Disabling polling...\n");
> +		stop_topology_update();
> +		break;
> +	case H_HARDWARE:
> +		printk(KERN_ERR
> +			"hcall_vphn() experienced a hardware fault "
> +			"preventing VPHN. Disabling polling...\n");
> +		stop_topology_update();
> +	}
> +
> +	return rc;
> +}
> +
> +/*
> + * Update the node maps and sysfs entries for each cpu whose home node
> + * has changed.
> + */
> +int arch_update_cpu_topology(void)
> +{
> +	int cpu = 0, nid = 0, old_nid = 0;
> +	unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
> +	struct sys_device *sysdev = NULL;
> +
> +	for_each_cpu_mask(cpu, cpu_associativity_changes_mask) {
> +		vphn_get_associativity(cpu, associativity);
> +		nid = associativity_to_nid(associativity);
> +
> +		if (nid < 0 || !node_online(nid))
> +			nid = first_online_node;
> +
> +		old_nid = numa_cpu_lookup_table[cpu];
> +
> +		/* Disable hotplug while we update the cpu
> +		 * masks and sysfs.
> +		 */
> +		get_online_cpus();
> +		unregister_cpu_under_node(cpu, old_nid);
> +		unmap_cpu_from_node(cpu);
> +		map_cpu_to_node(cpu, nid);
> +		register_cpu_under_node(cpu, nid);
> +		put_online_cpus();
> +
> +		sysdev = get_cpu_sysdev(cpu);
> +		if (sysdev)
> +			kobject_uevent(&sysdev->kobj, KOBJ_CHANGE);
> +	}
> +
> +	return 1;
> +}

That looks terribly expensive. Might be worth considering adding a way
to sysfs to "mv" an object around in the future.

> +static void topology_work_fn(struct work_struct *work)
> +{
> +	rebuild_sched_domains();
> +}
> +
> +void topology_schedule_update(void)
> +{
> +	schedule_work(&topology_work);
> +}
> +
> +static void topology_timer_fn(unsigned long ignored)
> +{
> +	update_cpu_associativity_changes_mask();
> +	if (!cpumask_empty(&cpu_associativity_changes_mask))
> +		topology_schedule_update();
> +	set_topology_timer();
> +}

I wonder if we really need that cpumask and timer overall. We might be
better off just having a per-cpu copy of the counters and check them in
the timer interrupt, it's low enough overhead don't you think ?

> +static void set_topology_timer(void)
> +{
> +	topology_timer.data = 0;
> +	topology_timer.expires = jiffies + 60 * HZ;
> +	add_timer(&topology_timer);
> +}
> +
> +/*
> + * Start polling for VPHN associativity changes.
> + */
> +int start_topology_update(void)
> +{
> +	int rc = 0;
> +
> +	if (firmware_has_feature(FW_FEATURE_VPHN)) {
> +		setup_cpu_associativity_change_counters();
> +		init_timer_deferrable(&topology_timer);
> +		set_topology_timer();
> +		rc = 1;
> +	}
> +
> +	return rc;
> +}
> +__initcall(start_topology_update);
> +
> +/*
> + * Disable polling for VPHN associativity changes.
> + */
> +int stop_topology_update(void)
> +{
> +	return del_timer(&topology_timer);
> +}

del_timer_sync() ?

Cheers,
Ben.

^ permalink raw reply

* [PATCH] powerpc: Record vma->phys_addr in ioremap()
From: Michael Ellerman @ 2010-11-29  4:26 UTC (permalink / raw)
  To: linuxppc-dev

The vmalloc code can track the physical address of a vma, when the
vma is used for ioremap, if set it is displayed in /proc/vmallocinfo.

Because get_vm_area_caller() doesn't know it's being called for
ioremap() it's up to the arch code to set the phys_addr. A bunch
of other arch's do this, I'm not sure why powerpc doesn't?

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/mm/pgtable_32.c |    1 +
 arch/powerpc/mm/pgtable_64.c |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index a87ead0..71932d0 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -230,6 +230,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
 		area = get_vm_area_caller(size, VM_IOREMAP, caller);
 		if (area == 0)
 			return NULL;
+		area->phys_addr = p;
 		v = (unsigned long) area->addr;
 	} else {
 		v = (ioremap_bot -= size);
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 21d6dfa..88927a0 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -223,6 +223,8 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size,
 					    caller);
 		if (area == NULL)
 			return NULL;
+
+		area->phys_addr = paligned;
 		ret = __ioremap_at(paligned, area->addr, size, flags);
 		if (!ret)
 			vunmap(area->addr);
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH] powerpc: Record vma->phys_addr in ioremap()
From: Benjamin Herrenschmidt @ 2010-11-29  4:56 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev
In-Reply-To: <e4aea657faf920a0d207e582724ccd7ef08487f1.1291004790.git.michael@ellerman.id.au>

On Mon, 2010-11-29 at 15:26 +1100, Michael Ellerman wrote:
> The vmalloc code can track the physical address of a vma, when the
> vma is used for ioremap, if set it is displayed in /proc/vmallocinfo.
> 
> Because get_vm_area_caller() doesn't know it's being called for
> ioremap() it's up to the arch code to set the phys_addr. A bunch
> of other arch's do this, I'm not sure why powerpc doesn't?

Because I never noticed ? :-)

Cheers,
Ben.

> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
>  arch/powerpc/mm/pgtable_32.c |    1 +
>  arch/powerpc/mm/pgtable_64.c |    2 ++
>  2 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
> index a87ead0..71932d0 100644
> --- a/arch/powerpc/mm/pgtable_32.c
> +++ b/arch/powerpc/mm/pgtable_32.c
> @@ -230,6 +230,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
>  		area = get_vm_area_caller(size, VM_IOREMAP, caller);
>  		if (area == 0)
>  			return NULL;
> +		area->phys_addr = p;
>  		v = (unsigned long) area->addr;
>  	} else {
>  		v = (ioremap_bot -= size);
> diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
> index 21d6dfa..88927a0 100644
> --- a/arch/powerpc/mm/pgtable_64.c
> +++ b/arch/powerpc/mm/pgtable_64.c
> @@ -223,6 +223,8 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size,
>  					    caller);
>  		if (area == NULL)
>  			return NULL;
> +
> +		area->phys_addr = paligned;
>  		ret = __ioremap_at(paligned, area->addr, size, flags);
>  		if (!ret)
>  			vunmap(area->addr);

^ permalink raw reply

* Re: [PATCH] powerpc: Record vma->phys_addr in ioremap()
From: Michael Ellerman @ 2010-11-29  5:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1291006613.32570.288.camel@pasglop>

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

On Mon, 2010-11-29 at 15:56 +1100, Benjamin Herrenschmidt wrote:
> On Mon, 2010-11-29 at 15:26 +1100, Michael Ellerman wrote:
> > The vmalloc code can track the physical address of a vma, when the
> > vma is used for ioremap, if set it is displayed in /proc/vmallocinfo.
> > 
> > Because get_vm_area_caller() doesn't know it's being called for
> > ioremap() it's up to the arch code to set the phys_addr. A bunch
> > of other arch's do this, I'm not sure why powerpc doesn't?
> 
> Because I never noticed ? :-)

Yeah I figured. It seems to go back past 2.6.12 so who knows when it
went in, anyway it's useful.

cheers


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

^ permalink raw reply

* Re: Pegasos OHCI bug (was Re: PROBLEM: memory corrupting bug,
From: Benjamin Herrenschmidt @ 2010-11-29  5:44 UTC (permalink / raw)
  To: pacman; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20101105064332.1678.qmail@kosh.dhis.org>


> I have a mostly-finished patch to do the above. I'll include it below, but
> first a few words about why it's only mostly finished.
> 
> The other Pegasos workarounds are in fixup_device_tree_chrp, and I don't see
> anything like an "if(machine_is_pegasos)" around them. What keeps them from
> being erroneously run on other CHRP-type machines? I made this patch mainly
> by copying pieces of other functions from prom_init.c, but couldn't find the
> "test for Pegasos before running a Pegasos workaround" piece.

Probably bcs the condition they test for really only happens on
pegasos ? :-)

I agree it's a bit gross tho.

The "ranges" property fixup is pretty harmless in any case. The other
fixup might be worth moving to a separate pegasos-only function in which
you would test for a pegasos properly and add your own stuff.

> Another issue is, since the firmware doesn't give me a "compatible" property
> with the details of the controller, I just have to assume that it's
> little-endian. I'm not sure if that's clean, since the real ohci driver
> supports both endiannesses, with at least 3 different Kconfig options(!) to
> choose between them.

If it's PCI it's LE or somebody needs to be shot :-)

> Then there's the volatile which I guess is supposed to be replaced by
> something else, but I don't know what the something else is. I believe this
> usage is extremely close to what volatile was meant for.

Yeah, it's fine, just add something like that on the next line:

 asm volatile("eieio" : : : "memory");

> Finally, when I updated to a more recent upstream kernel to test the patch, I
> found that an intervening commit (3df7169e73fc1d71a39cffeacc969f6840cdf52b,
> OHCI: work around for nVidia shutdown problem) has had a major effect,
> on the appearance of my bug.
> 
> Before that change, the window in which the bug could strike was from the end
> of prom_init (when the kernel believes that devices are quiescent) to the
> initialization of the ohci-hcd driver (which actually quietens the device, or
> at least directs its scribbling to a properly allocated page). After the
> change, the window ends at some point early in the PCI bus setup. That's a
> window so small that with a new kernel, I can't provoke a symptom even if I
> try.

Right but it's very fishy, ie, it may still be DMA'ing and god knows
where ... you may or may not get lucky. I'd rather you do a proper
fixup :-)

Cheers,
Ben.

> Mostly-finished patch:
> 
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index 941ff4d..a14f21b 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -2237,6 +2237,81 @@ static void __init fixup_device_tree_chrp(void)
>  		}
>  	}
>  }
> +
> +/*
> + * Pegasos firmware doesn't quiesce OHCI controllers, so do it manually
> + */
> +static void __init pegasos_quiesce(void)
> +{
> +	phandle node, parent_node;
> +	ihandle parent_ih;
> +	int rc;
> +	char type[16], *path;
> +	u32 prop[5], map_size;
> +	prom_arg_t ohci_virt;
> +
> +	for (node = 0; prom_next_node(&node); ) {
> +		memset(type, 0, sizeof(type));
> +		prom_getprop(node, "device_type", type, sizeof(type));
> +		if (strcmp(type, RELOC("usb")) != 0)
> +			continue;
> +
> +		/* Parent should be a PCI bus (so class-code makes sense).
> +		   class-code should be 0x0C0310 */
> +		parent_node = call_prom("parent", 1, 1, node);
> +		if (!parent_node)
> +			continue;
> +		rc = prom_getprop(node, "class-code", prop, sizeof(u32));
> +		if (rc != sizeof(u32) || prop[0] != 0x0c0310)
> +			continue;
> +
> +		rc = prom_getprop(node, "assigned-addresses",
> +				  prop, 5*sizeof(u32));
> +		if (rc != 5*sizeof(u32))
> +			continue;
> +
> +		/* Open the parent and call map-in */
> +
> +		/* It seems OF doesn't null-terminate the path :-( */
> +		path = RELOC(prom_scratch);
> +		memset(path, 0, PROM_SCRATCH_SIZE);
> +
> +		if (call_prom("package-to-path", 3, 1, parent_node,
> +			      path, PROM_SCRATCH_SIZE-1) == PROM_ERROR)
> +			continue;
> +		parent_ih = call_prom("open", 1, 1, path);
> +
> +		/* Get the OHCI node's pathname, for printing later */
> +		memset(path, 0, PROM_SCRATCH_SIZE);
> +		call_prom("package-to-path", 3, 1, node,
> +			  path, PROM_SCRATCH_SIZE-1);
> +
> +		map_size = prop[4];
> +		if (call_prom_ret("call-method", 6, 2, &ohci_virt,
> +				  ADDR("map-in"), parent_ih,
> +				  map_size, prop[0], prop[1], prop[2]) == 0) {
> +			prom_printf("resetting OHCI device %s...", path);
> +
> +			/* Set HostControllerReset (==1) in HcCommandStatus,
> +			 * located at offset 8 in the register area. The <<24
> +			 * is because the CPU is big-endian and the device is
> +			 * little-endian. */
> +			*(volatile u32 *)(ohci_virt + 8) |= (1<<24);
> +
> +			/* controller should acknowledge by zeroing the bit
> +			 * within 10us. waiting 1ms should be plenty. */
> +			call_prom("interpret", 1, 1, "1 ms");
> +			if (*(volatile u32 *)(ohci_virt + 8) & (1<<24))
> +				prom_printf("failed\n");
> +			else
> +				prom_printf("done\n");
> +
> +			call_prom("call-method", 4, 1, ADDR("map-out"),
> +				  parent_ih, map_size, ohci_virt);
> +		}
> +		call_prom("close", 1, 0, parent_ih);
> +	}
> +}
>  #else
>  #define fixup_device_tree_chrp()
>  #endif
> @@ -2642,6 +2717,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
>  	 * devices etc...
>  	 */
>  	prom_printf("Calling quiesce...\n");
> +	pegasos_quiesce();
>  	call_prom("quiesce", 0, 0);
>  
>  	/*
> 

^ permalink raw reply

* Re: RFC: Mega rename of device tree routines from of_*() to dt_*()
From: David Gibson @ 2010-11-29  5:55 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: linux-arch, linux-mips, microblaze-uclinux, devicetree-discuss,
	LKML, linuxppc-dev list, sparclinux
In-Reply-To: <1290692075.689.20.camel@concordia>

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

On Fri, Nov 26, 2010 at 12:34:35AM +1100, Michael Ellerman wrote:
> On Thu, 2010-11-25 at 01:03 +1100, Michael Ellerman wrote:
> > Hi all,
> > 
> > There were some murmurings on IRC last week about renaming the of_*()
> > routines.
> ...
> > The thinking is that on many platforms that use the of_() routines
> > OpenFirmware is not involved at all, this is true even on many powerpc
> > platforms. Also for folks who don't know the OpenFirmware connection
> > it reads as "of", as in "a can of worms".
> ...
> > So I'm hoping people with either say "YES this is a great idea", or "NO
> > this is stupid".
> 
> I'm still hoping, but so far it seems most people have got better things
> to do, and of those that do have an opinion the balance is slightly
> positive.
> 
> So here's a first cut of a patch to add the new names. I've not touched
> of_platform because that is supposed to go away. That will lead to some
> odd looking code in the interim, but I think is the right approach.
> 
> Most of these are straight renames, but some have changed more
> substantially. The routines for the flat tree have all become fdt_foo().

I'm a little uneasy about using the same prefix as libfdt (fdt_foo())
for routines that have a different implementation and different names
/ semantics to the libfdt routines.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: RFC: Mega rename of device tree routines from of_*() to dt_*()
From: Grant Likely @ 2010-11-29  6:07 UTC (permalink / raw)
  To: Michael Ellerman, LKML, linux-arch, linux-mips,
	microblaze-uclinux, devicetree-discuss, linuxppc-dev list,
	sparclinux
In-Reply-To: <20101129055529.GB17113@yookeroo>

On Sun, Nov 28, 2010 at 10:55 PM, David Gibson
<david@gibson.dropbear.id.au> wrote:
> On Fri, Nov 26, 2010 at 12:34:35AM +1100, Michael Ellerman wrote:
>> Most of these are straight renames, but some have changed more
>> substantially. The routines for the flat tree have all become fdt_foo().
>
> I'm a little uneasy about using the same prefix as libfdt (fdt_foo())
> for routines that have a different implementation and different names
> / semantics to the libfdt routines.

I'd also be okay with either dtflat_ or flatdt_ for the prefix on
these routines.

g.

^ permalink raw reply

* Re: ppc_set_hwdebug vs ptrace_set_debugreg
From: K.Prasad @ 2010-11-29  7:22 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev, Dave Kleikamp
In-Reply-To: <m2lj4ezhhd.fsf@igel.home>

On Sat, Nov 27, 2010 at 08:36:30PM +0100, Andreas Schwab wrote:
> Why does ptrace_set_debugreg call register_user_hw_breakpoint, but
> ppc_set_hwdebug doesn't?  Shouldn't ppc_set_hwdebug set the
> DABR_DATA_(READ|WRITE|TRANSLATION) bits in the dabr?
> 
> Andreas.

The hw-breakpoint interfaces were initially planned for the old ptrace
option PTRACE_SET_DEBUGREG,while, the newer ptrace options are mostly
to exploit the advanced debug features of Book3E processors.

Although ppc_set_hwdebug() can set DABR through set_dabr() in
arch/powerpc/kernel/process.c, it is good to have it converted to use
register_user_hw_breakpoint(). This was planned to be done alongside the
conversion of all ptrace options enabled by CONFIG_PPC_ADV_DEBUG_REGS,
which is yet to be done.

Are you looking to use debug registers through perf, or somesuch, that
you need register_user_hw_breakpoint() to be used for these new ptrace
flags?

Thanks,
K.Prasad

^ permalink raw reply

* Re: ppc_set_hwdebug vs ptrace_set_debugreg
From: Andreas Schwab @ 2010-11-29 10:15 UTC (permalink / raw)
  To: prasad; +Cc: linuxppc-dev, Dave Kleikamp
In-Reply-To: <20101129072233.GA15560@in.ibm.com>

"K.Prasad" <prasad@linux.vnet.ibm.com> writes:

> Although ppc_set_hwdebug() can set DABR through set_dabr() in
> arch/powerpc/kernel/process.c, it is good to have it converted to use
> register_user_hw_breakpoint().

What do you mean with "good to have"?  It doesn't work without it unless
I disable PERF_EVENTS (which is the only way to disable
HAVE_HW_BREAKPOINT).

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* [PATCH v4] ppc44x:PHY fixup for USB on canyonlands board
From: Rupjyoti Sarmah @ 2010-11-29 13:13 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: rsarmah

This fix is a reset for USB PHY that requires some amount of time for power to be stable on Canyonlands.

Signed-off-by: Rupjyoti Sarmah <rsarmah@apm.com>
---
changes from previous version:
-- changed the dts node names for consistency
-- corrected the indentation pointed by Wolfgang Denk

 arch/powerpc/boot/dts/canyonlands.dts      |   13 +++
 arch/powerpc/platforms/44x/44x.h           |    4 +
 arch/powerpc/platforms/44x/Makefile        |    1 +
 arch/powerpc/platforms/44x/canyonlands.c   |  120 ++++++++++++++++++++++++++++
 arch/powerpc/platforms/44x/ppc44x_simple.c |    1 -
 5 files changed, 138 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/platforms/44x/canyonlands.c

diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index a303703..3c5d63c 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -224,6 +224,13 @@
 					};
 				};
 
+				cpld@2,0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "amcc,ppc460ex-bcsr";
+					reg = <2 0x0 0x9>;
+				};
+
 				ndfc@3,0 {
 					compatible = "ibm,ndfc";
 					reg = <0x00000003 0x00000000 0x00002000>;
@@ -320,6 +327,12 @@
 				interrupts = <0x3 0x4>;
 			};
 
+			GPIO0: gpio@ef600b00 {
+				compatible = "ibm,ppc4xx-gpio";
+				reg = <0xef600b00 0x00000048>;
+				gpio-controller;
+			};
+
 			ZMII0: emac-zmii@ef600d00 {
 				compatible = "ibm,zmii-460ex", "ibm,zmii";
 				reg = <0xef600d00 0x0000000c>;
diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h
index dbc4d2b..63f703e 100644
--- a/arch/powerpc/platforms/44x/44x.h
+++ b/arch/powerpc/platforms/44x/44x.h
@@ -4,4 +4,8 @@
 extern u8 as1_readb(volatile u8 __iomem  *addr);
 extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
 
+#define GPIO0_OSRH	0xC
+#define GPIO0_TSRH	0x14
+#define GPIO0_ISR1H	0x34
+
 #endif /* __POWERPC_PLATFORMS_44X_44X_H */
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 82ff326..6854e73 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_WARP)	+= warp.o
 obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
 obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
 obj-$(CONFIG_ISS4xx)	+= iss4xx.o
+obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
new file mode 100644
index 0000000..4917c31
--- /dev/null
+++ b/arch/powerpc/platforms/44x/canyonlands.c
@@ -0,0 +1,120 @@
+/*
+ * This contain platform specific code for APM PPC460EX based Canyonlands
+ * board.
+ *
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Rupjyoti Sarmah <rsarmah@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc4xx.h>
+#include <asm/udbg.h>
+#include <asm/uic.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+#include "44x.h"
+
+#define BCSR_USB_EN	0x11
+
+static __initdata struct of_device_id ppc44x_of_bus[] = {
+	{ .compatible = "ibm,plb4", },
+	{ .compatible = "ibm,opb", },
+	{ .compatible = "ibm,ebc", },
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+static int __init ppc44x_device_probe(void)
+{
+	of_platform_bus_probe(NULL, ppc44x_of_bus, NULL);
+
+	return 0;
+}
+machine_device_initcall(canyonlands, ppc44x_device_probe);
+
+/* Using this code only for the Canyonlands board.  */
+
+static int __init ppc44x_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+	if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
+		ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+		return 1;
+		}
+	return 0;
+}
+
+/* USB PHY fixup code on Canyonlands kit. */
+
+static int __init ppc460ex_canyonlands_fixup(void)
+{
+	u8 __iomem *bcsr ;
+	void __iomem *vaddr;
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-bcsr");
+	if (!np) {
+		printk(KERN_ERR "failed did not find amcc, ppc460ex bcsr node\n");
+		return -ENODEV;
+	}
+
+	bcsr = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!bcsr) {
+		printk(KERN_CRIT "Could not remap bcsr\n");
+		return -ENODEV;
+	}
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,ppc4xx-gpio");
+	vaddr = of_iomap(np, 0);
+	if (!vaddr) {
+		printk(KERN_CRIT "Could not get gpio node address\n");
+		return -ENODEV;
+	}
+	/* Disable USB, through the BCSR7 bits */
+	setbits8(&bcsr[7], BCSR_USB_EN);
+
+	/* Wait for a while after reset */
+	msleep(100);
+
+	/* Enable USB here */
+	clrbits8(&bcsr[7], BCSR_USB_EN);
+
+	/*
+	 * Configure multiplexed gpio16 and gpio19 as alternate1 output
+	 * source after USB reset.This configuration is done through GPIO0_TSRH
+	 * and GPIO0_OSRH bits 0:1 and 6:7.
+	 */
+	setbits32((vaddr + GPIO0_OSRH), 0x42000000);
+	setbits32((vaddr + GPIO0_TSRH), 0x42000000);
+	of_node_put(np);
+	return 0;
+}
+machine_device_initcall(canyonlands, ppc460ex_canyonlands_fixup);
+define_machine(canyonlands) {
+	.name = "Canyonlands",
+	.probe = ppc44x_probe,
+	.progress = udbg_progress,
+	.init_IRQ = uic_init_tree,
+	.get_irq = uic_get_irq,
+	.restart = ppc4xx_reset_system,
+	.calibrate_decr = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 7ddcba3..c81c19c 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -53,7 +53,6 @@ static char *board[] __initdata = {
 	"amcc,arches",
 	"amcc,bamboo",
 	"amcc,bluestone",
-	"amcc,canyonlands",
 	"amcc,glacier",
 	"ibm,ebony",
 	"amcc,eiger",
-- 
1.5.6.3

^ permalink raw reply related

* Re: [PATCH][v2] Fixing the garbage collector problem after NAND-flash image record in u-boot
From: Artem Bityutskiy @ 2010-11-29 14:53 UTC (permalink / raw)
  To: Sergej.Stepanov; +Cc: scottwood, linux-mtd, linuxppc-dev, dwmw2, Rolf.Riehle
In-Reply-To: <4206182445660643B9AEB8D4E55BBD0A106A0AA93A@HERMES2>

On Tue, 2010-11-23 at 18:38 +0100, Sergej.Stepanov@ids.de wrote:
> This patch should fix the following problem:
>  1. the  jffs2-image update in the u-boot was ok
>  2. first restart and first mount of the NAND-flash-partition was also ok
>  3. before the restart of controller there are no any activity on NAND-flash except of the jffs2_gcd_mtdX-process ...
>  4. BUT after the second restart the NAND-flash-partition could not be really used after the second mount,
>     dmesg filled with messages:
> ...
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x03ce0000: 0xc0ff instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x03d00000: 0xc0ff instead
> ....
> Just for for info:
> the behaviour observed on mpc8313-based board with the large-page NAND.
> The only activity on NAND-flash was the garbage collector process, that looks for CLEANMARKER-nodes
> 
> As Scott said it was broken by commit 3ab8f2a2e7011c5e83363b42950757e46ef06824
> 
> Signed-off-by: Sergej Stepanov <Sergej.Stepanov@ids.de>
> Cc: Rolf Riehle <Rolf.Riehle@ids.de>
> Cc: Scott Wood <scottwood@freescale.com>
> Cc: David Woodhouse <dwmw2@infradead.org>

Pusehd to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (Битюцкий Артём)

^ permalink raw reply

* Re: [PATCH 3/5] fpga: add basic CARMA board support
From: Ira W. Snyder @ 2010-11-29 16:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1290991094.32570.213.camel@pasglop>

On Mon, Nov 29, 2010 at 11:38:14AM +1100, Benjamin Herrenschmidt wrote:
> On Wed, 2010-09-08 at 09:41 -0700, Ira W. Snyder wrote:
> > This adds basic support for the system controller FPGA on the OVRO CARMA
> > board. This patch only adds infrastructure that will be used by later
> > drivers.
> 
> Oh and another comment ...
> 
> I'm not sure about drivers/fpga ... in the end, one would expect such a
> directory to contain stuff to manipulate FPGAs in the sense of
> downloading bitfiles, instanciating devices (device-tree manipulation ?)
> etc...
> 
> From what I see in your code, the fact that these are FPGAs is almost
> irrelevant, you are providing support for "carma" devices, and such are
> no different than some other platform device, they just happen to be
> implemented as FPGAs. Or am I missing something ?
> 

You are exactly right. They are just regular platform devices. One
devices does happen to be a bitfile downloading driver
(carma-fpga-program), but it does not create any generic infrastructure
for downloading bitfiles.

Regarding your earlier comment about the carma class: no, it isn't
necessary. I found it convenient to have everything related to this
hardware appear in /sys/class/carma/, nothing more. It just wasn't as
easy to remember something like:
/sys/bus/platform/devices/f0000000.carma-fpga/.

I was thinking about changing the drivers from generic char devices into
misc devices instead. The sysfs interface would move from
/sys/class/carma/carma-fpga to /sys/class/misc/carma-fpga (for example),
but that is easy enough to remember.

Rather than putting the source code in drivers/fpga/carma, what about
drivers/misc/carma instead? I've already done that in my local tree, and
I'm much happier with the result.

Thanks for the comments.

Ira

^ permalink raw reply

* Re: [PATCH v2] PPC4xx: Adding PCI(E) MSI support
From: Josh Boyer @ 2010-11-29 18:35 UTC (permalink / raw)
  To: tmarri; +Cc: linuxppc-dev
In-Reply-To: <1289852106-17577-1-git-send-email-tmarri@apm.com>

On Mon, Nov 15, 2010 at 12:15:06PM -0800, tmarri@apm.com wrote:
>From: Tirumala Marri <tmarri@apm.com>
>
>This patch adds MSI support for 440SPe, 460Ex, 460Sx and 405Ex.
>

My apologies in the delay here.  I was on holiday for a while and never
got back to review this.  A few notes below.

Also, I've added a few patches from Victor for suspend/idle support in
my next branch that cause a minor conflict with this one.  It's not a
big deal to fix, but if you rework the patch for the comments, rebasing
it to my next branch would be appreciated.

>diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
>new file mode 100644
>index 0000000..9ed559f
>--- /dev/null
>+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
>@@ -0,0 +1,311 @@
>+/*
>+ * Adding PCI-E MSI support for PPC4XX SoCs.
>+ *
>+ * Copyright (c) 2010, Applied Micro Circuits Corporation
>+ * Authors: 	Tirumala R Marri <tmarri@apm.com>
>+ * 		Feng Kan <fkan@apm.com>
>+ *
>+ * This program is free software; you can redistribute it and/or
>+ * modify it under the terms of the GNU General Public License as
>+ * published by the Free Software Foundation; either version 2 of
>+ * the License, or (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
>+ * MA 02111-1307 USA
>+ */
>+
>+#include <linux/irq.h>
>+#include <linux/bootmem.h>
>+#include <linux/pci.h>
>+#include <linux/msi.h>
>+#include <linux/of_platform.h>
>+#include <linux/interrupt.h>
>+#include <asm/prom.h>
>+#include <asm/hw_irq.h>
>+#include <asm/ppc-pci.h>
>+#include <boot/dcr.h>

This still seems weird to include.  Perhaps you should duplicate the
macros you need into asm/dcr-regs.h or something.

>+#include <asm/dcr-regs.h>
>+#include <asm/msi_bitmap.h>
>+
>+#define PEIH_TERMADH	0x00
>+#define PEIH_TERMADL	0x08
>+#define PEIH_MSIED	0x10
>+#define PEIH_MSIMK	0x18
>+#define PEIH_MSIASS	0x20
>+#define PEIH_FLUSH0	0x30
>+#define PEIH_FLUSH1	0x38
>+#define PEIH_CNTRST	0x48
>+#define NR_MSI_IRQS	4
>+
>+LIST_HEAD(msi_head);
>+struct ppc4xx_msi {
>+	u32 msi_addr_lo;
>+	u32 msi_addr_hi;
>+	void __iomem *msi_regs;
>+	int msi_virqs[NR_MSI_IRQS];
>+	struct msi_bitmap bitmap;
>+	struct list_head list;
>+};
>+
>+struct ppc4xx_msi_feature {
>+	u32 ppc4xx_pic_ip;
>+	u32 msiir_offset;
>+};
>+
>+static int ppc4xx_msi_init_allocator(struct platform_device *dev,
>+		struct ppc4xx_msi *msi_data)
>+{
>+	int err;
>+
>+	err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
>+			      dev->dev.of_node);
>+	if (err)
>+		return err;
>+
>+	err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
>+	if (err < 0) {
>+		msi_bitmap_free(&msi_data->bitmap);
>+		return err;
>+	}
>+
>+	return 0;
>+}
>+
>+static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
>+{
>+	int err = 0;
>+	int int_no = -ENOMEM;
>+	unsigned int virq;
>+	struct msi_msg msg;
>+	struct msi_desc *entry;
>+	struct device_node *msi_dev = NULL;
>+	struct ppc4xx_msi *msi_data = dev->dev.platform_data;
>+
>+	msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
>+	if (msi_dev) {
>+		err = -ENODEV;
>+		goto out_free;
>+	}
>+
>+	list_for_each_entry(entry, &dev->msi_list, list) {
>+		list_for_each_entry(msi_data, &msi_head, list) {
>+			int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
>+			if(int_no >= 0)
>+				break;
>+		}
>+		if(int_no < 0) {
>+
>+			err = int_no;
>+			pr_debug("%s: fail allocating msi interrupt\n",
>+					__func__);
>+		}
>+		virq = irq_of_parse_and_map(msi_dev, int_no);
>+		if (virq == NO_IRQ) {
>+			dev_err(&dev->dev, "%s: fail mapping irq\n", __func__);
>+			msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1);
>+			err = -ENOSPC;
>+			goto out_free;
>+		}
>+		msi_data->msi_virqs[int_no] = virq;
>+		set_irq_data(virq, (void *)int_no);
>+		dev_dbg(&dev->dev, "%s: virq = %d \n", __func__, virq);
>+
>+		/* Setup msi address space */
>+		msg.address_hi = msi_data->msi_addr_hi;
>+		msg.address_lo = msi_data->msi_addr_lo;
>+
>+		set_irq_msi(virq, entry);
>+		msg.data = int_no;
>+		write_msi_msg(virq, &msg);
>+	}
>+	of_node_put(msi_dev);
>+	return err;
>+
>+out_free:
>+	of_node_put(msi_dev);
>+	return err;

You can move the label up and get rid of the duplicate of_node_put and
return calls.

>+}
>+
>+void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
>+{
>+	struct msi_desc *entry;
>+	struct ppc4xx_msi *msi_data = dev->dev.platform_data;
>+
>+	dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
>+
>+	list_for_each_entry(entry, &dev->msi_list, list) {
>+		if (entry->irq == NO_IRQ)
>+			continue;
>+		set_irq_msi(entry->irq, NULL);
>+		msi_bitmap_free_hwirqs(&msi_data->bitmap,
>+				virq_to_hw(entry->irq), 1);
>+		irq_dispose_mapping(entry->irq);
>+	}
>+
>+	return;
>+}
>+
>+static int ppc4xx_msi_check_device(struct pci_dev *pdev, int nvec, int type)
>+{
>+	dev_dbg(&pdev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
>+		__func__, nvec, type);
>+	if (type == PCI_CAP_ID_MSIX)
>+		pr_debug("fslmsi: MSI-X untested, trying anyway.\n");

fslmsi?

>+
>+	return 0;
>+}
>+
>+static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
>+				 struct resource res, struct ppc4xx_msi *msi)
>+{
>+	const u32 *msi_data;
>+	const u32 *msi_mask;
>+	const u32 *sdr_addr;
>+	int err = 0;
>+	dma_addr_t msi_phys;
>+	void *msi_virt;
>+	struct device_node *msi_dev = NULL;
>+
>+	sdr_addr = of_get_property(dev->dev.of_node, "sdr-base", NULL);
>+	if (!sdr_addr)
>+		return -1;
>+
>+	SDR0_WRITE(sdr_addr, (u64)res.start >> 32);	 /*HIGH addr */
>+	SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */
>+
>+
>+	msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
>+	if (msi_dev) {
>+		err = -ENODEV;
>+		goto error_out;
>+	}
>+	msi->msi_regs = of_iomap(msi_dev, 0);
>+	if (!msi->msi_regs) {
>+		dev_err(&dev->dev, "ioremap problem failed\n");

Should probably read "of_iomap failed".

>+		return -ENOMEM;
>+	}
>+	of_node_put(msi_dev);
>+	dev_dbg(&dev->dev, "PCIE-MSI: msi register mapped 0x%x 0x%x\n",
>+		(u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
>+
>+	msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);

This can fail, can't it?  Also, where is this actually used?

>+	msi->msi_addr_hi = 0x0;
>+	msi->msi_addr_lo = (u32) msi_phys;
>+	dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x \n", msi->msi_addr_lo);
>+
>+	/* Progam the Interrupt handler Termination addr registers */
>+	out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
>+	out_be32(msi->msi_regs + PEIH_TERMADL, msi->msi_addr_lo);
>+
>+	msi_data = of_get_property(dev->dev.of_node, "msi-data", NULL);
>+	if (!msi_data) {
>+		err = -1;
>+		goto error_out;
>+	}
>+
>+	msi_mask = of_get_property(dev->dev.of_node, "msi-mask", NULL);
>+	if (!msi_mask) {
>+		err = -1;
>+		goto error_out;
>+	}

I don't see where dma_free_coherent is called to cleanup if either of
those fail.

>+
>+	/* Program MSI Expected data and Mask bits */
>+	out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
>+	out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
>+
>+	return err;
>+error_out:
>+	return err;

You can just move the label up 2 lines and get rid of one of these
return statements.

>+}
>+
>+static int ppc4xx_of_msi_remove(struct platform_device *dev)
>+{
>+	struct ppc4xx_msi *msi = dev->dev.platform_data;
>+	int i;
>+	int virq;
>+
>+	for(i = 0; i < NR_MSI_IRQS; i++) {
>+		virq = msi->msi_virqs[i];
>+		if (virq != NO_IRQ)
>+			irq_dispose_mapping(virq);
>+	}
>+
>+	if (msi->list.prev != NULL)
>+		list_del(&msi->list);
>+
>+	if (msi->bitmap.bitmap)
>+		msi_bitmap_free(&msi->bitmap);
>+	iounmap(msi->msi_regs);
>+	kfree(msi);
>+
>+	return 0;
>+}
>+
>+static int __devinit ppc4xx_msi_probe(struct platform_device *dev,
>+				      const struct of_device_id *match)
>+{
>+	struct ppc4xx_msi *msi;
>+	struct resource res;
>+	int err = 0;
>+
>+	dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
>+
>+	msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
>+	if (!msi) {
>+		dev_err(&dev->dev, "No memory for MSI structure\n");
>+		err = -ENOMEM;
>+		goto error_out;
>+	}
>+	dev->dev.platform_data = msi;
>+
>+	/* Get MSI ranges */
>+	err = of_address_to_resource(dev->dev.of_node, 0, &res);
>+	if (err) {
>+		dev_err(&dev->dev, "%s resource error!\n",
>+			dev->dev.of_node->full_name);
>+		goto error_out;
>+	}
>+
>+	if (ppc4xx_setup_pcieh_hw(dev, res, msi))
>+		goto error_out;
>+
>+	err = ppc4xx_msi_init_allocator(dev, msi);
>+	if (err) {
>+		dev_err(&dev->dev, "Error allocating MSI bitmap\n");
>+		goto error_out;
>+	}
>+
>+	list_add_tail(&msi->list, &msi_head);
>+
>+	ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
>+	ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
>+	ppc_md.msi_check_device = ppc4xx_msi_check_device;
>+	return err;
>+
>+error_out:
>+	ppc4xx_of_msi_remove(dev);
>+	return err;
>+}
>+
>+static struct of_platform_driver ppc4xx_msi_driver = {
>+	.driver = {
>+		   .name = "ppc4xx-msi",
>+		   .owner = THIS_MODULE,
>+		   },
>+	.probe = ppc4xx_msi_probe,
>+	.remove = ppc4xx_of_msi_remove,
>+};
>+
>+static __init int ppc4xx_msi_init(void)
>+{
>+	return of_register_platform_driver(&ppc4xx_msi_driver);
>+}
>+
>+subsys_initcall(ppc4xx_msi_init);
>-- 
>1.6.1.rc3
>

^ permalink raw reply

* Re: [PATCH 15/15] ppc/vio: ensure dma_coherent_mask is set
From: Nishanth Aravamudan @ 2010-11-29 19:46 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <1290992577.32570.216.camel@pasglop>

Hi Ben,

On 29.11.2010 [12:02:57 +1100], Benjamin Herrenschmidt wrote:
> On Wed, 2010-09-15 at 11:05 -0700, Nishanth Aravamudan wrote:
> > Without this change drivers, such as ibmvscsi, fail to load with the
> > previous change.
> > ---
> 
> So you broke bisection... fold the patch instead or invert them

Thanks for the review. I resent this series on 10/18 and it had the
patches folded together.

Thanks,
Nish

-- 
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center

^ permalink raw reply

* Re: [PATCH 15/15] ppc/vio: ensure dma_coherent_mask is set
From: Benjamin Herrenschmidt @ 2010-11-29 20:25 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Brian King, Paul Mackerras, linuxppc-dev, Milton Miller
In-Reply-To: <20101129194620.GA2998@us.ibm.com>

On Mon, 2010-11-29 at 11:46 -0800, Nishanth Aravamudan wrote:
> > So you broke bisection... fold the patch instead or invert them
> 
> Thanks for the review. I resent this series on 10/18 and it had the
> patches folded together. 

Right, I know :-) I just mistakenly had that old one still tagged in
patchwork, my bad.

I've merged some of the new ones already.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH v2] PPC4xx: Adding PCI(E) MSI support
From: Michael Ellerman @ 2010-11-30  1:30 UTC (permalink / raw)
  To: Josh Boyer; +Cc: tmarri, linuxppc-dev
In-Reply-To: <20101129183535.GA5603@zod.rchland.ibm.com>

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

On Mon, 2010-11-29 at 13:35 -0500, Josh Boyer wrote:
> On Mon, Nov 15, 2010 at 12:15:06PM -0800, tmarri@apm.com wrote:
> >From: Tirumala Marri <tmarri@apm.com>
> >
> >This patch adds MSI support for 440SPe, 460Ex, 460Sx and 405Ex.
> >
> 
> My apologies in the delay here.  I was on holiday for a while and never
> got back to review this.  A few notes below.
> 
> Also, I've added a few patches from Victor for suspend/idle support in
> my next branch that cause a minor conflict with this one.  It's not a
> big deal to fix, but if you rework the patch for the comments, rebasing
> it to my next branch would be appreciated.
> 
> >diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
> >new file mode 100644
> >index 0000000..9ed559f
> >--- /dev/null
> >+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
> >@@ -0,0 +1,311 @@
> >+/*
> >+ * Adding PCI-E MSI support for PPC4XX SoCs.
> >+ *
> >+ * Copyright (c) 2010, Applied Micro Circuits Corporation
> >+ * Authors: 	Tirumala R Marri <tmarri@apm.com>
> >+ * 		Feng Kan <fkan@apm.com>
> >+ *
> >+ * This program is free software; you can redistribute it and/or
> >+ * modify it under the terms of the GNU General Public License as
> >+ * published by the Free Software Foundation; either version 2 of
> >+ * the License, or (at your option) any later version.
> >+ *
> >+ * This program is distributed in the hope that it will be useful,
> >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> >+ * GNU General Public License for more details.
> >+ *
> >+ * You should have received a copy of the GNU General Public License
> >+ * along with this program; if not, write to the Free Software
> >+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> >+ * MA 02111-1307 USA
> >+ */
> >+
> >+#include <linux/irq.h>
> >+#include <linux/bootmem.h>
> >+#include <linux/pci.h>
> >+#include <linux/msi.h>
> >+#include <linux/of_platform.h>
> >+#include <linux/interrupt.h>
> >+#include <asm/prom.h>
> >+#include <asm/hw_irq.h>
> >+#include <asm/ppc-pci.h>
> >+#include <boot/dcr.h>
> 
> This still seems weird to include.  Perhaps you should duplicate the
> macros you need into asm/dcr-regs.h or something.
> 
> >+#include <asm/dcr-regs.h>
> >+#include <asm/msi_bitmap.h>
> >+
> >+#define PEIH_TERMADH	0x00
> >+#define PEIH_TERMADL	0x08
> >+#define PEIH_MSIED	0x10
> >+#define PEIH_MSIMK	0x18
> >+#define PEIH_MSIASS	0x20
> >+#define PEIH_FLUSH0	0x30
> >+#define PEIH_FLUSH1	0x38
> >+#define PEIH_CNTRST	0x48
> >+#define NR_MSI_IRQS	4
> >+
> >+LIST_HEAD(msi_head);
> >+struct ppc4xx_msi {
> >+	u32 msi_addr_lo;
> >+	u32 msi_addr_hi;
> >+	void __iomem *msi_regs;
> >+	int msi_virqs[NR_MSI_IRQS];
> >+	struct msi_bitmap bitmap;
> >+	struct list_head list;
> >+};
> >+
> >+struct ppc4xx_msi_feature {
> >+	u32 ppc4xx_pic_ip;
> >+	u32 msiir_offset;
> >+};
> >+
> >+static int ppc4xx_msi_init_allocator(struct platform_device *dev,
> >+		struct ppc4xx_msi *msi_data)
> >+{
> >+	int err;
> >+
> >+	err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
> >+			      dev->dev.of_node);
> >+	if (err)
> >+		return err;
> >+
> >+	err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
> >+	if (err < 0) {
> >+		msi_bitmap_free(&msi_data->bitmap);
> >+		return err;
> >+	}
> >+
> >+	return 0;
> >+}
> >+
> >+static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
> >+{
> >+	int err = 0;
> >+	int int_no = -ENOMEM;
> >+	unsigned int virq;
> >+	struct msi_msg msg;
> >+	struct msi_desc *entry;
> >+	struct device_node *msi_dev = NULL;
> >+	struct ppc4xx_msi *msi_data = dev->dev.platform_data;
> >+
> >+	msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
> >+	if (msi_dev) {
> >+		err = -ENODEV;
> >+		goto out_free;
> >+	}
> >+
> >+	list_for_each_entry(entry, &dev->msi_list, list) {
> >+		list_for_each_entry(msi_data, &msi_head, list) {
> >+			int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
> >+			if(int_no >= 0)
> >+				break;
> >+		}
> >+		if(int_no < 0) {
> >+
> >+			err = int_no;
> >+			pr_debug("%s: fail allocating msi interrupt\n",
> >+					__func__);
> >+		}
> >+		virq = irq_of_parse_and_map(msi_dev, int_no);
> >+		if (virq == NO_IRQ) {
> >+			dev_err(&dev->dev, "%s: fail mapping irq\n", __func__);
> >+			msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1);
> >+			err = -ENOSPC;
> >+			goto out_free;
> >+		}
> >+		msi_data->msi_virqs[int_no] = virq;
> >+		set_irq_data(virq, (void *)int_no);
> >+		dev_dbg(&dev->dev, "%s: virq = %d \n", __func__, virq);
> >+
> >+		/* Setup msi address space */
> >+		msg.address_hi = msi_data->msi_addr_hi;
> >+		msg.address_lo = msi_data->msi_addr_lo;
> >+
> >+		set_irq_msi(virq, entry);
> >+		msg.data = int_no;
> >+		write_msi_msg(virq, &msg);
> >+	}
> >+	of_node_put(msi_dev);
> >+	return err;
> >+
> >+out_free:
> >+	of_node_put(msi_dev);
> >+	return err;
> 
> You can move the label up and get rid of the duplicate of_node_put and
> return calls.

Yes, but the real issue is you shouldn't be looking for the of node in
this routine. It should be stored in the ppc4xx_msi structure at probe
time.

Which raises the question, how are you finding the ppc4xx_msi struct.
You grab it out of the pci_dev's platform_data, but I don't see where
you stashed it in there.

I think you copied that pattern from fsl_msi.c, it works for remove, but
it doesn't work for setup_msi_irqs(). The device you are passed there is
the pci device which is having MSIs enabled, not the device that
represents your MSI controller.

You also have a list of ppc4xx_msi structs, but you never actually use
it, except to add and remove them. But that achieves nothing because you
never try to look them up.

cheers

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

^ permalink raw reply

* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2010-11-30  4:07 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list

Hi Linus !

This is a small fix for a misuse of RCU on powerpc, please pull.

Cheers,
Ben.

The following changes since commit
72083646528d4887b920deb71b37e09bc7d227bb:

  Un-inline get_pipe_info() helper function (2010-11-28 16:27:19 -0800)

are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge

Peter Zijlstra (1):
      powerpc: Use call_rcu_sched() for pagetables

 arch/powerpc/mm/pgtable.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

^ permalink raw reply

* Re: [PATCH 0/4] More ppc64 nvram code cleanup
From: Benjamin Herrenschmidt @ 2010-11-30  5:25 UTC (permalink / raw)
  To: Jim Keniston; +Cc: linuxppc-dev
In-Reply-To: <20101112045346.4290.43739.stgit@localhost.localdomain>

On Thu, 2010-11-11 at 20:53 -0800, Jim Keniston wrote:
> This series contains some fixups to Ben Herrenschmidt's Aug. 2 patch
> set, "[RFC] Clean up ppc64 nvram code" --
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-August/084601.html
> 
> These patches apply atop Ben's 11-patch series.
> ---
> 
> Jim Keniston (4):
>       Handle partition names >= 12 chars
>       Fix NVRAM partition list setup
>       Fix nvram_create_partition() arg order
>       Fix powerpc nvram init order

I've folded the first two (or a slightly different variant) in my series
and applied the two next on top. I'll post that new version of the
series to the list after a few tests today and will include it in next
in a couple of days, possibly along with your other patches provided
they survive my review :-)

Cheers,
Ben.

^ permalink raw reply

* [PATCH 01/13] powerpc/nvram: Move things out of asm/nvram.h
From: benh @ 2010-11-30  5:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: jkensito

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

This moves a bunch of definitions out of asm/nvram.h to the files
that use them or just outright remove completely unused stuff.

We leave the partition signatures definitions, they will be useful

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/nvram.h       |   42 +------------------------------
 arch/powerpc/kernel/nvram_64.c         |   21 +++++++++++++++-
 arch/powerpc/platforms/chrp/time.c     |    4 +++
 arch/powerpc/platforms/pseries/nvram.c |    2 +
 4 files changed, 28 insertions(+), 41 deletions(-)

diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 850b72f..459dc09 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -10,31 +10,7 @@
 #ifndef _ASM_POWERPC_NVRAM_H
 #define _ASM_POWERPC_NVRAM_H
 
-#include <linux/errno.h>
-
-#define NVRW_CNT 0x20
-#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
-#define NVRAM_BLOCK_LEN 16
-#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
-#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
-
-#define NVRAM_AS0  0x74
-#define NVRAM_AS1  0x75
-#define NVRAM_DATA 0x77
-
-
-/* RTC Offsets */
-
-#define MOTO_RTC_SECONDS	0x1FF9
-#define MOTO_RTC_MINUTES	0x1FFA
-#define MOTO_RTC_HOURS		0x1FFB
-#define MOTO_RTC_DAY_OF_WEEK	0x1FFC
-#define MOTO_RTC_DAY_OF_MONTH	0x1FFD
-#define MOTO_RTC_MONTH		0x1FFE
-#define MOTO_RTC_YEAR		0x1FFF
-#define MOTO_RTC_CONTROLA       0x1FF8
-#define MOTO_RTC_CONTROLB       0x1FF9
-
+/* Signatures for nvram partitions */
 #define NVRAM_SIG_SP	0x02	/* support processor */
 #define NVRAM_SIG_OF	0x50	/* open firmware config */
 #define NVRAM_SIG_FW	0x51	/* general firmware */
@@ -49,25 +25,11 @@
 #define NVRAM_SIG_OS	0xa0	/* OS defined */
 #define NVRAM_SIG_PANIC	0xa1	/* Apple OSX "panic" */
 
-/* If change this size, then change the size of NVNAME_LEN */
-struct nvram_header {
-	unsigned char signature;
-	unsigned char checksum;
-	unsigned short length;
-	char name[12];
-};
-
 #ifdef __KERNEL__
 
+#include <linux/errno.h>
 #include <linux/list.h>
 
-struct nvram_partition {
-	struct list_head partition;
-	struct nvram_header header;
-	unsigned int index;
-};
-
-
 extern int nvram_write_error_log(char * buff, int length,
 					 unsigned int err_type, unsigned int err_seq);
 extern int nvram_read_error_log(char * buff, int length,
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 9cf197f..a8154f1 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -34,6 +34,25 @@
 
 #undef DEBUG_NVRAM
 
+#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
+#define NVRAM_BLOCK_LEN 16
+#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
+#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
+
+/* If change this size, then change the size of NVNAME_LEN */
+struct nvram_header {
+	unsigned char signature;
+	unsigned char checksum;
+	unsigned short length;
+	char name[12];
+};
+
+struct nvram_partition {
+	struct list_head partition;
+	struct nvram_header header;
+	unsigned int index;
+};
+
 static struct nvram_partition * nvram_part;
 static long nvram_error_log_index = -1;
 static long nvram_error_log_size = 0;
@@ -432,7 +451,7 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* try creating a partition with the free space we have */
-	rc = nvram_create_os_partition();
+	rc = nvram_create_partition("ppc64,linux", );
 	if (!rc) {
 		return 0;
 	}
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 054dfe5..f803f4b 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -29,6 +29,10 @@
 
 extern spinlock_t rtc_lock;
 
+#define NVRAM_AS0  0x74
+#define NVRAM_AS1  0x75
+#define NVRAM_DATA 0x77
+
 static int nvram_as1 = NVRAM_AS1;
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index bc3c7f2..f4e4c06 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -27,6 +27,8 @@ static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
+/* Max bytes to read/write in one go */
+#define NVRW_CNT 0x20
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
-- 
1.7.1

^ permalink raw reply related

* [PATCH 02/13] powerpc/nvram: More flexible nvram_create_partition()
From: benh @ 2010-11-30  5:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: jkensito
In-Reply-To: <1291096063-14386-1-git-send-email-benh@kernel.crashing.org>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Replace nvram_create_os_partition() with a variant that takes
the partition name, signature and size as arguments.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c         |   46 +++++++++++++++++++------------
 arch/powerpc/platforms/pseries/nvram.c |    6 ++--
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index a8154f1..9e13335 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -307,13 +307,15 @@ static int __init nvram_remove_os_partition(void)
 	return 0;
 }
 
-/* nvram_create_os_partition
- *
- * Create a OS linux partition to buffer error logs.
- * Will create a partition starting at the first free
- * space found if space has enough room.
+/**
+ * nvram_create_partition - Create a partition in nvram
+ * @name: name of the partition to create
+ * @sig: signature of the partition to create
+ * @req_size: size to allocate preferrably
+ * @min_size: minimum acceptable size (0 means req_size)
  */
-static int __init nvram_create_os_partition(void)
+static int __init nvram_create_partition(const char *name, int sig,
+					 int req_size, int min_size)
 {
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
@@ -322,20 +324,27 @@ static int __init nvram_create_os_partition(void)
 	loff_t tmp_index;
 	long size = 0;
 	int rc;
-	
+
+	/* If no minimum size specified, make it the same as the
+	 * requested size
+	 */
+	if (min_size == 0)
+		min_size = req_size;
+
 	/* Find a free partition that will give us the maximum needed size 
 	   If can't find one that will give us the minimum size needed */
 	list_for_each_entry(part, &nvram_part->partition, partition) {
 		if (part->header.signature != NVRAM_SIG_FREE)
 			continue;
 
-		if (part->header.length >= NVRAM_MAX_REQ) {
-			size = NVRAM_MAX_REQ;
+		if (part->header.length >= req_size) {
+			size = req_size;
 			free_part = part;
 			break;
 		}
-		if (!size && part->header.length >= NVRAM_MIN_REQ) {
-			size = NVRAM_MIN_REQ;
+		if (part->header.length > size &&
+		    part->header.length >= min_size) {
+			size = part->header.length;
 			free_part = part;
 		}
 	}
@@ -350,9 +359,9 @@ static int __init nvram_create_os_partition(void)
 	}
 
 	new_part->index = free_part->index;
-	new_part->header.signature = NVRAM_SIG_OS;
+	new_part->header.signature = sig;
 	new_part->header.length = size;
-	strcpy(new_part->header.name, "ppc64,linux");
+	strncpy(new_part->header.name, name, 12);
 	new_part->header.checksum = nvram_checksum(&new_part->header);
 
 	rc = nvram_write_header(new_part);
@@ -451,10 +460,10 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* try creating a partition with the free space we have */
-	rc = nvram_create_partition("ppc64,linux", );
-	if (!rc) {
+	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+				       NVRAM_MAX_REQ, NVRAM_MIN_REQ);
+	if (!rc)
 		return 0;
-	}
 		
 	/* need to free up some space */
 	rc = nvram_remove_os_partition();
@@ -463,9 +472,10 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* create a partition in this new space */
-	rc = nvram_create_os_partition();
+	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+				       NVRAM_MAX_REQ, NVRAM_MIN_REQ);
 	if (rc) {
-		printk(KERN_ERR "nvram_create_os_partition: Could not find a "
+		printk(KERN_ERR "nvram_create_partition: Could not find a "
 		       "NVRAM partition large enough\n");
 		return rc;
 	}
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index f4e4c06..2a1ef5c 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -22,14 +22,14 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
+/* Max bytes to read/write in one go */
+#define NVRW_CNT 0x20
+
 static unsigned int nvram_size;
 static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
-/* Max bytes to read/write in one go */
-#define NVRW_CNT 0x20
-
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
 	unsigned int i;
-- 
1.7.1

^ permalink raw reply related

* [PATCH 04/13] powerpc/nvram: Ensure that the partition header/block size is right
From: benh @ 2010-11-30  5:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: jkensito
In-Reply-To: <1291096063-14386-1-git-send-email-benh@kernel.crashing.org>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Use BUILD_BUG_ON to ensure the structure representing a partition
header have the right size.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index a5a5587..f753882 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -565,6 +565,8 @@ static int __init nvram_init(void)
 	int error;
 	int rc;
 	
+	BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
+
 	if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
 		return  -ENODEV;
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 03/13] powerpc/nvram: nvram_create_partitions() now uses bytes
From: benh @ 2010-11-30  5:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: jkensito
In-Reply-To: <1291096063-14386-1-git-send-email-benh@kernel.crashing.org>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

This converts nvram_create_partition() to use a size in bytes
rather than blocks. It does the appropriate alignment internally

The size passed is also the data size (ie. doesn't include the
header anymore).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 9e13335..a5a5587 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -34,10 +34,10 @@
 
 #undef DEBUG_NVRAM
 
-#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
-#define NVRAM_BLOCK_LEN 16
-#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
-#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
+#define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
+#define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
+#define NVRAM_MAX_REQ		2079
+#define NVRAM_MIN_REQ		1055
 
 /* If change this size, then change the size of NVNAME_LEN */
 struct nvram_header {
@@ -311,7 +311,7 @@ static int __init nvram_remove_os_partition(void)
  * nvram_create_partition - Create a partition in nvram
  * @name: name of the partition to create
  * @sig: signature of the partition to create
- * @req_size: size to allocate preferrably
+ * @req_size: size of data to allocate in bytes
  * @min_size: minimum acceptable size (0 means req_size)
  */
 static int __init nvram_create_partition(const char *name, int sig,
@@ -325,12 +325,20 @@ static int __init nvram_create_partition(const char *name, int sig,
 	long size = 0;
 	int rc;
 
+	/* Convert sizes from bytes to blocks */
+	req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
+	min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
+
 	/* If no minimum size specified, make it the same as the
 	 * requested size
 	 */
 	if (min_size == 0)
 		min_size = req_size;
 
+	/* Now add one block to each for the header */
+	req_size += 1;
+	min_size += 1;
+
 	/* Find a free partition that will give us the maximum needed size 
 	   If can't find one that will give us the minimum size needed */
 	list_for_each_entry(part, &nvram_part->partition, partition) {
@@ -450,7 +458,7 @@ static int __init nvram_setup_partition(void)
 		if (strcmp(part->header.name, "ppc64,linux"))
 			continue;
 
-		if (part->header.length >= NVRAM_MIN_REQ) {
+		if ((part->header.length - 1) * NVRAM_BLOCK_LEN >= NVRAM_MIN_REQ) {
 			/* found our partition */
 			nvram_error_log_index = part->index + NVRAM_HEADER_LEN;
 			nvram_error_log_size = ((part->header.length - 1) *
-- 
1.7.1

^ permalink raw reply related

* [PATCH 05/13] powerpc/nvram: Completely clear a new partition
From: benh @ 2010-11-30  5:47 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: jkensito
In-Reply-To: <1291096063-14386-1-git-send-email-benh@kernel.crashing.org>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

When creating a partition, we clear it entirely rather than
just the first two words since the previous code was rather
specific to the pseries log partition format.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index f753882..02737e6 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -320,7 +320,7 @@ static int __init nvram_create_partition(const char *name, int sig,
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
 	struct nvram_partition *free_part = NULL;
-	int seq_init[2] = { 0, 0 };
+	static char nv_init_vals[16];
 	loff_t tmp_index;
 	long size = 0;
 	int rc;
@@ -379,14 +379,15 @@ static int __init nvram_create_partition(const char *name, int sig,
 		return rc;
 	}
 
-	/* make sure and initialize to zero the sequence number and the error
-	   type logged */
-	tmp_index = new_part->index + NVRAM_HEADER_LEN;
-	rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write "
-		       "failed (%d)\n", rc);
-		return rc;
+	/* Clear the partition */
+	for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
+	     tmp_index <  ((size - 1) * NVRAM_BLOCK_LEN);
+	     tmp_index += NVRAM_BLOCK_LEN) {
+		rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
+		if (rc <= 0) {
+			pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc);
+			return rc;
+		}
 	}
 	
 	nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
-- 
1.7.1

^ permalink raw reply related


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