LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH 2/2] powerpc: add support for MPIC message register API
From: Kushwaha Prabhakar-B32579 @ 2011-04-29  5:00 UTC (permalink / raw)
  To: Meador Inge
  Cc: openmcapi-dev@googlegroups.com, linuxppc-dev@lists.ozlabs.org,
	devicetree-discuss@lists.ozlabs.org, Hollis Blanchard
In-Reply-To: <1303232375-25014-3-git-send-email-meador_inge@mentor.com>

Hi,

I have no comments about coding and architecture. It looks fine.

Only have a query about its use case..
  "Any application intended to use message interrupt requires to know reg_n=
um because of struct mpic_msgr* mpic_msgr_get(unsigned int reg_num) API"

It will be good to search available unit internally and provide its pointer=
. It will make application more flexible.=20

Regards,
Prabhakar

> -----Original Message-----
> From: devicetree-discuss-bounces+b32579=3Dfreescale.com@lists.ozlabs.org
> [mailto:devicetree-discuss-bounces+b32579=3Dfreescale.com@lists.ozlabs.or=
g]
> On Behalf Of Meador Inge
> Sent: Tuesday, April 19, 2011 10:30 PM
> To: linuxppc-dev@lists.ozlabs.org
> Cc: openmcapi-dev@googlegroups.com; devicetree-discuss@lists.ozlabs.org;
> Hollis Blanchard
> Subject: [PATCH 2/2] powerpc: add support for MPIC message register API
>=20
> Some MPIC implementations contain one or more blocks of message registers
> that are used to send messages between cores via IPIs.  A simple API has
> been added to access (get/put, read, write, etc ...) these message
> registers.
> The available message registers are initially discovered via nodes in the
> device tree.  A separate commit contains a binding for the message
> register nodes.
>=20
> Signed-off-by: Meador Inge <meador_inge@mentor.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Hollis Blanchard <hollis_blanchard@mentor.com>
> ---
>  arch/powerpc/include/asm/mpic_msgr.h |   35 +++++
>  arch/powerpc/platforms/Kconfig       |    8 +
>  arch/powerpc/sysdev/Makefile         |    3 +-
>  arch/powerpc/sysdev/mpic_msgr.c      |  279
> ++++++++++++++++++++++++++++++++++
>  4 files changed, 324 insertions(+), 1 deletions(-)  create mode 100644
> arch/powerpc/include/asm/mpic_msgr.h
>  create mode 100644 arch/powerpc/sysdev/mpic_msgr.c
>=20
> diff --git a/arch/powerpc/include/asm/mpic_msgr.h
> b/arch/powerpc/include/asm/mpic_msgr.h
> new file mode 100644
> index 0000000..370dcb4
> --- /dev/null
> +++ b/arch/powerpc/include/asm/mpic_msgr.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; version 2 of the
> + * License.
> + *
> + */
> +
> +#ifndef _ASM_MPIC_MSGR_H
> +#define _ASM_MPIC_MSGR_H
> +
> +#include <linux/types.h>
> +
> +struct mpic_msgr {
> +	u32 __iomem *addr;
> +	u32 __iomem *mer;
> +	u32 __iomem	*msr;
> +	int irq;
> +	atomic_t in_use;
> +	int num;
> +};
> +
> +extern struct mpic_msgr* mpic_msgr_get(unsigned int reg_num); extern
> +void mpic_msgr_put(struct mpic_msgr* msgr); extern void
> +mpic_msgr_enable(struct mpic_msgr *msgr); extern void
> +mpic_msgr_disable(struct mpic_msgr *msgr); extern void
> +mpic_msgr_write(struct mpic_msgr *msgr, u32 message); extern u32
> +mpic_msgr_read(struct mpic_msgr *msgr); extern void
> +mpic_msgr_clear(struct mpic_msgr *msgr); extern void
> +mpic_msgr_set_destination(struct mpic_msgr *msgr, u32 cpu_num); extern
> +int mpic_msgr_get_irq(struct mpic_msgr *msgr);
> +
> +#endif
> diff --git a/arch/powerpc/platforms/Kconfig
> b/arch/powerpc/platforms/Kconfig index f7b0772..4d65593 100644
> --- a/arch/powerpc/platforms/Kconfig
> +++ b/arch/powerpc/platforms/Kconfig
> @@ -78,6 +78,14 @@ config MPIC_WEIRD
>  	bool
>  	default n
>=20
> +config MPIC_MSGR
> +	bool "MPIC message register support"
> +	depends on MPIC
> +	default n
> +	help
> +	  Enables support for the MPIC message registers.  These
> +	  registers are used for inter-processor communication.
> +
>  config PPC_I8259
>  	bool
>  	default n
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
> index 1e0c933..6d40185 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -3,7 +3,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) :=3D -Werror
>  ccflags-$(CONFIG_PPC64)		:=3D -mno-minimal-toc
>=20
>  mpic-msi-obj-$(CONFIG_PCI_MSI)	+=3D mpic_msi.o mpic_u3msi.o
> mpic_pasemi_msi.o
> -obj-$(CONFIG_MPIC)		+=3D mpic.o $(mpic-msi-obj-y)
> +mpic-msgr-obj-$(CONFIG_MPIC_MSGR)	+=3D mpic_msgr.o
> +obj-$(CONFIG_MPIC)		+=3D mpic.o $(mpic-msi-obj-y) $(mpic-msgr-
> obj-y)
>  fsl-msi-obj-$(CONFIG_PCI_MSI)	+=3D fsl_msi.o
>  obj-$(CONFIG_PPC_MSI_BITMAP)	+=3D msi_bitmap.o
>=20
> diff --git a/arch/powerpc/sysdev/mpic_msgr.c
> b/arch/powerpc/sysdev/mpic_msgr.c new file mode 100644 index
> 0000000..352bfa6
> --- /dev/null
> +++ b/arch/powerpc/sysdev/mpic_msgr.c
> @@ -0,0 +1,279 @@
> +/*
> + * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
> + *
> + * Some ideas based on un-pushed work done by Vivek Mahajan, Jason Jin,
> +and
> + * Mingkai Hu from Freescale Semiconductor, Inc.
> + *
> + * 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; version 2 of the
> + * License.
> + *
> + */
> +
> +#include <linux/list.h>
> +#include <linux/of_platform.h>
> +#include <linux/errno.h>
> +#include <asm/prom.h>
> +#include <asm/hw_irq.h>
> +#include <asm/ppc-pci.h>
> +#include <asm/mpic_msgr.h>
> +
> +#define MPIC_MSGR_REGISTERS_PER_BLOCK 4 #define MSGR_INUSE 0 #define
> +MSGR_FREE 1
> +
> +/* Internal structure used *only* for IO mapping register blocks. */
> +struct mpic_msgr_block {
> +	struct msgr {
> +		u32 msgr;
> +		u8 res[12];
> +	} msgrs[MPIC_MSGR_REGISTERS_PER_BLOCK];
> +	u8 res0[192];
> +	u32 mer;
> +	u8 res1[12];
> +	u32 msr;
> +};
> +
> +static struct mpic_msgr **mpic_msgrs =3D 0; static unsigned int
> +mpic_msgr_count =3D 0;
> +
> +struct mpic_msgr* mpic_msgr_get(unsigned int reg_num) {
> +	struct mpic_msgr* msgr;
> +
> +	if (reg_num >=3D mpic_msgr_count)
> +		return ERR_PTR(-ENODEV);
> +
> +	msgr =3D mpic_msgrs[reg_num];
> +
> +	if (atomic_cmpxchg(&msgr->in_use, MSGR_FREE, MSGR_INUSE) =3D=3D
> MSGR_FREE)
> +		return msgr;
> +
> +	return ERR_PTR(-EBUSY);
> +}
> +EXPORT_SYMBOL(mpic_msgr_get);
> +
> +void mpic_msgr_put(struct mpic_msgr* msgr) {
> +	atomic_set(&msgr->in_use, MSGR_FREE);
> +}
> +EXPORT_SYMBOL(mpic_msgr_put);
> +
> +void mpic_msgr_enable(struct mpic_msgr *msgr) {
> +	out_be32(msgr->mer, in_be32(msgr->mer) | (1 << msgr->num)); }
> +EXPORT_SYMBOL(mpic_msgr_enable);
> +
> +void mpic_msgr_disable(struct mpic_msgr *msgr) {
> +	out_be32(msgr->mer, in_be32(msgr->mer) & ~(1 << msgr->num)); }
> +EXPORT_SYMBOL(mpic_msgr_disable);
> +
> +void mpic_msgr_write(struct mpic_msgr *msgr, u32 message) {
> +	out_be32(msgr->addr, message);
> +}
> +EXPORT_SYMBOL(mpic_msgr_write);
> +
> +u32 mpic_msgr_read(struct mpic_msgr *msgr) {
> +	return in_be32(msgr->addr);
> +}
> +EXPORT_SYMBOL(mpic_msgr_read);
> +
> +void mpic_msgr_clear(struct mpic_msgr *msgr) {
> +	(void) mpic_msgr_read(msgr);
> +}
> +EXPORT_SYMBOL(mpic_msgr_clear);
> +
> +void mpic_msgr_set_destination(struct mpic_msgr *msgr, u32 cpu_num) {
> +	out_be32(msgr->addr, 1 << cpu_num);
> +}
> +EXPORT_SYMBOL(mpic_msgr_set_destination);
> +
> +int mpic_msgr_get_irq(struct mpic_msgr *msgr) {
> +	return msgr->irq;
> +}
> +EXPORT_SYMBOL(mpic_msgr_get_irq);
> +
> +/* The following three functions are used to compute the order and
> +number of
> + * the message register blocks.  They are clearly very inefficent.
> +However,
> + * they are called *only* a few times during device initialization.
> + */
> +static unsigned int mpic_msgr_number_of_blocks(void) {
> +	unsigned int count;
> +	struct device_node *aliases;
> +
> +	count =3D 0;
> +	aliases =3D of_find_node_by_name(NULL, "aliases");
> +
> +	if (aliases) {
> +		char buf[32];
> +
> +		for (;;) {
> +			snprintf(buf, sizeof(buf), "msgr-block%d", count);
> +			if (!of_find_property(aliases, buf, NULL))
> +				break;
> +
> +			count +=3D 1;
> +		}
> +	}
> +
> +	return count;
> +}
> +
> +static unsigned int mpic_msgr_number_of_registers(void)
> +{
> +	return mpic_msgr_number_of_blocks() *
> MPIC_MSGR_REGISTERS_PER_BLOCK; }
> +
> +static int mpic_msgr_block_number(struct device_node *node) {
> +	struct device_node *aliases;
> +	unsigned int index, number_of_blocks;
> +	char buf[64];
> +
> +	number_of_blocks =3D mpic_msgr_number_of_blocks();
> +	aliases =3D of_find_node_by_name(NULL, "aliases");
> +	if (!aliases)
> +		return -1;
> +
> +	for (index =3D 0; index < number_of_blocks; ++index) {
> +		struct property *prop;
> +
> +		snprintf(buf, sizeof(buf), "msgr-block%d", index);
> +		prop =3D of_find_property(aliases, buf, NULL);
> +		if (node =3D=3D of_find_node_by_path(prop->value))
> +			break;
> +	}
> +
> +	return index =3D=3D number_of_blocks ? -1 : index; }
> +
> +/* The probe function for a single message register block.
> + */
> +static __devinit int mpic_msgr_probe(struct platform_device *dev) {
> +	struct mpic_msgr_block __iomem *msgr_block;
> +	int block_number;
> +	struct resource rsrc;
> +	unsigned int i;
> +	unsigned int irq_index;
> +	struct device_node *np =3D dev->dev.of_node;
> +	unsigned int receive_mask;
> +	const unsigned int *prop;
> +
> +	if (!np) {
> +		dev_err(&dev->dev, "Device OF-Node is NULL");
> +		return -EFAULT;
> +	}
> +
> +	/* Allocate the message register array upon the first device
> +	 * registered.
> +	 */
> +	if (!mpic_msgrs) {
> +		mpic_msgr_count =3D mpic_msgr_number_of_registers();
> +		dev_info(&dev->dev, "Found %d message registers\n",
> mpic_msgr_count);
> +
> +		mpic_msgrs =3D kzalloc(sizeof(struct mpic_msgr) *
> mpic_msgr_count,
> +							 GFP_KERNEL);
> +		if (!mpic_msgrs) {
> +			dev_err(&dev->dev, "No memory for message register
> blocks\n");
> +			return -ENOMEM;
> +		}
> +	}
> +	dev_info(&dev->dev, "Of-device full name %s\n", np->full_name);
> +
> +	/* IO map the message register block. */
> +	of_address_to_resource(np, 0, &rsrc);
> +	msgr_block =3D ioremap(rsrc.start, rsrc.end - rsrc.start);
> +	if (!msgr_block) {
> +		dev_err(&dev->dev, "Failed to iomap MPIC message registers");
> +		return -EFAULT;
> +	}
> +
> +	/* Ensure the block has a defined order. */
> +	block_number =3D mpic_msgr_block_number(np);
> +	if (block_number < 0) {
> +		dev_err(&dev->dev, "Failed to find message register block
> alias\n");
> +		return -ENODEV;
> +	}
> +	dev_info(&dev->dev, "Setting up message register block %d\n",
> +block_number);
> +
> +	/* Grab the receive mask which specifies what registers can receive
> +	 * interrupts.
> +	 */
> +	prop =3D of_get_property(np, "msg-receive-mask", NULL);
> +	receive_mask =3D (prop) ? *prop : 0xF;
> +
> +	/* Build up the appropriate message register data structures. */
> +	for (i =3D 0, irq_index =3D 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i)
> {
> +		struct mpic_msgr *msgr;
> +		unsigned int reg_number;
> +
> +		msgr =3D kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL);
> +		if (!msgr) {
> +			dev_err(&dev->dev, "No memory for message register\n");
> +			return -ENOMEM;
> +		}
> +
> +		reg_number =3D block_number * MPIC_MSGR_REGISTERS_PER_BLOCK +
> i;
> +		msgr->addr =3D &msgr_block->msgrs[i].msgr;
> +		msgr->mer =3D &msgr_block->mer;
> +		msgr->msr =3D &msgr_block->msr;
> +		atomic_set(&msgr->in_use, MSGR_FREE);
> +		msgr->num =3D reg_number;
> +
> +		if (receive_mask & (1 << i)) {
> +			struct resource irq;
> +
> +			if (of_irq_to_resource(np, irq_index, &irq) =3D=3D NO_IRQ)
> {
> +				dev_err(&dev->dev, "Missing interrupt
> specifier");
> +				kfree(msgr);
> +				return -EFAULT;
> +			}
> +			msgr->irq =3D irq.start;
> +			irq_index +=3D 1;
> +		} else {
> +			msgr->irq =3D NO_IRQ;
> +		}
> +
> +		mpic_msgrs[reg_number] =3D msgr;
> +		mpic_msgr_disable(msgr);
> +		dev_info(&dev->dev, "Register %d initialized: irq %d\n",
> +				 msgr->num, msgr->irq);
> +
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id mpic_msgr_ids[] =3D {
> +	{
> +		.compatible =3D "fsl,mpic-v3.1-msgr",
> +		.data =3D NULL,
> +	},
> +	{}
> +};
> +
> +static struct platform_driver mpic_msgr_driver =3D {
> +	.driver =3D {
> +		.name =3D "mpic-msgr",
> +		.owner =3D THIS_MODULE,
> +		.of_match_table =3D mpic_msgr_ids,
> +	},
> +	.probe =3D mpic_msgr_probe,
> +};
> +
> +static __init int mpic_msgr_init(void)
> +{
> +	return platform_driver_register(&mpic_msgr_driver);
> +}
> +subsys_initcall(mpic_msgr_init);
> --
> 1.6.3.3
>=20
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss

^ permalink raw reply

* linux-next: build warning after merge of the final tree (powercp tree related)
From: Stephen Rothwell @ 2011-04-29  3:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev
  Cc: linux-next, linux-kernel

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

Hi all,

After merging the final tree, today's linux-next build (powerpc64
allnoconfig) produced this warning:

WARNING: vmlinux.o(.text+0x907a): Section mismatch in reference from the variable generic_secondary_common_init to the variable .init.data:boot_cpu_count
The function generic_secondary_common_init() references
the variable __initdata boot_cpu_count.
This is often because generic_secondary_common_init lacks a __initdata 
annotation or the annotation of boot_cpu_count is wrong.

Caused by commit 9d07bc841c97 ("powerpc: Properly handshake CPUs going
out of boot spin loop").

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

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

^ permalink raw reply

* [RFC/PATCH 4/4] powerpc/pseries: Re-implement HVSI as part of hvc_vio
From: Benjamin Herrenschmidt @ 2011-04-29  1:18 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1304039922-32262-1-git-send-email-benh@kernel.crashing.org>

On pseries machines, consoles are provided by the hypervisor using
a low level get_chars/put_chars type interface. However, this is
really just a transport to the service processor which implements
them either as "raw" console (networked consoles, HMC, ...) or as
"hvsi" serial ports.

The later is a simple packet protocol on top of the raw character
interface that is supposed to convey additional "serial port" style
semantics. In practice however, all it does is provide a way to
read the CD line and set/clear our DTR line, that's it.

We currently implement the "raw" protocol as an hvc console backend
(/dev/hvcN) and the "hvsi" protocol using a separate tty driver
(/dev/hvsi0).

However this is quite impractical. The arbitrary difference between
the two type of devices has been a major source of user (and distro)
confusion. Additionally, there's an additional mini -hvsi implementation
in the pseries platform code for our low level debug console and early
boot kernel messages, which means code duplication, though that low
level variant is impractical as it's incapable of doing the initial
protocol negociation to establish the link to the FSP.

This essentially replaces the dedicated hvsi driver and the platform
udbg code completely by extending the existing hvc_vio backend used
in "raw" mode so that:

 - It now supports HVSI as well
 - We add support for hvc backend providing tiocm{get,set}
 - It also provides a udbg interface for early debug and boot console

This is overall less code, though this will only be obvious once we
remove the old "hvsi" driver, which is still available for now. When
the old driver is enabled, the new code still kicks in for the low
level udbg console, replacing the old mini implementation in the platform
code, it just doesn't provide the higher level "hvc" interface.

In addition to producing generally simler code, this has several benefits
over our current situation:

 - The user/distro only has to deal with /dev/hvcN for the hypervisor
console, avoiding all sort of confusion that has plagued us in the past

 - The tty, kernel and low level debug console all use the same code
base which supports the full protocol establishment process, thus the
console is now available much earlier than it used to be with the
old HVSI driver. The kernel console works much earlier and udbg is
available much earlier too. Hackers can enable a hard coded very-early
debug console as well that works with HVSI (previously that was only
supported for the "raw" mode).

I've tried to keep the same semantics as hvsi relative to how I react
to things like CD changes, with some subtle differences though:

 - I clear DTR on close if HUPCL is set

 - Current hvsi triggers a hangup if it detects a up->down transition
   on CD (you can still open a console with CD down). My new implementation
   triggers a hangup if the link to the FSP is severed, and severs it upon
   detecting a up->down transition on CD.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/Kconfig.debug               |   15 +
 arch/powerpc/include/asm/udbg.h          |    1 +
 arch/powerpc/kernel/udbg.c               |    3 +
 arch/powerpc/platforms/pseries/lpar.c    |  189 --------
 arch/powerpc/platforms/pseries/pseries.h |    3 +-
 arch/powerpc/platforms/pseries/setup.c   |    2 +-
 drivers/tty/hvc/Kconfig                  |    5 +
 drivers/tty/hvc/Makefile                 |    3 +-
 drivers/tty/hvc/hvc_console.c            |   23 +-
 drivers/tty/hvc/hvc_console.h            |    4 +
 drivers/tty/hvc/hvc_vio.c                |  725 ++++++++++++++++++++++++++++--
 11 files changed, 747 insertions(+), 226 deletions(-)

diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 2d38a50..5cc9ad0 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -188,6 +188,13 @@ config PPC_EARLY_DEBUG_LPAR
 	  Select this to enable early debugging for a machine with a HVC
 	  console on vterm 0.
 
+config PPC_EARLY_DEBUG_LPAR_HVSI
+	bool "LPAR HVSI Console"
+	depends on PPC_PSERIES
+	help
+	  Select this to enable early debugging for a machine with a HVSI
+	  console on a specified vterm.
+
 config PPC_EARLY_DEBUG_G5
 	bool "Apple G5"
 	depends on PPC_PMAC64
@@ -269,6 +276,14 @@ config PPC_EARLY_DEBUG_USBGECKO
 
 endchoice
 
+config PPC_EARLY_DEBUG_HVSI_VTERMNO
+	hex "vterm number to use with early debug HVSI"
+	depends on PPC_EARLY_DEBUG_LPAR_HVSI
+	default "0x30000000"
+	help
+	  You probably want 0x30000000 for your first serial port and
+	  0x30000001 for your second one
+
 config PPC_EARLY_DEBUG_44x_PHYSLOW
 	hex "Low 32 bits of early debug UART physical address"
 	depends on PPC_EARLY_DEBUG_44x
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index 11ae699..f6f7726 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -40,6 +40,7 @@ extern void udbg_adb_init_early(void);
 
 extern void __init udbg_early_init(void);
 extern void __init udbg_init_debug_lpar(void);
+extern void __init udbg_init_debug_lpar_hvsi(void);
 extern void __init udbg_init_pmac_realmode(void);
 extern void __init udbg_init_maple_realmode(void);
 extern void __init udbg_init_pas_realmode(void);
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 4aada69..78c3abe 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -31,6 +31,9 @@ void __init udbg_early_init(void)
 #if defined(CONFIG_PPC_EARLY_DEBUG_LPAR)
 	/* For LPAR machines that have an HVC console on vterm 0 */
 	udbg_init_debug_lpar();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI)
+	/* For LPAR machines that have an HVSI console on vterm 0 */
+	udbg_init_debug_lpar_hvsi();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
 	/* For use on Apple G5 machines */
 	udbg_init_pmac_realmode();
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index aabe8d7..7820e5d 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -52,195 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_norets);
 
 extern void pSeries_find_serial_port(void);
 
-
-static int vtermno;	/* virtual terminal# for udbg  */
-
-#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
-static void udbg_hvsi_putc(char c)
-{
-	/* packet's seqno isn't used anyways */
-	uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
-	int rc;
-
-	if (c == '\n')
-		udbg_hvsi_putc('\r');
-
-	do {
-		rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
-	} while (rc == H_BUSY);
-}
-
-static long hvsi_udbg_buf_len;
-static uint8_t hvsi_udbg_buf[256];
-
-static int udbg_hvsi_getc_poll(void)
-{
-	unsigned char ch;
-	int rc, i;
-
-	if (hvsi_udbg_buf_len == 0) {
-		rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
-		if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
-			/* bad read or non-data packet */
-			hvsi_udbg_buf_len = 0;
-		} else {
-			/* remove the packet header */
-			for (i = 4; i < hvsi_udbg_buf_len; i++)
-				hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
-			hvsi_udbg_buf_len -= 4;
-		}
-	}
-
-	if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
-		/* no data ready */
-		hvsi_udbg_buf_len = 0;
-		return -1;
-	}
-
-	ch = hvsi_udbg_buf[0];
-	/* shift remaining data down */
-	for (i = 1; i < hvsi_udbg_buf_len; i++) {
-		hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
-	}
-	hvsi_udbg_buf_len--;
-
-	return ch;
-}
-
-static int udbg_hvsi_getc(void)
-{
-	int ch;
-	for (;;) {
-		ch = udbg_hvsi_getc_poll();
-		if (ch == -1) {
-			/* This shouldn't be needed...but... */
-			volatile unsigned long delay;
-			for (delay=0; delay < 2000000; delay++)
-				;
-		} else {
-			return ch;
-		}
-	}
-}
-
-static void udbg_putcLP(char c)
-{
-	char buf[16];
-	unsigned long rc;
-
-	if (c == '\n')
-		udbg_putcLP('\r');
-
-	buf[0] = c;
-	do {
-		rc = plpar_put_term_char(vtermno, 1, buf);
-	} while(rc == H_BUSY);
-}
-
-/* Buffered chars getc */
-static long inbuflen;
-static long inbuf[2];	/* must be 2 longs */
-
-static int udbg_getc_pollLP(void)
-{
-	/* The interface is tricky because it may return up to 16 chars.
-	 * We save them statically for future calls to udbg_getc().
-	 */
-	char ch, *buf = (char *)inbuf;
-	int i;
-	long rc;
-	if (inbuflen == 0) {
-		/* get some more chars. */
-		inbuflen = 0;
-		rc = plpar_get_term_char(vtermno, &inbuflen, buf);
-		if (rc != H_SUCCESS)
-			inbuflen = 0;	/* otherwise inbuflen is garbage */
-	}
-	if (inbuflen <= 0 || inbuflen > 16) {
-		/* Catch error case as well as other oddities (corruption) */
-		inbuflen = 0;
-		return -1;
-	}
-	ch = buf[0];
-	for (i = 1; i < inbuflen; i++)	/* shuffle them down. */
-		buf[i-1] = buf[i];
-	inbuflen--;
-	return ch;
-}
-
-static int udbg_getcLP(void)
-{
-	int ch;
-	for (;;) {
-		ch = udbg_getc_pollLP();
-		if (ch == -1) {
-			/* This shouldn't be needed...but... */
-			volatile unsigned long delay;
-			for (delay=0; delay < 2000000; delay++)
-				;
-		} else {
-			return ch;
-		}
-	}
-}
-
-/* call this from early_init() for a working debug console on
- * vterm capable LPAR machines
- */
-void __init udbg_init_debug_lpar(void)
-{
-	vtermno = 0;
-	udbg_putc = udbg_putcLP;
-	udbg_getc = udbg_getcLP;
-	udbg_getc_poll = udbg_getc_pollLP;
-}
-
-/* returns 0 if couldn't find or use /chosen/stdout as console */
-void __init find_udbg_vterm(void)
-{
-	struct device_node *stdout_node;
-	const u32 *termno;
-	const char *name;
-
-	/* find the boot console from /chosen/stdout */
-	if (!of_chosen)
-		return;
-	name = of_get_property(of_chosen, "linux,stdout-path", NULL);
-	if (name == NULL)
-		return;
-	stdout_node = of_find_node_by_path(name);
-	if (!stdout_node)
-		return;
-	name = of_get_property(stdout_node, "name", NULL);
-	if (!name) {
-		printk(KERN_WARNING "stdout node missing 'name' property!\n");
-		goto out;
-	}
-
-	/* Check if it's a virtual terminal */
-	if (strncmp(name, "vty", 3) != 0)
-		goto out;
-	termno = of_get_property(stdout_node, "reg", NULL);
-	if (termno == NULL)
-		goto out;
-	vtermno = termno[0];
-
-	if (of_device_is_compatible(stdout_node, "hvterm1")) {
-		udbg_putc = udbg_putcLP;
-		udbg_getc = udbg_getcLP;
-		udbg_getc_poll = udbg_getc_pollLP;
-		add_preferred_console("hvc", termno[0] & 0xff, NULL);
-	} else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
-		vtermno = termno[0];
-		udbg_putc = udbg_hvsi_putc;
-		udbg_getc = udbg_hvsi_getc;
-		udbg_getc_poll = udbg_hvsi_getc_poll;
-		add_preferred_console("hvsi", termno[0] & 0xff, NULL);
-	}
-out:
-	of_node_put(stdout_node);
-}
-
 void vpa_init(int cpu)
 {
 	int hwcpu = get_hard_smp_processor_id(cpu);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index e9f6d28..24c7162 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -47,7 +47,8 @@ extern void pSeries_final_fixup(void);
 /* Poweron flag used for enabling auto ups restart */
 extern unsigned long rtas_poweron_auto;
 
-extern void find_udbg_vterm(void);
+/* Provided by HVC VIO */
+extern void hvc_vio_init_early(void);
 
 /* Dynamic logical Partitioning/Mobility */
 extern void dlpar_free_cc_nodes(struct device_node *);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index ab73ad2..15a8d72 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -489,7 +489,7 @@ static void __init pSeries_init_early(void)
 	pr_debug(" -> pSeries_init_early()\n");
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		find_udbg_vterm();
+		hvc_vio_init_early();
 
 	if (firmware_has_feature(FW_FEATURE_DABR))
 		ppc_md.set_dabr = pseries_set_dabr;
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index 6f2c980..e371753 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -19,6 +19,11 @@ config HVC_CONSOLE
 	  console. This driver allows each pSeries partition to have a console
 	  which is accessed via the HMC.
 
+config HVC_OLD_HVSI
+	bool "Old driver for pSeries serial port (/dev/hvsi*)"
+	depends on HVC_CONSOLE
+	default n
+
 config HVC_ISERIES
 	bool "iSeries Hypervisor Virtual Console support"
 	depends on PPC_ISERIES
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index 40a25d9..69a444b 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -1,4 +1,5 @@
-obj-$(CONFIG_HVC_CONSOLE)	+= hvc_vio.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE)	+= hvc_vio.o
+obj-$(CONFIG_HVC_OLD_HVSI)	+= hvsi.o
 obj-$(CONFIG_HVC_ISERIES)	+= hvc_iseries.o
 obj-$(CONFIG_HVC_RTAS)		+= hvc_rtas.o
 obj-$(CONFIG_HVC_TILE)		+= hvc_tile.o
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index e9cba13..f8ff6f5 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -184,7 +184,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
 }
 
 static int __init hvc_console_setup(struct console *co, char *options)
-{
+{	
 	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
 		return -ENODEV;
 
@@ -745,6 +745,25 @@ static int khvcd(void *unused)
 	return 0;
 }
 
+static int hvc_tiocmget(struct tty_struct *tty)
+{
+	struct hvc_struct *hp = tty->driver_data;
+
+	if (!hp || !hp->ops->tiocmget)
+		return -EINVAL;
+	return hp->ops->tiocmget(hp);
+}
+
+static int hvc_tiocmset(struct tty_struct *tty,
+			unsigned int set, unsigned int clear)
+{
+	struct hvc_struct *hp = tty->driver_data;
+
+	if (!hp || !hp->ops->tiocmset)
+		return -EINVAL;
+	return hp->ops->tiocmset(hp, set, clear);
+}
+
 static const struct tty_operations hvc_ops = {
 	.open = hvc_open,
 	.close = hvc_close,
@@ -753,6 +772,8 @@ static const struct tty_operations hvc_ops = {
 	.unthrottle = hvc_unthrottle,
 	.write_room = hvc_write_room,
 	.chars_in_buffer = hvc_chars_in_buffer,
+	.tiocmget = hvc_tiocmget,
+	.tiocmset = hvc_tiocmset,
 };
 
 struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
index 54381eb..c335a14 100644
--- a/drivers/tty/hvc/hvc_console.h
+++ b/drivers/tty/hvc/hvc_console.h
@@ -73,6 +73,10 @@ struct hv_ops {
 	int (*notifier_add)(struct hvc_struct *hp, int irq);
 	void (*notifier_del)(struct hvc_struct *hp, int irq);
 	void (*notifier_hangup)(struct hvc_struct *hp, int irq);
+
+	/* tiocmget/set implementation */
+	int (*tiocmget)(struct hvc_struct *hp);
+	int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear);
 };
 
 /* Register a vterm and a slot index for use as a console (console_init) */
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index e6eea14..8e632bc 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -27,15 +27,27 @@
  * 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
+ *
+ * TODO:
+ *
+ *   - handle error in sending hvsi protocol packets
+ *   - retry nego on subsequent sends ?
  */
 
+#undef DEBUG
+
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/console.h>
 
 #include <asm/hvconsole.h>
 #include <asm/vio.h>
 #include <asm/prom.h>
 #include <asm/firmware.h>
+#include <asm/hvsi.h>
+#include <asm/udbg.h>
 
 #include "hvc_console.h"
 
@@ -43,14 +55,47 @@ static const char hvc_driver_name[] = "hvc_console";
 
 static struct vio_device_id hvc_driver_table[] __devinitdata = {
 	{"serial", "hvterm1"},
+#ifndef HVC_OLD_HVSI
+	{"serial", "hvterm-protocol"},
+#endif
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, hvc_driver_table);
 
-static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
+typedef enum hv_protocol {
+	HV_PROTOCOL_RAW,
+	HV_PROTOCOL_HVSI
+} hv_protocol_t;
+
+#define HV_INBUF_SIZE		255
+
+struct hvterm_priv {
+	u32		termno;		/* HV term number */
+	hv_protocol_t	proto;		/* Raw data or HVSI packets */
+	unsigned int	inbuf_len;	/* Data in input buffer */
+	unsigned char	inbuf[HV_INBUF_SIZE];
+	unsigned int	inbuf_cur;	/* Cursor in input buffer */
+	unsigned int	inbuf_pktlen;	/* HVSI packet lenght from cursor */
+	atomic_t	seqno;		/* HVSI packet sequence number */
+	unsigned int	opened:1;	/* HVSI driver opened */
+	unsigned int	established:1;	/* HVSI protocol established */
+	unsigned int 	is_console:1;	/* Used as a kernel console device */
+	unsigned int	mctrl_update:1;	/* HVSI modem control updated */
+	unsigned short	mctrl;		/* HVSI modem control */
+	struct tty_struct *tty;		/* TTY structure */
+};
+static struct hvterm_priv *hvterm_privs[MAX_NR_HVC_CONSOLES];
+
+/* For early boot console */
+static struct hvterm_priv hvterm_priv0;
+
+static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count)
 {
-	unsigned long got;
-	int i;
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+	unsigned long got, i;
+
+	if (WARN_ON(!pv))
+		return 0;
 
 	/*
 	 * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion
@@ -60,7 +105,7 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
 	if (count < SIZE_VIO_GET_CHARS)
 		return -EAGAIN;
 
-	got = hvc_get_chars(vtermno, buf, count);
+	got = hvc_get_chars(pv->termno, buf, count);
 
 	/*
 	 * Work around a HV bug where it gives us a null
@@ -70,32 +115,527 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
 		if (buf[i] == 0 && buf[i-1] == '\r') {
 			--got;
 			if (i < got)
-				memmove(&buf[i], &buf[i+1],
-					got - i);
+				memmove(&buf[i], &buf[i+1], got - i);
 		}
 	}
 	return got;
 }
 
-static const struct hv_ops hvc_get_put_ops = {
-	.get_chars = filtered_get_chars,
-	.put_chars = hvc_put_chars,
+static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	return hvc_put_chars(pv->termno, buf, count);
+}
+
+static const struct hv_ops hvterm_raw_ops = {
+	.get_chars = hvterm_raw_get_chars,
+	.put_chars = hvterm_raw_put_chars,
 	.notifier_add = notifier_add_irq,
 	.notifier_del = notifier_del_irq,
 	.notifier_hangup = notifier_hangup_irq,
 };
 
+static int hvterm_hvsi_send_packet(struct hvterm_priv *pv, struct hvsi_header *packet)
+{
+	packet->seqno = atomic_inc_return(&pv->seqno);
+
+	/* Assumes that always succeeds, works in practice */
+	return hvc_put_chars(pv->termno, (char *)packet, packet->len);
+}
+
+static void hvterm_hvsi_start_handshake(struct hvterm_priv *pv)
+{
+	struct hvsi_query q;
+
+	/* Reset state */
+	pv->established = 0;
+	atomic_set(&pv->seqno, 0);
+
+	pr_devel("HVSI@%x: Handshaking started\n", pv->termno);
+
+	/* Send version query */
+	q.hdr.type = VS_QUERY_PACKET_HEADER;
+	q.hdr.len = sizeof(struct hvsi_query);
+	q.verb = VSV_SEND_VERSION_NUMBER;
+	hvterm_hvsi_send_packet(pv, &q.hdr);
+}
+
+static int hvterm_hvsi_send_close(struct hvterm_priv *pv)
+{
+	struct hvsi_control ctrl;
+
+	pv->established = 0;
+
+	ctrl.hdr.type = VS_CONTROL_PACKET_HEADER;
+	ctrl.hdr.len = sizeof(struct hvsi_control);
+	ctrl.verb = VSV_CLOSE_PROTOCOL;
+	return hvterm_hvsi_send_packet(pv, &ctrl.hdr);
+}
+
+static void hvterm_cd_change(struct hvterm_priv *pv, int cd)
+{
+	if (cd)
+		pv->mctrl |= TIOCM_CD;
+	else {
+		pv->mctrl &= ~TIOCM_CD;
+
+		/* We copy the existing hvsi driver semantics
+		 * here which are to trigger a hangup when
+		 * we get a carrier loss.
+		 * Closing our connection to the server will
+		 * do just that.
+		 */
+		if (!pv->is_console && pv->opened) {
+			pr_devel("HVSI@%x Carrier lost, hanging up !\n",
+				 pv->termno);
+			hvterm_hvsi_send_close(pv);
+		}
+	}
+}
+
+static void hvterm_hvsi_got_control(struct hvterm_priv *pv)
+{
+	struct hvsi_control *pkt = (struct hvsi_control *)pv->inbuf;
+
+	switch (pkt->verb) {
+	case VSV_CLOSE_PROTOCOL:
+		/* We restart the handshaking */
+		hvterm_hvsi_start_handshake(pv);
+		break;
+	case VSV_MODEM_CTL_UPDATE:
+		/* Transition of carrier detect */
+		hvterm_cd_change(pv, pkt->word & HVSI_TSCD);
+		break;
+	}
+}
+
+static void hvterm_hvsi_got_query(struct hvterm_priv *pv)
+{
+	struct hvsi_query *pkt = (struct hvsi_query *)pv->inbuf;
+	struct hvsi_query_response r;
+
+	/* We only handle version queries */
+	if (pkt->verb != VSV_SEND_VERSION_NUMBER)
+		return;
+
+	pr_devel("HVSI@%x: Got version query, sending response...\n",
+		 pv->termno);
+
+	/* Send version response */
+	r.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+	r.hdr.len = sizeof(struct hvsi_query_response);
+	r.verb = VSV_SEND_VERSION_NUMBER;
+	r.u.version = HVSI_VERSION;
+	r.query_seqno = pkt->hdr.seqno;
+	hvterm_hvsi_send_packet(pv, &r.hdr);
+
+	/* Assume protocol is open now */
+	pv->established = 1;
+}
+
+static void hvterm_hvsi_got_response(struct hvterm_priv *pv)
+{
+	struct hvsi_query_response *r = (struct hvsi_query_response *)pv->inbuf;
+
+	switch(r->verb) {
+	case VSV_SEND_MODEM_CTL_STATUS:
+		hvterm_cd_change(pv, r->u.mctrl_word & HVSI_TSCD);
+		pv->mctrl_update = 1;
+		break;
+	}
+}
+
+static int hvterm_hvsi_check_packet(struct hvterm_priv *pv)
+{
+	u8 len, type;
+
+	/* Check header validity. If it's invalid, we ditch
+	 * the whole buffer and hope we eventually resync
+	 */
+	if (pv->inbuf[0] < 0xfc) {
+		pv->inbuf_len = pv->inbuf_pktlen = 0;
+		return 0;
+	}
+	type = pv->inbuf[0];
+	len = pv->inbuf[1];
+
+	/* Packet incomplete ? */
+	if (pv->inbuf_len < len)
+		return 0;
+
+	pr_devel("HVSI@%x: Got packet type %x len %d bytes:\n",
+		 pv->termno, type, len);
+
+	/* We have a packet, yay ! Handle it */
+	switch(type) {
+	case VS_DATA_PACKET_HEADER:
+		pv->inbuf_pktlen = len - 4;
+		pv->inbuf_cur = 4;
+		return 1;
+	case VS_CONTROL_PACKET_HEADER:
+		hvterm_hvsi_got_control(pv);
+		break;
+	case VS_QUERY_PACKET_HEADER:
+		hvterm_hvsi_got_query(pv);
+		break;
+	case VS_QUERY_RESPONSE_PACKET_HEADER:
+		hvterm_hvsi_got_response(pv);
+		break;
+	}
+
+	/* Swallow packet and retry */
+	pv->inbuf_len -= len;
+	memmove(pv->inbuf, &pv->inbuf[len], pv->inbuf_len);
+	return 1;
+}
+
+static int hvterm_hvsi_get_packet(struct hvterm_priv *pv)
+{
+	/* If we have room in the buffer, ask HV for more */
+	if (pv->inbuf_len < HV_INBUF_SIZE)
+		pv->inbuf_len += hvc_get_chars(pv->termno,
+					       &pv->inbuf[pv->inbuf_len],
+					       HV_INBUF_SIZE - pv->inbuf_len);
+	/*
+	 * If we have at least 4 bytes in the buffer, check for
+	 * a full packet and retry
+	 */
+	if (pv->inbuf_len >= 4)
+		return hvterm_hvsi_check_packet(pv);
+	return 0;
+}
+
+static int hvterm_hvsi_get_chars(uint32_t vtermno, char *buf, int count)
+{
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+	unsigned int tries, read = 0;
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	/* If we aren't open, dont do anything in order to avoid races
+	 * with connection establishment. The hvc core will call this
+	 * before we have returned from notifier_add(), and we need to
+	 * avoid multiple users playing with the receive buffer
+	 */
+	if (!pv->opened)
+		return 0;
+
+	/* We try twice, once with what data we have and once more
+	 * after we try to fetch some more from the hypervisor
+	 */
+	for (tries = 1; count && tries < 2; tries++) {
+		/* Consume existing data packet */
+		if (pv->inbuf_pktlen) {
+			unsigned int l = min(count, (int)pv->inbuf_pktlen);
+			memcpy(buf, &pv->inbuf[pv->inbuf_cur], l);
+			pv->inbuf_cur += l;
+			pv->inbuf_pktlen -= l;
+			count -= read;
+			read += l;
+		}
+		if (count == 0)
+			break;
+
+		/* Data packet fully consumed, move down remaning data */
+		if (pv->inbuf_cur) {
+			pv->inbuf_len -= pv->inbuf_cur;
+			memmove(pv->inbuf, &pv->inbuf[pv->inbuf_cur], pv->inbuf_len);
+			pv->inbuf_cur = 0;
+		}
+
+		/* Try to get another packet */
+		if (hvterm_hvsi_get_packet(pv))
+			tries--;
+	}
+	if (!pv->established) {
+		pr_devel("HVSI@%x: returning -EPIPE\n", pv->termno);
+		return -EPIPE;
+	}
+	return read;
+}
+
+static int hvterm_hvsi_put_chars(uint32_t vtermno, const char *buf, int count)
+{
+	struct hvterm_priv *pv = hvterm_privs[vtermno];
+	struct hvsi_data dp;
+	int rc, adjcount = min(count, HVSI_MAX_OUTGOING_DATA);
+
+	if (WARN_ON(!pv))
+		return 0;
+
+	dp.hdr.type = VS_DATA_PACKET_HEADER;
+	dp.hdr.len = adjcount + sizeof(struct hvsi_header);
+	memcpy(dp.data, buf, adjcount);
+	rc = hvterm_hvsi_send_packet(pv, &dp.hdr);
+	if (rc <= 0)
+		return rc;
+	return adjcount;
+}
+
+static void maybe_msleep(unsigned long ms)
+{
+	/* During early boot, IRQs are disabled, use mdelay */
+	if (irqs_disabled())
+		mdelay(ms);
+	else
+		msleep(ms);
+}
+
+static int hvterm_hvsi_read_mctrl(struct hvterm_priv *pv)
+{
+	struct hvsi_query q;
+	int rc, timeout;
+
+	pr_devel("HVSI@%x: Querying modem control status...\n",
+		 pv->termno);
+
+	pv->mctrl_update = 0;
+	q.hdr.type = VS_QUERY_PACKET_HEADER;
+	q.hdr.len = sizeof(struct hvsi_query);
+	q.hdr.seqno = atomic_inc_return(&pv->seqno);
+	q.verb = VSV_SEND_MODEM_CTL_STATUS;
+	rc = hvterm_hvsi_send_packet(pv, &q.hdr);
+	if (rc <= 0) {
+		pr_devel("HVSI@%x: Error %d...\n", pv->termno, rc);
+		return rc;
+	}
+
+	/* Try for up to 1s */
+	for (timeout = 0; timeout < 1000; timeout++) {
+		if (!pv->established)
+			return -ENXIO;
+		if (pv->mctrl_update)
+			return 0;
+		if (!hvterm_hvsi_get_packet(pv))
+			maybe_msleep(1);
+	}
+	return -EIO;
+}
+
+static int hvterm_hvsi_write_mctrl(struct hvterm_priv *pv, int dtr)
+{
+	struct hvsi_control ctrl;
+
+	pr_devel("HVSI@%x: %s DTR...\n", pv->termno,
+		 dtr ? "Setting" : "Clearing");
+
+	ctrl.hdr.type = VS_CONTROL_PACKET_HEADER,
+	ctrl.hdr.len = sizeof(struct hvsi_control);
+	ctrl.verb = VSV_SET_MODEM_CTL;
+	ctrl.mask = HVSI_TSDTR;
+	ctrl.word = dtr ? HVSI_TSDTR : 0;
+	if (dtr)
+		pv->mctrl |= TIOCM_DTR;
+	else
+		pv->mctrl &= ~TIOCM_DTR;
+	return hvterm_hvsi_send_packet(pv, &ctrl.hdr);
+}
+
+static void hvterm_hvsi_establish(struct hvterm_priv *pv)
+{
+	int timeout;
+
+	/* Try for up to 10ms, there can be a packet to
+	 * start the process waiting for us...
+	 */
+	for (timeout = 0; timeout < 10; timeout++) {
+		if (pv->established)
+			goto established;
+		if (!hvterm_hvsi_get_packet(pv))
+			maybe_msleep(1);
+	}
+
+	/* Failed, send a close connection packet just
+	 * in case
+	 */
+	hvterm_hvsi_send_close(pv);
+
+	/* Then restart handshake */
+	hvterm_hvsi_start_handshake(pv);
+
+	/* Try for up to 100ms */
+	for (timeout = 0; timeout < 100; timeout++) {
+		if (pv->established)
+			goto established;
+		if (!hvterm_hvsi_get_packet(pv))
+			maybe_msleep(1);
+	}
+
+	if (!pv->established) {
+		pr_devel("HVSI@%x: Timeout handshaking, giving up !\n",
+			 pv->termno);
+		return;
+	}
+ established:
+	/* Query modem control lines */
+	hvterm_hvsi_read_mctrl(pv);
+
+	/* Set our own DTR */
+	hvterm_hvsi_write_mctrl(pv, 1);
+
+	/* Set the opened flag so reads are allowed */
+	wmb();
+	pv->opened = 1;
+}
+
+static int hvterm_hvsi_open(struct hvc_struct *hp, int data)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+	int rc;
+
+	pr_devel("HVSI@%x: open !\n", pv->termno);
+
+	rc = notifier_add_irq(hp, data);
+	if (rc)
+		return rc;
+
+	/* Keep track of the tty data structure */
+	pv->tty = tty_kref_get(hp->tty);
+
+	hvterm_hvsi_establish(pv);
+	return 0;
+}
+
+static void hvterm_hvsi_shutdown(struct hvc_struct *hp, struct hvterm_priv *pv)
+{
+	unsigned long flags;
+
+	if (!pv->is_console) {
+		pr_devel("HVSI@%x: Not a console, tearing down\n",
+			 pv->termno);
+
+		/* Clear opened, synchronize with khvcd */
+		spin_lock_irqsave(&hp->lock, flags);
+		pv->opened = 0;
+		spin_unlock_irqrestore(&hp->lock, flags);
+
+		/* Clear our own DTR */
+		if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL))
+			hvterm_hvsi_write_mctrl(pv, 0);
+
+		/* Tear down the connection */
+		hvterm_hvsi_send_close(pv);
+	}
+
+	if (pv->tty)
+		tty_kref_put(pv->tty);
+	pv->tty = NULL;
+}
+
+static void hvterm_hvsi_close(struct hvc_struct *hp, int data)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	pr_devel("HVSI@%x: close !\n", pv->termno);
+
+	hvterm_hvsi_shutdown(hp, pv);
+
+	notifier_del_irq(hp, data);
+}
+
+void hvterm_hvsi_hangup(struct hvc_struct *hp, int data)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	pr_devel("HVSI@%x: hangup !\n", pv->termno);
+
+	hvterm_hvsi_shutdown(hp, pv);
+
+	notifier_hangup_irq(hp, data);
+}
+
+static int hvterm_hvsi_tiocmget(struct hvc_struct *hp)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	if (!pv)
+		return -EINVAL;
+	return pv->mctrl;
+}
+
+static int hvterm_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
+				unsigned int clear)
+{
+	struct hvterm_priv *pv = hvterm_privs[hp->vtermno];
+
+	pr_devel("HVSI@%x: Set modem control, set=%x,clr=%x\n",
+		 pv->termno, set, clear);
+
+	if (set & TIOCM_DTR)
+		hvterm_hvsi_write_mctrl(pv, 1);
+	else if (clear & TIOCM_DTR)
+		hvterm_hvsi_write_mctrl(pv, 0);
+
+	return 0;
+}
+
+static const struct hv_ops hvterm_hvsi_ops = {
+	.get_chars = hvterm_hvsi_get_chars,
+	.put_chars = hvterm_hvsi_put_chars,
+	.notifier_add = hvterm_hvsi_open,
+	.notifier_del = hvterm_hvsi_close,
+	.notifier_hangup = hvterm_hvsi_hangup,
+	.tiocmget = hvterm_hvsi_tiocmget,
+	.tiocmset = hvterm_hvsi_tiocmset,
+};
+
 static int __devinit hvc_vio_probe(struct vio_dev *vdev,
-				const struct vio_device_id *id)
+				   const struct vio_device_id *id)
 {
+	const struct hv_ops *ops;
 	struct hvc_struct *hp;
+	struct hvterm_priv *pv;
+	hv_protocol_t proto;
+	int i, termno = -1;
 
 	/* probed with invalid parameters. */
 	if (!vdev || !id)
 		return -EPERM;
 
-	hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops,
-			MAX_VIO_PUT_CHARS);
+	if (of_device_is_compatible(vdev->dev.of_node, "hvterm1")) {
+		proto = HV_PROTOCOL_RAW;
+		ops = &hvterm_raw_ops;
+	} else if (of_device_is_compatible(vdev->dev.of_node, "hvterm-protocol")) {
+		proto = HV_PROTOCOL_HVSI;
+		ops = &hvterm_hvsi_ops;
+	} else {
+		pr_err("hvc_vio: Unkown protocol for %s\n", vdev->dev.of_node->full_name);
+		return -ENXIO;
+	}
+
+	pr_devel("hvc_vio_probe() device %s, using %s protocol\n",
+		 vdev->dev.of_node->full_name,
+		 proto == HV_PROTOCOL_RAW ? "raw" : "hvsi");
+
+	/* Is it our boot one ? */
+	if (hvterm_privs[0] == &hvterm_priv0 &&
+	    vdev->unit_address == hvterm_priv0.termno) {
+		pv = hvterm_privs[0];
+		termno = 0;
+		pr_devel("->boot console, using termno 0\n");
+	}
+	/* nope, allocate a new one */
+	else {
+		for (i = 0; i < MAX_NR_HVC_CONSOLES && termno < 0; i++)
+			if (!hvterm_privs[i])
+				termno = i;
+		pr_devel("->non-boot console, using termno %d\n", termno);
+		if (termno < 0)
+			return -ENODEV;
+		pv = kzalloc(sizeof(struct hvterm_priv), GFP_KERNEL);
+		if (!pv)
+			return -ENOMEM;
+		pv->termno = vdev->unit_address;
+		pv->proto = proto;
+		hvterm_privs[termno] = pv;
+	}
+
+	hp = hvc_alloc(termno, vdev->irq, ops, MAX_VIO_PUT_CHARS);
 	if (IS_ERR(hp))
 		return PTR_ERR(hp);
 	dev_set_drvdata(&vdev->dev, hp);
@@ -106,8 +646,16 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
 static int __devexit hvc_vio_remove(struct vio_dev *vdev)
 {
 	struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
+	int rc, termno;
 
-	return hvc_remove(hp);
+	termno = hp->vtermno;
+	rc = hvc_remove(hp);
+	if (rc == 0) {
+		if (hvterm_privs[termno] != &hvterm_priv0)
+			kfree(hvterm_privs[termno]);
+		hvterm_privs[termno] = NULL;
+	}
+	return rc;
 }
 
 static struct vio_driver hvc_vio_driver = {
@@ -140,34 +688,145 @@ static void __exit hvc_vio_exit(void)
 }
 module_exit(hvc_vio_exit);
 
-/* the device tree order defines our numbering */
-static int hvc_find_vtys(void)
+static void udbg_hvc_putc(char c)
 {
-	struct device_node *vty;
-	int num_found = 0;
+	int count = -1;
 
-	for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
-			vty = of_find_node_by_name(vty, "vty")) {
-		const uint32_t *vtermno;
+	if (c == '\n')
+		udbg_hvc_putc('\r');
 
-		/* We have statically defined space for only a certain number
-		 * of console adapters.
-		 */
-		if (num_found >= MAX_NR_HVC_CONSOLES) {
-			of_node_put(vty);
+	do {
+		switch(hvterm_priv0.proto) {
+		case HV_PROTOCOL_RAW:
+			count = hvterm_raw_put_chars(0, &c, 1);
+			break;
+		case HV_PROTOCOL_HVSI:
+			count = hvterm_hvsi_put_chars(0, &c, 1);
 			break;
 		}
+	} while(count == 0);
+}
+
+static int udbg_hvc_getc_poll(void)
+{
+	int rc = 0;
+	char c;
 
-		vtermno = of_get_property(vty, "reg", NULL);
-		if (!vtermno)
-			continue;
+	switch(hvterm_priv0.proto) {
+	case HV_PROTOCOL_RAW:
+		rc = hvterm_raw_get_chars(0, &c, 1);
+		break;
+	case HV_PROTOCOL_HVSI:
+		rc = hvterm_hvsi_get_chars(0, &c, 1);
+		break;
+	}
+	if (!rc)
+		return -1;
+	return c;
+}
 
-		if (of_device_is_compatible(vty, "hvterm1")) {
-			hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
-			++num_found;
+static int udbg_hvc_getc(void)
+{
+	int ch;
+	for (;;) {
+		ch = udbg_hvc_getc_poll();
+		if (ch == -1) {
+			/* This shouldn't be needed...but... */
+			volatile unsigned long delay;
+			for (delay=0; delay < 2000000; delay++)
+				;
+		} else {
+			return ch;
 		}
 	}
+}
+
+void __init hvc_vio_init_early(void)
+{
+	struct device_node *stdout_node;
+	const u32 *termno;
+	const char *name;
+	const struct hv_ops *ops;
+
+	/* find the boot console from /chosen/stdout */
+	if (!of_chosen)
+		return;
+	name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL)
+		return;
+	stdout_node = of_find_node_by_path(name);
+	if (!stdout_node)
+		return;
+	name = of_get_property(stdout_node, "name", NULL);
+	if (!name) {
+		printk(KERN_WARNING "stdout node missing 'name' property!\n");
+		goto out;
+	}
+
+	/* Check if it's a virtual terminal */
+	if (strncmp(name, "vty", 3) != 0)
+		goto out;
+	termno = of_get_property(stdout_node, "reg", NULL);
+	if (termno == NULL)
+		goto out;
+	hvterm_priv0.termno = *termno;
+	hvterm_priv0.is_console = 1;
+	hvterm_privs[0] = &hvterm_priv0;
+
+	/* Check the protocol */
+	if (of_device_is_compatible(stdout_node, "hvterm1")) {
+		hvterm_priv0.proto = HV_PROTOCOL_RAW;
+		ops = &hvterm_raw_ops;
+	}
+	else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
+		hvterm_priv0.proto = HV_PROTOCOL_HVSI;
+		ops = &hvterm_hvsi_ops;
+		/* HVSI, perform the handshake now */
+		hvterm_hvsi_establish(&hvterm_priv0);
+	} else
+		goto out;
+	udbg_putc = udbg_hvc_putc;
+	udbg_getc = udbg_hvc_getc;
+	udbg_getc_poll = udbg_hvc_getc_poll;
+#ifdef HVC_OLD_HVSI
+	/* When using the old HVSI driver don't register the HVC
+	 * backend for HVSI, only do udbg
+	 */
+	if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
+		goto out;
+#endif
+	add_preferred_console("hvc", 0, NULL);
+	hvc_instantiate(0, 0, ops);
+out:
+	of_node_put(stdout_node);
+}
+
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR
+void __init udbg_init_debug_lpar(void)
+{
+	hvterm_privs[0] = &hvterm_priv0;
+	hvterm_priv0.termno = 0;
+	hvterm_priv0.proto = HV_PROTOCOL_RAW;
+	hvterm_priv0.is_console = 1;
+	udbg_putc = udbg_putc;
+	udbg_getc = udbg_getc;
+	udbg_getc_poll = udbg_getc_poll;
+}
+#endif /* CONFIG_PPC_EARLY_DEBUG_LPAR */
 
-	return num_found;
+#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI
+void __init udbg_init_debug_lpar_hvsi(void)
+{
+	hvterm_privs[0] = &hvterm_priv0;
+	hvterm_priv0.termno = CONFIG_PPC_EARLY_DEBUG_HVSI_VTERMNO;
+	hvterm_priv0.proto = HV_PROTOCOL_HVSI;
+	hvterm_priv0.is_console = 1;
+	udbg_putc = udbg_putc;
+	udbg_getc = udbg_getc;
+	udbg_getc_poll = udbg_getc_poll;
+	hvterm_hvsi_establish(&hvterm_priv0);
 }
-console_initcall(hvc_find_vtys);
+#endif /* CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI */
-- 
1.7.1

^ permalink raw reply related

* [RFC/PATCH 2/4] powerpc/pseries: Factor HVSI header struct in packet definitions
From: Benjamin Herrenschmidt @ 2011-04-29  1:18 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1304039922-32262-1-git-send-email-benh@kernel.crashing.org>

Embed the struct hvsi_header in the various packet definitions
rather than open coding it multiple times. Will help provide
stronger type checking.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/hvsi.h |   16 ++-------
 drivers/tty/hvc/hvsi.c          |   66 +++++++++++++++++++-------------------
 2 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h
index f13125a..ab2ddd7 100644
--- a/arch/powerpc/include/asm/hvsi.h
+++ b/arch/powerpc/include/asm/hvsi.h
@@ -29,16 +29,12 @@ struct hvsi_header {
 } __attribute__((packed));
 
 struct hvsi_data {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
+	struct hvsi_header hdr;
 	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
 } __attribute__((packed));
 
 struct hvsi_control {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
+	struct hvsi_header hdr;
 	uint16_t verb;
 	/* optional depending on verb: */
 	uint32_t word;
@@ -46,16 +42,12 @@ struct hvsi_control {
 } __attribute__((packed));
 
 struct hvsi_query {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
+	struct hvsi_header hdr;
 	uint16_t verb;
 } __attribute__((packed));
 
 struct hvsi_query_response {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
+	struct hvsi_header hdr;
 	uint16_t verb;
 	uint16_t query_seqno;
 	union {
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 0b35793..c94e2f5 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -295,18 +295,18 @@ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
 	struct hvsi_query_response packet __ALIGNED__;
 	int wrote;
 
-	packet.type = VS_QUERY_RESPONSE_PACKET_HEADER;
-	packet.len = sizeof(struct hvsi_query_response);
-	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
+	packet.hdr.len = sizeof(struct hvsi_query_response);
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
 	packet.verb = VSV_SEND_VERSION_NUMBER;
 	packet.u.version = HVSI_VERSION;
 	packet.query_seqno = query_seqno+1;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (wrote != packet.hdr.len) {
 		printk(KERN_ERR "hvsi%i: couldn't send query response!\n",
 			hp->index);
 		return -EIO;
@@ -321,7 +321,7 @@ static void hvsi_recv_query(struct hvsi_struct *hp, uint8_t *packet)
 
 	switch (hp->state) {
 		case HVSI_WAIT_FOR_VER_QUERY:
-			hvsi_version_respond(hp, query->seqno);
+			hvsi_version_respond(hp, query->hdr.seqno);
 			__set_state(hp, HVSI_OPEN);
 			break;
 		default:
@@ -579,16 +579,16 @@ static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
 	struct hvsi_query packet __ALIGNED__;
 	int wrote;
 
-	packet.type = VS_QUERY_PACKET_HEADER;
-	packet.len = sizeof(struct hvsi_query);
-	packet.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.type = VS_QUERY_PACKET_HEADER;
+	packet.hdr.len = sizeof(struct hvsi_query);
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
 	packet.verb = verb;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (wrote != packet.hdr.len) {
 		printk(KERN_ERR "hvsi%i: couldn't send query (%i)!\n", hp->index,
 			wrote);
 		return -EIO;
@@ -622,20 +622,20 @@ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
 	struct hvsi_control packet __ALIGNED__;
 	int wrote;
 
-	packet.type = VS_CONTROL_PACKET_HEADER,
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = sizeof(struct hvsi_control);
+	packet.hdr.type = VS_CONTROL_PACKET_HEADER,
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.len = sizeof(struct hvsi_control);
 	packet.verb = VSV_SET_MODEM_CTL;
 	packet.mask = HVSI_TSDTR;
 
 	if (mctrl & TIOCM_DTR)
 		packet.word = HVSI_TSDTR;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (wrote != packet.len) {
+	wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (wrote != packet.hdr.len) {
 		printk(KERN_ERR "hvsi%i: couldn't set DTR!\n", hp->index);
 		return -EIO;
 	}
@@ -705,13 +705,13 @@ static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
 
 	BUG_ON(count > HVSI_MAX_OUTGOING_DATA);
 
-	packet.type = VS_DATA_PACKET_HEADER;
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = count + sizeof(struct hvsi_header);
+	packet.hdr.type = VS_DATA_PACKET_HEADER;
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.len = count + sizeof(struct hvsi_header);
 	memcpy(&packet.data, buf, count);
 
-	ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
-	if (ret == packet.len) {
+	ret = hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
+	if (ret == packet.hdr.len) {
 		/* return the number of chars written, not the packet length */
 		return count;
 	}
@@ -722,15 +722,15 @@ static void hvsi_close_protocol(struct hvsi_struct *hp)
 {
 	struct hvsi_control packet __ALIGNED__;
 
-	packet.type = VS_CONTROL_PACKET_HEADER;
-	packet.seqno = atomic_inc_return(&hp->seqno);
-	packet.len = 6;
+	packet.hdr.type = VS_CONTROL_PACKET_HEADER;
+	packet.hdr.seqno = atomic_inc_return(&hp->seqno);
+	packet.hdr.len = 6;
 	packet.verb = VSV_CLOSE_PROTOCOL;
 
-	pr_debug("%s: sending %i bytes\n", __func__, packet.len);
-	dbg_dump_hex((uint8_t*)&packet, packet.len);
+	pr_debug("%s: sending %i bytes\n", __func__, packet.hdr.len);
+	dbg_dump_hex((uint8_t*)&packet, packet.hdr.len);
 
-	hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
+	hvc_put_chars(hp->vtermno, (char *)&packet, packet.hdr.len);
 }
 
 static int hvsi_open(struct tty_struct *tty, struct file *filp)
-- 
1.7.1

^ permalink raw reply related

* [RFC/PATCH 3/4] powerpc/udbg: Register udbg console generically
From: Benjamin Herrenschmidt @ 2011-04-29  1:18 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1304039922-32262-1-git-send-email-benh@kernel.crashing.org>

When CONFIG_PPC_EARLY_DEBUG is set, call register_early_udbg_console()
early from generic code.

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

diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index e39cad8..4aada69 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -66,6 +66,8 @@ void __init udbg_early_init(void)
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
 	console_loglevel = 10;
+
+	register_early_udbg_console();
 #endif
 }
 
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 6f0ed3a..aabe8d7 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -193,8 +193,6 @@ void __init udbg_init_debug_lpar(void)
 	udbg_putc = udbg_putcLP;
 	udbg_getc = udbg_getcLP;
 	udbg_getc_poll = udbg_getc_pollLP;
-
-	register_early_udbg_console();
 }
 
 /* returns 0 if couldn't find or use /chosen/stdout as console */
-- 
1.7.1

^ permalink raw reply related

* [RFC/PATCH 1/4] powerpc/hvsi: Move HVSI protocol definitions to a header file
From: Benjamin Herrenschmidt @ 2011-04-29  1:18 UTC (permalink / raw)
  To: linuxppc-dev

This moves various HVSI protocol definitions from the hvsi.c
driver to a header file that can be used later on by a udbg
implementation

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/hvsi.h |   68 +++++++++++++++++++++++++++++++++++++++
 drivers/tty/hvc/hvsi.c          |   63 +-----------------------------------
 2 files changed, 69 insertions(+), 62 deletions(-)
 create mode 100644 arch/powerpc/include/asm/hvsi.h

diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h
new file mode 100644
index 0000000..f13125a
--- /dev/null
+++ b/arch/powerpc/include/asm/hvsi.h
@@ -0,0 +1,68 @@
+#ifndef _HVSI_H
+#define _HVSI_H
+
+#define VS_DATA_PACKET_HEADER           0xff
+#define VS_CONTROL_PACKET_HEADER        0xfe
+#define VS_QUERY_PACKET_HEADER          0xfd
+#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
+
+/* control verbs */
+#define VSV_SET_MODEM_CTL    1 /* to service processor only */
+#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
+#define VSV_CLOSE_PROTOCOL   3
+
+/* query verbs */
+#define VSV_SEND_VERSION_NUMBER 1
+#define VSV_SEND_MODEM_CTL_STATUS 2
+
+/* yes, these masks are not consecutive. */
+#define HVSI_TSDTR 0x01
+#define HVSI_TSCD  0x20
+
+#define HVSI_MAX_OUTGOING_DATA 12
+#define HVSI_VERSION 1
+
+struct hvsi_header {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+} __attribute__((packed));
+
+struct hvsi_data {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
+} __attribute__((packed));
+
+struct hvsi_control {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint16_t verb;
+	/* optional depending on verb: */
+	uint32_t word;
+	uint32_t mask;
+} __attribute__((packed));
+
+struct hvsi_query {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint16_t verb;
+} __attribute__((packed));
+
+struct hvsi_query_response {
+	uint8_t  type;
+	uint8_t  len;
+	uint16_t seqno;
+	uint16_t verb;
+	uint16_t query_seqno;
+	union {
+		uint8_t  version;
+		uint32_t mctrl_word;
+	} u;
+} __attribute__((packed));
+
+
+#endif /* _HVSI_H */
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 8a8d637..0b35793 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -49,6 +49,7 @@
 #include <asm/uaccess.h>
 #include <asm/vio.h>
 #include <asm/param.h>
+#include <asm/hvsi.h>
 
 #define HVSI_MAJOR	229
 #define HVSI_MINOR	128
@@ -109,68 +110,6 @@ enum HVSI_PROTOCOL_STATE {
 };
 #define HVSI_CONSOLE 0x1
 
-#define VS_DATA_PACKET_HEADER           0xff
-#define VS_CONTROL_PACKET_HEADER        0xfe
-#define VS_QUERY_PACKET_HEADER          0xfd
-#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
-
-/* control verbs */
-#define VSV_SET_MODEM_CTL    1 /* to service processor only */
-#define VSV_MODEM_CTL_UPDATE 2 /* from service processor only */
-#define VSV_CLOSE_PROTOCOL   3
-
-/* query verbs */
-#define VSV_SEND_VERSION_NUMBER 1
-#define VSV_SEND_MODEM_CTL_STATUS 2
-
-/* yes, these masks are not consecutive. */
-#define HVSI_TSDTR 0x01
-#define HVSI_TSCD  0x20
-
-struct hvsi_header {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-} __attribute__((packed));
-
-struct hvsi_data {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint8_t  data[HVSI_MAX_OUTGOING_DATA];
-} __attribute__((packed));
-
-struct hvsi_control {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-	/* optional depending on verb: */
-	uint32_t word;
-	uint32_t mask;
-} __attribute__((packed));
-
-struct hvsi_query {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-} __attribute__((packed));
-
-struct hvsi_query_response {
-	uint8_t  type;
-	uint8_t  len;
-	uint16_t seqno;
-	uint16_t verb;
-	uint16_t query_seqno;
-	union {
-		uint8_t  version;
-		uint32_t mctrl_word;
-	} u;
-} __attribute__((packed));
-
-
-
 static inline int is_console(struct hvsi_struct *hp)
 {
 	return hp->flags & HVSI_CONSOLE;
-- 
1.7.1

^ permalink raw reply related

* Re: device not available because of BAR 0 collisions
From: Steven A. Falco @ 2011-04-28 21:19 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1304025271.2513.199.camel@pasglop>

On 04/28/2011 05:14 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-28 at 17:11 -0400, Steven A. Falco wrote:
> 
>> It is in __dev_sort_resources() in setup-bus.c
>>
>> There is this test:
>>
>> 	/* Don't touch classless devices or host bridges or ioapics.  */
>> 	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
>> 		return;
>>
>> where PCI_CLASS_NOT_DEFINED is 0x0000.  So basically Linux skips over allocating
>> anything with a class of 0.
> 
> Ah nice. Can you try the quirk ?

That is exactly the way I fixed it. :-)

I added the following in my board-specific file:

static void quirk_d7(struct pci_dev *pdev)
{
	// D7 has a bogus class code, which breaks BAR assignment.  Patch it.
	pdev->class = 0xff0000;
}
DECLARE_PCI_FIXUP_EARLY(0x1b03, 0x7000, quirk_d7);

(And thanks again for your assistance - I appreciate it.)

	Steve

> 
> Cheers,
> Ben.
> 
>> 	Steve
>>
>>>
>>>> My choices appear to be:
>>>>
>>>> 1) Fix the ASIC (yeah, right)
>>>>
>>>> 2) Force Linux to use the U-Boot settings
>>>>
>>>> 3) Hack Linux to set up a device with a bogus class.
>>>>
>>>> I'm not sure why this hardware works in x86 - I guess it is less
>>>> fussy.
>>>
>>> x86 probably just re-uses whatever setting the BIOS does, but I'm still
>>> a bit surprised by your class code story.
>>>
>>> I supose you can do a PCI header quirk that overrides the class code in
>>> struct pci_dev. Something like:
>>>
>>> static void __devinit quirk_your_asic_class(struct pci_dev *dev)
>>> {
>>> 	dev->class = foobar;
>>> }
>>> DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_xxx, PCI_DEVICE_ID_yyy, quirk_your_asic_class);
>>>
>>> But I'd like to figure out where that is tested bcs I haven't found so
>>> far...
>>>
>>>> 	Steve
>>>>
>>>>>>>>>
>>>>>>>>> I see in setup-res.c that this message comes out when there is no
>>>>>>>>> parent for
>>>>>>>>> a device resource.
>>>>>>>>
>>>>>>>>  .../...
>>>>>>>>
>>>>>>>> It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
>>>>>>>> setup-res.c
>>>>>>>>
>>>>>>>> Try #define DEBUG at the top (before the #includes) of pci-common.c and
>>>>>>>> pci_32.c (remove the exiting #undef in the last one) and send us the
>>>>>>>> full dmesg log, along with the output of cat /proc/iomem
>>>>>>
>>>>>> Have you set any specific flags ? IE. Modified the value of
>>>>>> ppc_pci_flags from what the 4xx code sets originally ?
>>>>>
>>>>> For fun, I just tried changing:
>>>>>
>>>>> ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
>>>>>
>>>>> to:
>>>>>
>>>>> ppc_pci_set_flags(PPC_PCI_PROBE_ONLY);
>>>>>
>>>>> I realize that is the exact opposite of what you were suggesting, but
>>>>> please bear with me for a bit.
>>>>>
>>>>> I also changed the PCIE 0 ranges from:
>>>>>
>>>>> ranges = <0x02000000 0x00000000 0x80000000 0x90000000 0x00000000 0x10000000
>>>>>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
>>>>>
>>>>> ranges = <0x02000000 0x00000000 0x90000000 0x90000000 0x00000000 0x10000000
>>>>>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
>>>>>
>>>>> I changed the ranges not because I wanted a 1:1 map, but because 90000000 is
>>>>> what U-Boot chooses when it scans PCIe 1.
>>>>>
>>>>> At this point, everything is working.  Here is /proc/iomap:
>>>>>
>>>>> 90000000-9fffffff : /plb/pciex@0c0000000
>>>>>   90000000-94ffffff : PCI Bus 0001:41
>>>>>     90000000-9001ffff : 0001:41:00.0
>>>>>     90100000-94ffffff : PCI Bus 0001:42
>>>>>       90100000-92ffffff : PCI Bus 0001:43
>>>>>         91000000-91ffffff : 0001:43:00.0  //<--- was missing before
>>>>>         92000000-92ffffff : 0001:43:00.0  //<--- was missing before
>>>>>       93000000-94ffffff : PCI Bus 0001:44
>>>>>         93000000-93ffffff : 0001:44:00.0  //<--- was missing before
>>>>>         94000000-94ffffff : 0001:44:00.0  //<--- was missing before
>>>>> e0000000-e7ffffff : /plb/pciex@0a0000000
>>>>>   e0000000-e7ffffff : PCI Bus 0000:01
>>>>>     e0000000-e00fffff : 0000:01:00.0
>>>>>     e0100000-e01fffff : 0000:01:00.0
>>>>>     e4000000-e7ffffff : 0000:01:00.0
>>>>> ef600200-ef600207 : serial
>>>>> ef600300-ef600307 : serial
>>>>> ef600600-ef600606 : spi_ppc4xx_of
>>>>> ef6c0000-ef6cffff : dwc_otg.0
>>>>>   ef6c0000-ef6cffff : dwc_otg
>>>>> fc000000-ffffffff : fc000000.nor_flash
>>>>>
>>>>> Now I see the bars for the ASICs (flagged above).  I could stop here,
>>>>> and declare success, but I don't really like this solution, because it
>>>>> requires me to be sure the dts has the same bus addresses that U-Boot
>>>>> will choose.  Seems risky.
>>>>>
>>>>> Tentative conclusion:  Either I still have something set wrong in my dts
>>>>> or there is a bug in the Linux PCI bus mapping code.
>>>>>
>>>>> 	Steve
>>>>>
>>>>>>
>>>>>> It does look to me like some of your device BARs have been setup already
>>>>>> by the firmware in a way that conflict with the way you configure your
>>>>>> ranges, and the kernel doesn't appear to detect nor try to remap that
>>>>>> which would happen if you have the "probe only" flag set.
>>>>>>
>>>>>> IE. On your c0000000 bus, you have memory at 90000000 CPU space mapped
>>>>>> to 80000000 PCI space. However, when probing, the kernel finds:
>>>>>>
>>>>>> pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
>>>>>>
>>>>>> IE. A BAR was already set with a value of 90000000 PCI-side which is out
>>>>>> of the bounds you have for your bus.
>>>>>>
>>>>>> Maybe you really want to configure that second bus to have CPU 90000000
>>>>>> mapped to 90000000 PCI-side ? (IE. a 1:1 mapping). That would be
>>>>>> something to fix in your "ranges" property.
>>>>>>
>>>>>> Cheers,
>>>>>> Ben.
>>>>>
>>>>>
>>>>
>>>>
>>>
>>>
>>>
>>
>>
> 
> 
> 


-- 
A: Because it makes the logic of the discussion difficult to follow.
Q: Why shouldn't I top post?
A: No.
Q: Should I top post?

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Benjamin Herrenschmidt @ 2011-04-28 21:14 UTC (permalink / raw)
  To: Steven A. Falco; +Cc: linuxppc-dev
In-Reply-To: <4DB9D7ED.5090208@harris.com>

On Thu, 2011-04-28 at 17:11 -0400, Steven A. Falco wrote:

> It is in __dev_sort_resources() in setup-bus.c
> 
> There is this test:
> 
> 	/* Don't touch classless devices or host bridges or ioapics.  */
> 	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
> 		return;
> 
> where PCI_CLASS_NOT_DEFINED is 0x0000.  So basically Linux skips over allocating
> anything with a class of 0.

Ah nice. Can you try the quirk ?

Cheers,
Ben.

> 	Steve
> 
> > 
> >> My choices appear to be:
> >>
> >> 1) Fix the ASIC (yeah, right)
> >>
> >> 2) Force Linux to use the U-Boot settings
> >>
> >> 3) Hack Linux to set up a device with a bogus class.
> >>
> >> I'm not sure why this hardware works in x86 - I guess it is less
> >> fussy.
> > 
> > x86 probably just re-uses whatever setting the BIOS does, but I'm still
> > a bit surprised by your class code story.
> > 
> > I supose you can do a PCI header quirk that overrides the class code in
> > struct pci_dev. Something like:
> > 
> > static void __devinit quirk_your_asic_class(struct pci_dev *dev)
> > {
> > 	dev->class = foobar;
> > }
> > DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_xxx, PCI_DEVICE_ID_yyy, quirk_your_asic_class);
> > 
> > But I'd like to figure out where that is tested bcs I haven't found so
> > far...
> > 
> >> 	Steve
> >>
> >>>>>>>
> >>>>>>> I see in setup-res.c that this message comes out when there is no
> >>>>>>> parent for
> >>>>>>> a device resource.
> >>>>>>
> >>>>>>  .../...
> >>>>>>
> >>>>>> It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
> >>>>>> setup-res.c
> >>>>>>
> >>>>>> Try #define DEBUG at the top (before the #includes) of pci-common.c and
> >>>>>> pci_32.c (remove the exiting #undef in the last one) and send us the
> >>>>>> full dmesg log, along with the output of cat /proc/iomem
> >>>>
> >>>> Have you set any specific flags ? IE. Modified the value of
> >>>> ppc_pci_flags from what the 4xx code sets originally ?
> >>>
> >>> For fun, I just tried changing:
> >>>
> >>> ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
> >>>
> >>> to:
> >>>
> >>> ppc_pci_set_flags(PPC_PCI_PROBE_ONLY);
> >>>
> >>> I realize that is the exact opposite of what you were suggesting, but
> >>> please bear with me for a bit.
> >>>
> >>> I also changed the PCIE 0 ranges from:
> >>>
> >>> ranges = <0x02000000 0x00000000 0x80000000 0x90000000 0x00000000 0x10000000
> >>>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
> >>>
> >>> ranges = <0x02000000 0x00000000 0x90000000 0x90000000 0x00000000 0x10000000
> >>>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
> >>>
> >>> I changed the ranges not because I wanted a 1:1 map, but because 90000000 is
> >>> what U-Boot chooses when it scans PCIe 1.
> >>>
> >>> At this point, everything is working.  Here is /proc/iomap:
> >>>
> >>> 90000000-9fffffff : /plb/pciex@0c0000000
> >>>   90000000-94ffffff : PCI Bus 0001:41
> >>>     90000000-9001ffff : 0001:41:00.0
> >>>     90100000-94ffffff : PCI Bus 0001:42
> >>>       90100000-92ffffff : PCI Bus 0001:43
> >>>         91000000-91ffffff : 0001:43:00.0  //<--- was missing before
> >>>         92000000-92ffffff : 0001:43:00.0  //<--- was missing before
> >>>       93000000-94ffffff : PCI Bus 0001:44
> >>>         93000000-93ffffff : 0001:44:00.0  //<--- was missing before
> >>>         94000000-94ffffff : 0001:44:00.0  //<--- was missing before
> >>> e0000000-e7ffffff : /plb/pciex@0a0000000
> >>>   e0000000-e7ffffff : PCI Bus 0000:01
> >>>     e0000000-e00fffff : 0000:01:00.0
> >>>     e0100000-e01fffff : 0000:01:00.0
> >>>     e4000000-e7ffffff : 0000:01:00.0
> >>> ef600200-ef600207 : serial
> >>> ef600300-ef600307 : serial
> >>> ef600600-ef600606 : spi_ppc4xx_of
> >>> ef6c0000-ef6cffff : dwc_otg.0
> >>>   ef6c0000-ef6cffff : dwc_otg
> >>> fc000000-ffffffff : fc000000.nor_flash
> >>>
> >>> Now I see the bars for the ASICs (flagged above).  I could stop here,
> >>> and declare success, but I don't really like this solution, because it
> >>> requires me to be sure the dts has the same bus addresses that U-Boot
> >>> will choose.  Seems risky.
> >>>
> >>> Tentative conclusion:  Either I still have something set wrong in my dts
> >>> or there is a bug in the Linux PCI bus mapping code.
> >>>
> >>> 	Steve
> >>>
> >>>>
> >>>> It does look to me like some of your device BARs have been setup already
> >>>> by the firmware in a way that conflict with the way you configure your
> >>>> ranges, and the kernel doesn't appear to detect nor try to remap that
> >>>> which would happen if you have the "probe only" flag set.
> >>>>
> >>>> IE. On your c0000000 bus, you have memory at 90000000 CPU space mapped
> >>>> to 80000000 PCI space. However, when probing, the kernel finds:
> >>>>
> >>>> pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
> >>>>
> >>>> IE. A BAR was already set with a value of 90000000 PCI-side which is out
> >>>> of the bounds you have for your bus.
> >>>>
> >>>> Maybe you really want to configure that second bus to have CPU 90000000
> >>>> mapped to 90000000 PCI-side ? (IE. a 1:1 mapping). That would be
> >>>> something to fix in your "ranges" property.
> >>>>
> >>>> Cheers,
> >>>> Ben.
> >>>
> >>>
> >>
> >>
> > 
> > 
> > 
> 
> 

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Steven A. Falco @ 2011-04-28 21:11 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1304024141.2513.196.camel@pasglop>

On 04/28/2011 04:55 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-28 at 13:29 -0400, Steven A. Falco wrote:
>> On 04/27/2011 03:51 PM, Steven A. Falco wrote:
>>> On 04/26/2011 07:39 PM, Benjamin Herrenschmidt wrote:
>>>> On Tue, 2011-04-26 at 09:38 -0400, Steven A. Falco wrote:
>>>>> On 04/25/2011 08:01 PM, Benjamin Herrenschmidt wrote:
>>>>>> On Mon, 2011-04-25 at 16:10 -0400, Steven A. Falco wrote:
>>>>>>> I'm getting an error message when trying to talk to some custom
>>>>>>> hardware:
>>>>>>>
>>>>>>> dx83xx 0001:43:00.0: device not available because of BAR 0
>>>>>>> [0xa1000000-0xa1ffffff] collisions
>>
>> I believe I've gotten to the root cause of this issue.  Turns out the
>> ASIC is reporting a class code of 0000, in violation of the PCI spec.
>>
>> As a result, Linux is refusing to set up the ASIC, and so it remains
>> with the settings made in U-Boot, which are in conflict with the
>> allocation Linux makes for the bridge the ASIC is connected to.
>>
>> So Ben, you are absolutely right that there was some left-over
>> configuration.
> 
> Hrm. that's odd still, do you know where in linux is the code that tests
> for the class code and decides to not setup the device resources ? I
> can't see that...

It is in __dev_sort_resources() in setup-bus.c

There is this test:

	/* Don't touch classless devices or host bridges or ioapics.  */
	if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
		return;

where PCI_CLASS_NOT_DEFINED is 0x0000.  So basically Linux skips over allocating
anything with a class of 0.

	Steve

> 
>> My choices appear to be:
>>
>> 1) Fix the ASIC (yeah, right)
>>
>> 2) Force Linux to use the U-Boot settings
>>
>> 3) Hack Linux to set up a device with a bogus class.
>>
>> I'm not sure why this hardware works in x86 - I guess it is less
>> fussy.
> 
> x86 probably just re-uses whatever setting the BIOS does, but I'm still
> a bit surprised by your class code story.
> 
> I supose you can do a PCI header quirk that overrides the class code in
> struct pci_dev. Something like:
> 
> static void __devinit quirk_your_asic_class(struct pci_dev *dev)
> {
> 	dev->class = foobar;
> }
> DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_xxx, PCI_DEVICE_ID_yyy, quirk_your_asic_class);
> 
> But I'd like to figure out where that is tested bcs I haven't found so
> far...
> 
>> 	Steve
>>
>>>>>>>
>>>>>>> I see in setup-res.c that this message comes out when there is no
>>>>>>> parent for
>>>>>>> a device resource.
>>>>>>
>>>>>>  .../...
>>>>>>
>>>>>> It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
>>>>>> setup-res.c
>>>>>>
>>>>>> Try #define DEBUG at the top (before the #includes) of pci-common.c and
>>>>>> pci_32.c (remove the exiting #undef in the last one) and send us the
>>>>>> full dmesg log, along with the output of cat /proc/iomem
>>>>
>>>> Have you set any specific flags ? IE. Modified the value of
>>>> ppc_pci_flags from what the 4xx code sets originally ?
>>>
>>> For fun, I just tried changing:
>>>
>>> ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
>>>
>>> to:
>>>
>>> ppc_pci_set_flags(PPC_PCI_PROBE_ONLY);
>>>
>>> I realize that is the exact opposite of what you were suggesting, but
>>> please bear with me for a bit.
>>>
>>> I also changed the PCIE 0 ranges from:
>>>
>>> ranges = <0x02000000 0x00000000 0x80000000 0x90000000 0x00000000 0x10000000
>>>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
>>>
>>> ranges = <0x02000000 0x00000000 0x90000000 0x90000000 0x00000000 0x10000000
>>>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
>>>
>>> I changed the ranges not because I wanted a 1:1 map, but because 90000000 is
>>> what U-Boot chooses when it scans PCIe 1.
>>>
>>> At this point, everything is working.  Here is /proc/iomap:
>>>
>>> 90000000-9fffffff : /plb/pciex@0c0000000
>>>   90000000-94ffffff : PCI Bus 0001:41
>>>     90000000-9001ffff : 0001:41:00.0
>>>     90100000-94ffffff : PCI Bus 0001:42
>>>       90100000-92ffffff : PCI Bus 0001:43
>>>         91000000-91ffffff : 0001:43:00.0  //<--- was missing before
>>>         92000000-92ffffff : 0001:43:00.0  //<--- was missing before
>>>       93000000-94ffffff : PCI Bus 0001:44
>>>         93000000-93ffffff : 0001:44:00.0  //<--- was missing before
>>>         94000000-94ffffff : 0001:44:00.0  //<--- was missing before
>>> e0000000-e7ffffff : /plb/pciex@0a0000000
>>>   e0000000-e7ffffff : PCI Bus 0000:01
>>>     e0000000-e00fffff : 0000:01:00.0
>>>     e0100000-e01fffff : 0000:01:00.0
>>>     e4000000-e7ffffff : 0000:01:00.0
>>> ef600200-ef600207 : serial
>>> ef600300-ef600307 : serial
>>> ef600600-ef600606 : spi_ppc4xx_of
>>> ef6c0000-ef6cffff : dwc_otg.0
>>>   ef6c0000-ef6cffff : dwc_otg
>>> fc000000-ffffffff : fc000000.nor_flash
>>>
>>> Now I see the bars for the ASICs (flagged above).  I could stop here,
>>> and declare success, but I don't really like this solution, because it
>>> requires me to be sure the dts has the same bus addresses that U-Boot
>>> will choose.  Seems risky.
>>>
>>> Tentative conclusion:  Either I still have something set wrong in my dts
>>> or there is a bug in the Linux PCI bus mapping code.
>>>
>>> 	Steve
>>>
>>>>
>>>> It does look to me like some of your device BARs have been setup already
>>>> by the firmware in a way that conflict with the way you configure your
>>>> ranges, and the kernel doesn't appear to detect nor try to remap that
>>>> which would happen if you have the "probe only" flag set.
>>>>
>>>> IE. On your c0000000 bus, you have memory at 90000000 CPU space mapped
>>>> to 80000000 PCI space. However, when probing, the kernel finds:
>>>>
>>>> pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
>>>>
>>>> IE. A BAR was already set with a value of 90000000 PCI-side which is out
>>>> of the bounds you have for your bus.
>>>>
>>>> Maybe you really want to configure that second bus to have CPU 90000000
>>>> mapped to 90000000 PCI-side ? (IE. a 1:1 mapping). That would be
>>>> something to fix in your "ranges" property.
>>>>
>>>> Cheers,
>>>> Ben.
>>>
>>>
>>
>>
> 
> 
> 


-- 
A: Because it makes the logic of the discussion difficult to follow.
Q: Why shouldn't I top post?
A: No.
Q: Should I top post?

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Benjamin Herrenschmidt @ 2011-04-28 20:55 UTC (permalink / raw)
  To: Steven A. Falco; +Cc: linuxppc-dev
In-Reply-To: <4DB9A3F1.9070300@harris.com>

On Thu, 2011-04-28 at 13:29 -0400, Steven A. Falco wrote:
> On 04/27/2011 03:51 PM, Steven A. Falco wrote:
> > On 04/26/2011 07:39 PM, Benjamin Herrenschmidt wrote:
> >> On Tue, 2011-04-26 at 09:38 -0400, Steven A. Falco wrote:
> >>> On 04/25/2011 08:01 PM, Benjamin Herrenschmidt wrote:
> >>>> On Mon, 2011-04-25 at 16:10 -0400, Steven A. Falco wrote:
> >>>>> I'm getting an error message when trying to talk to some custom
> >>>>> hardware:
> >>>>>
> >>>>> dx83xx 0001:43:00.0: device not available because of BAR 0
> >>>>> [0xa1000000-0xa1ffffff] collisions
> 
> I believe I've gotten to the root cause of this issue.  Turns out the
> ASIC is reporting a class code of 0000, in violation of the PCI spec.
> 
> As a result, Linux is refusing to set up the ASIC, and so it remains
> with the settings made in U-Boot, which are in conflict with the
> allocation Linux makes for the bridge the ASIC is connected to.
> 
> So Ben, you are absolutely right that there was some left-over
> configuration.

Hrm. that's odd still, do you know where in linux is the code that tests
for the class code and decides to not setup the device resources ? I
can't see that...

> My choices appear to be:
> 
> 1) Fix the ASIC (yeah, right)
> 
> 2) Force Linux to use the U-Boot settings
> 
> 3) Hack Linux to set up a device with a bogus class.
> 
> I'm not sure why this hardware works in x86 - I guess it is less
> fussy.

x86 probably just re-uses whatever setting the BIOS does, but I'm still
a bit surprised by your class code story.

I supose you can do a PCI header quirk that overrides the class code in
struct pci_dev. Something like:

static void __devinit quirk_your_asic_class(struct pci_dev *dev)
{
	dev->class = foobar;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_xxx, PCI_DEVICE_ID_yyy, quirk_your_asic_class);

But I'd like to figure out where that is tested bcs I haven't found so
far...

> 	Steve
> 
> >>>>>
> >>>>> I see in setup-res.c that this message comes out when there is no
> >>>>> parent for
> >>>>> a device resource.
> >>>>
> >>>>  .../...
> >>>>
> >>>> It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
> >>>> setup-res.c
> >>>>
> >>>> Try #define DEBUG at the top (before the #includes) of pci-common.c and
> >>>> pci_32.c (remove the exiting #undef in the last one) and send us the
> >>>> full dmesg log, along with the output of cat /proc/iomem
> >>
> >> Have you set any specific flags ? IE. Modified the value of
> >> ppc_pci_flags from what the 4xx code sets originally ?
> > 
> > For fun, I just tried changing:
> > 
> > ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
> > 
> > to:
> > 
> > ppc_pci_set_flags(PPC_PCI_PROBE_ONLY);
> > 
> > I realize that is the exact opposite of what you were suggesting, but
> > please bear with me for a bit.
> > 
> > I also changed the PCIE 0 ranges from:
> > 
> > ranges = <0x02000000 0x00000000 0x80000000 0x90000000 0x00000000 0x10000000
> >           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
> > 
> > ranges = <0x02000000 0x00000000 0x90000000 0x90000000 0x00000000 0x10000000
> >           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
> > 
> > I changed the ranges not because I wanted a 1:1 map, but because 90000000 is
> > what U-Boot chooses when it scans PCIe 1.
> > 
> > At this point, everything is working.  Here is /proc/iomap:
> > 
> > 90000000-9fffffff : /plb/pciex@0c0000000
> >   90000000-94ffffff : PCI Bus 0001:41
> >     90000000-9001ffff : 0001:41:00.0
> >     90100000-94ffffff : PCI Bus 0001:42
> >       90100000-92ffffff : PCI Bus 0001:43
> >         91000000-91ffffff : 0001:43:00.0  //<--- was missing before
> >         92000000-92ffffff : 0001:43:00.0  //<--- was missing before
> >       93000000-94ffffff : PCI Bus 0001:44
> >         93000000-93ffffff : 0001:44:00.0  //<--- was missing before
> >         94000000-94ffffff : 0001:44:00.0  //<--- was missing before
> > e0000000-e7ffffff : /plb/pciex@0a0000000
> >   e0000000-e7ffffff : PCI Bus 0000:01
> >     e0000000-e00fffff : 0000:01:00.0
> >     e0100000-e01fffff : 0000:01:00.0
> >     e4000000-e7ffffff : 0000:01:00.0
> > ef600200-ef600207 : serial
> > ef600300-ef600307 : serial
> > ef600600-ef600606 : spi_ppc4xx_of
> > ef6c0000-ef6cffff : dwc_otg.0
> >   ef6c0000-ef6cffff : dwc_otg
> > fc000000-ffffffff : fc000000.nor_flash
> > 
> > Now I see the bars for the ASICs (flagged above).  I could stop here,
> > and declare success, but I don't really like this solution, because it
> > requires me to be sure the dts has the same bus addresses that U-Boot
> > will choose.  Seems risky.
> > 
> > Tentative conclusion:  Either I still have something set wrong in my dts
> > or there is a bug in the Linux PCI bus mapping code.
> > 
> > 	Steve
> > 
> >>
> >> It does look to me like some of your device BARs have been setup already
> >> by the firmware in a way that conflict with the way you configure your
> >> ranges, and the kernel doesn't appear to detect nor try to remap that
> >> which would happen if you have the "probe only" flag set.
> >>
> >> IE. On your c0000000 bus, you have memory at 90000000 CPU space mapped
> >> to 80000000 PCI space. However, when probing, the kernel finds:
> >>
> >> pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
> >>
> >> IE. A BAR was already set with a value of 90000000 PCI-side which is out
> >> of the bounds you have for your bus.
> >>
> >> Maybe you really want to configure that second bus to have CPU 90000000
> >> mapped to 90000000 PCI-side ? (IE. a 1:1 mapping). That would be
> >> something to fix in your "ranges" property.
> >>
> >> Cheers,
> >> Ben.
> > 
> > 
> 
> 

^ permalink raw reply

* Re: linux-next: ibmveth runtime errors
From: David Miller @ 2011-04-28 20:46 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linuxppc-dev, linux-kernel, linux-next, mirq-linux,
	santil
In-Reply-To: <20110428121124.39c036ff.sfr@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Thu, 28 Apr 2011 12:11:24 +1000

> From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= <mirq-linux@rere.qmqm.pl>
> Date: Thu, 28 Apr 2011 11:59:15 +1000
> Subject: [PATCH] net: ibmveth: force reconfiguring checksum settings on
>  startup
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> Commit b9367bf3ee6d ("net: ibmveth: convert to hw_features") accidentally
> removed call to ibmveth_set_csum_offload() in ibmveth_probe(). Put the
> call back where it was, but with additional error checking provided
> by ibmveth_set_features().
> 
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
> [sfr: dev -> netdev]
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>

Applied, thanks everyone.

^ permalink raw reply

* [PATCH 6/6] powerpc: use irq_alloc_desc() to manage irq allocations
From: Grant Likely @ 2011-04-28 20:02 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev
In-Reply-To: <20110428192227.8979.49181.stgit@ponder>

This patch drops the architecture specific code for managing irq
assignments and uses core code instead.

*RFC*

This patch is *not* ready for merging.  The locking is messed up where
the irq_map is still used to find out if a mapping is already established,
but irq_alloc_desc() is now called before the irq_map is updated which
creates a race condition.  I've not completely sorted out how to solve
this yet.  The solution may very well be to convert the irq_big_lock
to a mutex (but I'm not sure if anything that sleeps calls the affected
code), and hold the mutex over the entire operation.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/kernel/irq.c |   51 ++++++++++++---------------------------------
 1 files changed, 14 insertions(+), 37 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 0fb90ab..e4a6646 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -984,53 +984,29 @@ unsigned int irq_linear_revmap(struct irq_host *host,
 static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
 {
 	unsigned long flags;
-	unsigned int i, j, found = NO_IRQ;
-	int res;
+	int found;
 
-	raw_spin_lock_irqsave(&irq_big_lock, flags);
-
-	/* Use hint for 1 interrupt if any */
-	if (hint >= NUM_ISA_INTERRUPTS &&
-	    hint < irq_virq_count && irq_map[hint].host == NULL) {
-		found = hint;
-		goto hint_found;
-	}
-
-	/* Look for a free virq in the allocatable (non-legacy) space */
-	for (i = NUM_ISA_INTERRUPTS, j = 0; i < irq_virq_count; i++) {
-		if (irq_map[i].host == NULL) {
-			found = i;
-			break;
-		}
-	}
-	if (found == NO_IRQ) {
-		raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+	/*
+	 * Find an unused interrupt.  First, attempt to allocate
+	 * 'hint'.  If that fails, then just allocate any free one.
+	 */
+	found = irq_alloc_desc_at(hint, 0);
+	if (found <= NO_IRQ)
+		found = irq_alloc_desc(0);
+	if (found <= NO_IRQ) {
+		pr_debug("irq: -> allocating desc failed\n");
 		return NO_IRQ;
 	}
- hint_found:
+
+	raw_spin_lock_irqsave(&irq_big_lock, flags);
 	irq_map[found].hwirq = host->inval_irq;
 	smp_wmb();
 	irq_map[found].host = host;
 	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
 
-	res = irq_alloc_desc_at(found, 0);
-	if (res != found) {
-		pr_debug("irq: -> allocating desc failed\n");
-		goto error_desc;
-	}
-
 	irq_clear_status_flags(found, IRQ_NOREQUEST);
 
 	return found;
-
- error_desc:
-	raw_spin_lock_irqsave(&irq_big_lock, flags);
-	host = irq_map[found].host;
-	irq_map[found].hwirq = host->inval_irq;
-	smp_wmb();
-	irq_map[found].host = NULL;
-	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
-	return NO_IRQ;
 }
 
 /**
@@ -1051,13 +1027,14 @@ static void irq_free_virt(unsigned int virq)
 		return;
 	}
 
-	irq_free_descs(virq, 1);
 	raw_spin_lock_irqsave(&irq_big_lock, flags);
 	host = irq_map[virq].host;
 	irq_map[virq].hwirq = host->inval_irq;
 	smp_wmb();
 	irq_map[virq].host = NULL;
 	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+
+	irq_free_descs(virq, 1);
 }
 
 int arch_early_irq_init(void)

^ permalink raw reply related

* [PATCH 5/6] powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
From: Grant Likely @ 2011-04-28 20:02 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev
In-Reply-To: <20110428192227.8979.49181.stgit@ponder>

This is a stepping stone to using core code for allocating virqs
instead of the powerpc architecture specific code.  A subsequent patch
will drop the algorithm that searches for a free irq and replaces it
with irq_alloc_desc()

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/kernel/irq.c |   49 ++++++++++++++++++++++++++-------------------
 1 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 9300e1c..0fb90ab 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -665,16 +665,6 @@ static void irq_free_virt(unsigned int virq);
 static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 			    irq_hw_number_t hwirq)
 {
-	int res;
-
-	res = irq_alloc_desc_at(virq, 0);
-	if (res != virq) {
-		pr_debug("irq: -> allocating desc failed\n");
-		goto error;
-	}
-
-	irq_clear_status_flags(virq, IRQ_NOREQUEST);
-
 	/* map it */
 	smp_wmb();
 	irq_map[virq].hwirq = hwirq;
@@ -688,8 +678,6 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 	return 0;
 
 errdesc:
-	irq_free_descs(virq, 1);
-error:
 	irq_free_virt(virq);
 	return -1;
 }
@@ -754,14 +742,14 @@ unsigned int irq_create_mapping(struct irq_host *host,
 		if (virq == 0 || virq >= NUM_ISA_INTERRUPTS)
 			return NO_IRQ;
 		return virq;
-	} else {
-		/* Allocate a virtual interrupt number */
-		hint = hwirq % irq_virq_count;
-		virq = irq_alloc_virt(host, hint);
-		if (virq == NO_IRQ) {
-			pr_debug("irq: -> virq allocation failed\n");
-			return NO_IRQ;
-		}
+	}
+
+	/* Allocate a virtual interrupt number */
+	hint = hwirq % irq_virq_count;
+	virq = irq_alloc_virt(host, hint);
+	if (virq == NO_IRQ) {
+		pr_debug("irq: -> virq allocation failed\n");
+		return NO_IRQ;
 	}
 
 	if (irq_setup_virq(host, virq, hwirq))
@@ -867,7 +855,6 @@ void irq_dispose_mapping(unsigned int virq)
 
 	irq_set_status_flags(virq, IRQ_NOREQUEST);
 
-	irq_free_descs(virq, 1);
 	/* Free it */
 	irq_free_virt(virq);
 }
@@ -998,6 +985,7 @@ static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
 {
 	unsigned long flags;
 	unsigned int i, j, found = NO_IRQ;
+	int res;
 
 	raw_spin_lock_irqsave(&irq_big_lock, flags);
 
@@ -1024,7 +1012,25 @@ static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
 	smp_wmb();
 	irq_map[found].host = host;
 	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+
+	res = irq_alloc_desc_at(found, 0);
+	if (res != found) {
+		pr_debug("irq: -> allocating desc failed\n");
+		goto error_desc;
+	}
+
+	irq_clear_status_flags(found, IRQ_NOREQUEST);
+
 	return found;
+
+ error_desc:
+	raw_spin_lock_irqsave(&irq_big_lock, flags);
+	host = irq_map[found].host;
+	irq_map[found].hwirq = host->inval_irq;
+	smp_wmb();
+	irq_map[found].host = NULL;
+	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
+	return NO_IRQ;
 }
 
 /**
@@ -1045,6 +1051,7 @@ static void irq_free_virt(unsigned int virq)
 		return;
 	}
 
+	irq_free_descs(virq, 1);
 	raw_spin_lock_irqsave(&irq_big_lock, flags);
 	host = irq_map[virq].host;
 	irq_map[virq].hwirq = host->inval_irq;

^ permalink raw reply related

* [PATCH 4/6] dt: generalize irq_of_create_mapping()
From: Grant Likely @ 2011-04-28 20:02 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev
In-Reply-To: <20110428192227.8979.49181.stgit@ponder>

This patch creates a common implementation of irq_of_create_mapping()
and factors out the interrupt domain translation code from powerpc to
make it available for all architectures.

It creates a new structure, struct of_irq_domain, which can be
embedded into the private data structure of an interrupt controller.
Any interrupt controller can call of_irq_domain_add() to register a
structure with a .map() hook that can translate irq specifiers from
the device tree into linux irq numbers.

The patch also modifies the powerpc irq_host to embed the
of_irq_domain structure and use the new common infrastructure for
registering domains.  This separates the reverse mapping and irq
allocation infrastructure of irq_host from the domain registration
infrastructure.  I elected to split the functionality this way for
several reasons.  First, with the major irq cleanup done by Thomas
Gleixner, dynamic allocation of irqs can be handled gracefully with
irq_alloc_desc*() and interrupt controllers may not need or want an
irq_host layer to manage it for them.  For example, the new
irq_chip_generic() already has a method for mapping between hwirq and
Linux irq.

Second, the irq_host code currently has a lot of complexity to handle
all the different reverse mapping types from a single structure.  The
radix mapping in particular has a lot of support code, but only one
user.  I didn't want to bring that complexity into the common code
as-is.  Instead, I'd prefer to create a separate encapsulating
structure for each revmap, and each type would have a separate .map
hook.

For now, the mapping code remains powerpc-specific and further
generalization will happen in subsequent patches.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/microblaze/kernel/irq.c             |    7 --
 arch/mips/kernel/prom.c                  |   14 ----
 arch/powerpc/include/asm/irq.h           |   21 +++--
 arch/powerpc/include/asm/irqhost.h       |    4 -
 arch/powerpc/kernel/irq.c                |   99 ++++++++++++++-----------
 arch/powerpc/platforms/cell/axon_msi.c   |   12 ++-
 arch/powerpc/platforms/cell/spider-pic.c |    8 +-
 arch/powerpc/sysdev/fsl_msi.c            |    2 -
 arch/powerpc/sysdev/i8259.c              |    2 -
 arch/powerpc/sysdev/ipic.c               |    2 -
 arch/powerpc/sysdev/mpic.c               |    4 +
 arch/powerpc/sysdev/mpic_msi.c           |    2 -
 arch/powerpc/sysdev/mpic_pasemi_msi.c    |    4 +
 arch/powerpc/sysdev/qe_lib/qe_ic.c       |    2 -
 arch/x86/include/asm/irq_controller.h    |   12 ---
 arch/x86/include/asm/prom.h              |    1 
 arch/x86/kernel/devicetree.c             |   77 ++++----------------
 drivers/of/irq.c                         |  118 ++++++++++++++++++++++++++++++
 include/linux/of_irq.h                   |   31 ++++++++
 19 files changed, 248 insertions(+), 174 deletions(-)
 delete mode 100644 arch/x86/include/asm/irq_controller.h

diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index ce7ac84..59bb560 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -54,10 +54,3 @@ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
 	return hwirq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
-
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index a19811e9..0b82f98 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -60,20 +60,6 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
 }
 #endif
 
-/*
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
 void __init early_init_devtree(void *params)
 {
 	/* Setup flat device-tree pointer */
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index a44be93..ccefc8c 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -55,11 +55,18 @@ typedef unsigned long irq_hw_number_t;
  * model). It's the host callbacks that are responsible for setting the
  * irq_chip on a given irq_desc after it's been mapped.
  *
+ * irq_host builds upon the of_irq_domain code in drivers/of/irq.c.
+ * of_irq_domain provides all of the translation hooks for registering irq
+ * controllers. irq_host add mapping infrastructure to and from hardware
+ * irq numbers. IRQ controllers that don't need the mapping infrastructure
+ * can use irq_domain directly.
+ *
  * The host code and data structures are fairly agnostic to the fact that
  * we use an open firmware device-tree. We do have references to struct
- * device_node in two places: in irq_find_host() to find the host matching
- * a given interrupt controller node, and of course as an argument to its
- * counterpart host->ops->match() callback. However, those are treated as
+ * device_node in two places: in of_irq_domain_find() to find the host matching
+ * a given interrupt controller node (which is actually common of_irq_domain
+ * code), and of course as an argument to its counterpart host->ops->match()
+ * and host->domain->match() callbacks. However, those are treated as
  * generic pointers by the core and the fact that it's actually a device-node
  * pointer is purely a convention between callers and implementation. This
  * code could thus be used on other architectures by replacing those two
@@ -137,14 +144,6 @@ extern struct irq_host *irq_alloc_host(struct device_node *of_node,
 				       struct irq_host_ops *ops,
 				       irq_hw_number_t inval_irq);
 
-
-/**
- * irq_find_host - Locates a host for a given device node
- * @node: device-tree node of the interrupt controller
- */
-extern struct irq_host *irq_find_host(struct device_node *node);
-
-
 /**
  * irq_set_default_host - Set a "default" host
  * @host: default host pointer
diff --git a/arch/powerpc/include/asm/irqhost.h b/arch/powerpc/include/asm/irqhost.h
index 958e6c1..a97a513 100644
--- a/arch/powerpc/include/asm/irqhost.h
+++ b/arch/powerpc/include/asm/irqhost.h
@@ -8,6 +8,7 @@
 
 struct irq_host {
 	struct list_head	link;
+	struct of_irq_domain	domain;
 
 	/* type of reverse mapping technique */
 	unsigned int		revmap_type;
@@ -21,9 +22,6 @@ struct irq_host {
 	struct irq_host_ops	*ops;
 	void			*host_data;
 	irq_hw_number_t		inval_irq;
-
-	/* Optional device node pointer */
-	struct device_node	*of_node;
 };
 
 #endif /* _ASM_POWERPC_IRQHOST_H */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index b961b19..9300e1c 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -514,11 +514,40 @@ struct irq_host *virq_to_host(unsigned int virq)
 }
 EXPORT_SYMBOL_GPL(virq_to_host);
 
-static int default_irq_host_match(struct irq_host *h, struct device_node *np)
+/**
+ * irq_host_domain_match() - irq_domain hook to call irq_host match ops.
+ *
+ * This functions gets set as the irq domain match function for irq_host
+ * instances *if* the ->ops->match() hook is populated.  If ->match() is
+ * not populated, then the default irq_domain matching behaviour is used
+ * instead.
+ */
+static bool irq_host_domain_match(struct of_irq_domain *domain,
+				  struct device_node *controller)
 {
-	return h->of_node != NULL && h->of_node == np;
+	struct irq_host *host = container_of(domain, struct irq_host, domain);
+	return host->ops->match(host, controller);
 }
 
+static unsigned int irq_host_domain_map(struct of_irq_domain *domain,
+					struct device_node *controller,
+					const u32 *intspec,
+					unsigned int intsize);
+
+/**
+ * irq_alloc_host() - Allocate and register an irq_host
+ * @of_node: Device node of the irq controller; this is used mainly as an
+ *           anonymouns context pointer.
+ * @revmap_type: One of IRQ_HOST_MAP_* defined in arch/powerpc/include/asm/irq.h
+ *               Defines the type of reverse map to be used by the irq_host.
+ * @revmap_arg: Currently only used by the IRQ_HOST_MAP_LINEAR which uses it
+ *              to define the size of the reverse map.
+ * @ops: irq_host ops structure for match/map/unmap/remap/xlate operations.
+ * @inval_irq: Value used by irq controller to indicate an invalid irq.
+ *
+ * irq_host implements mapping between hardware irq numbers and the linux
+ * virq number space.  This function allocates and registers an irq_host.
+ */
 struct irq_host *irq_alloc_host(struct device_node *of_node,
 				unsigned int revmap_type,
 				unsigned int revmap_arg,
@@ -542,10 +571,10 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
 	host->revmap_type = revmap_type;
 	host->inval_irq = inval_irq;
 	host->ops = ops;
-	host->of_node = of_node_get(of_node);
-
-	if (host->ops->match == NULL)
-		host->ops->match = default_irq_host_match;
+	host->domain.controller = of_node_get(of_node);
+	host->domain.map = irq_host_domain_map;
+	if (host->ops->match != NULL)
+		host->domain.match = irq_host_domain_match;
 
 	raw_spin_lock_irqsave(&irq_big_lock, flags);
 
@@ -561,7 +590,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
 			 * instead of the current cruft
 			 */
 			if (mem_init_done) {
-				of_node_put(host->of_node);
+				of_node_put(host->domain.controller);
 				kfree(host);
 			}
 			return NULL;
@@ -572,6 +601,8 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
 	list_add(&host->link, &irq_hosts);
 	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
 
+	of_irq_domain_add(&host->domain);
+
 	/* Additional setups per revmap type */
 	switch(revmap_type) {
 	case IRQ_HOST_MAP_LEGACY:
@@ -611,32 +642,12 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
 	return host;
 }
 
-struct irq_host *irq_find_host(struct device_node *node)
-{
-	struct irq_host *h, *found = NULL;
-	unsigned long flags;
-
-	/* We might want to match the legacy controller last since
-	 * it might potentially be set to match all interrupts in
-	 * the absence of a device node. This isn't a problem so far
-	 * yet though...
-	 */
-	raw_spin_lock_irqsave(&irq_big_lock, flags);
-	list_for_each_entry(h, &irq_hosts, link)
-		if (h->ops->match(h, node)) {
-			found = h;
-			break;
-		}
-	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
-	return found;
-}
-EXPORT_SYMBOL_GPL(irq_find_host);
-
 void irq_set_default_host(struct irq_host *host)
 {
 	pr_debug("irq: Default host set to @0x%p\n", host);
 
 	irq_default_host = host;
+	of_irq_set_default_domain(&host->domain);
 }
 
 void irq_set_virq_count(unsigned int count)
@@ -757,30 +768,29 @@ unsigned int irq_create_mapping(struct irq_host *host,
 		return NO_IRQ;
 
 	printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n",
-		hwirq, host->of_node ? host->of_node->full_name : "null", virq);
+		hwirq, host->domain.controller ? host->domain.controller->full_name : "null", virq);
 
 	return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
 
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
+/**
+ * irq_host_domain_map() - Map device tree irq to linux irq number
+ * This hook implements all of the powerpc 'irq_host' behaviour, which means
+ * - calling the ->ops->xlate hook to get the hardware irq number,
+ * - calling of_create_mapping to translate/allocate a linux virq number
+ * - calling irq_set_irq_type() if necessary
+ */
+static unsigned int irq_host_domain_map(struct of_irq_domain *domain,
+					struct device_node *controller,
+					const u32 *intspec,
+					unsigned int intsize)
 {
-	struct irq_host *host;
+	struct irq_host *host = container_of(domain, struct irq_host, domain);
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	unsigned int virq;
 
-	if (controller == NULL)
-		host = irq_default_host;
-	else
-		host = irq_find_host(controller);
-	if (host == NULL) {
-		printk(KERN_WARNING "irq: no irq host found for %s !\n",
-		       controller->full_name);
-		return NO_IRQ;
-	}
-
 	/* If host has no translation, then we assume interrupt line */
 	if (host->ops->xlate == NULL)
 		hwirq = intspec[0];
@@ -801,7 +811,6 @@ unsigned int irq_create_of_mapping(struct device_node *controller,
 		irq_set_irq_type(virq, type);
 	return virq;
 }
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
 
 void irq_dispose_mapping(unsigned int virq)
 {
@@ -1128,8 +1137,8 @@ static int virq_debug_show(struct seq_file *m, void *private)
 				p = none;
 			seq_printf(m, "%-15s  ", p);
 
-			if (irq_map[i].host && irq_map[i].host->of_node)
-				p = irq_map[i].host->of_node->full_name;
+			if (irq_map[i].host && irq_map[i].host->domain.controller)
+				p = irq_map[i].host->domain.controller->full_name;
 			else
 				p = none;
 			seq_printf(m, "%s\n", p);
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index e1469ae..f125673 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -152,7 +152,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 
 static struct axon_msic *find_msi_translator(struct pci_dev *dev)
 {
-	struct irq_host *irq_host;
+	struct of_irq_domain *irq_domain;
 	struct device_node *dn, *tmp;
 	const phandle *ph;
 	struct axon_msic *msic = NULL;
@@ -184,14 +184,14 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
 		goto out_error;
 	}
 
-	irq_host = irq_find_host(dn);
-	if (!irq_host) {
+	irq_domain = of_irq_domain_find(dn);
+	if (!irq_domain) {
 		dev_dbg(&dev->dev, "axon_msi: no irq_host found for node %s\n",
 			dn->full_name);
 		goto out_error;
 	}
 
-	msic = irq_host->host_data;
+	msic = irq_domain->priv;
 
 out_error:
 	of_node_put(dn);
@@ -336,7 +336,7 @@ static void axon_msi_shutdown(struct platform_device *device)
 	u32 tmp;
 
 	pr_devel("axon_msi: disabling %s\n",
-		  msic->irq_host->of_node->full_name);
+		  msic->irq_host->domain.controller->full_name);
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
@@ -399,7 +399,7 @@ static int axon_msi_probe(struct platform_device *device)
 		goto out_free_fifo;
 	}
 
-	msic->irq_host->host_data = msic;
+	msic->irq_host->domain.priv = msic;
 
 	irq_set_handler_data(virq, msic);
 	irq_set_chained_handler(virq, axon_msi_cascade);
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 73a5494..5bf36ab 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -236,18 +236,20 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
 	 * tree in case the device-tree is ever fixed
 	 */
 	struct of_irq oirq;
-	if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) {
+	if (of_irq_map_one(pic->host->domain.controller, 0, &oirq) == 0) {
 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 					     oirq.size);
 		return virq;
 	}
 
 	/* Now do the horrible hacks */
-	tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
+	tmp = of_get_property(pic->host->domain.controller,
+				"#interrupt-cells", NULL);
 	if (tmp == NULL)
 		return NO_IRQ;
 	intsize = *tmp;
-	imap = of_get_property(pic->host->of_node, "interrupt-map", &imaplen);
+	imap = of_get_property(pic->host->domain.controller,
+				"interrupt-map", &imaplen);
 	if (imap == NULL || imaplen < (intsize + 1))
 		return NO_IRQ;
 	iic = of_find_node_by_phandle(imap[intsize]);
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 2c11b3e..b45a25a 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -82,7 +82,7 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
 	int rc;
 
 	rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
-			      msi_data->irqhost->of_node);
+			      msi_data->irqhost->domain.controller);
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 30869f0..a6f78fb 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -166,7 +166,7 @@ static struct resource pic_edgectrl_iores = {
 
 static int i8259_host_match(struct irq_host *h, struct device_node *node)
 {
-	return h->of_node == NULL || h->of_node == node;
+	return h->domain.controller == NULL || h->domain.controller == node;
 }
 
 static int i8259_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index fc3751f..5805c7b 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -676,7 +676,7 @@ static struct irq_chip ipic_edge_irq_chip = {
 static int ipic_host_match(struct irq_host *h, struct device_node *node)
 {
 	/* Exact match, unless ipic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	return h->domain.controller == NULL || h->domain.controller == node;
 }
 
 static int ipic_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6e9e594..cafc364 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -956,7 +956,7 @@ static struct irq_chip mpic_irq_ht_chip = {
 static int mpic_host_match(struct irq_host *h, struct device_node *node)
 {
 	/* Exact match, unless mpic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	return h->domain.controller == NULL || h->domain.controller == node;
 }
 
 static int mpic_host_map(struct irq_host *h, unsigned int virq,
@@ -1296,7 +1296,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
 
 	BUG_ON(isu_num >= MPIC_MAX_ISU);
 
-	mpic_map(mpic, mpic->irqhost->of_node,
+	mpic_map(mpic, mpic->irqhost->domain.controller,
 		 paddr, &mpic->isus[isu_num], 0,
 		 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
 
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 50176ed..ddf79c7 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -85,7 +85,7 @@ int mpic_msi_init_allocator(struct mpic *mpic)
 	int rc;
 
 	rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count,
-			      mpic->irqhost->of_node);
+			      mpic->irqhost->domain.controller);
 	if (rc)
 		return rc;
 
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 6b11a89..857be51 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -153,8 +153,8 @@ int mpic_pasemi_msi_init(struct mpic *mpic)
 {
 	int rc;
 
-	if (!mpic->irqhost->of_node ||
-	    !of_device_is_compatible(mpic->irqhost->of_node,
+	if (!mpic->irqhost->domain.controller ||
+	    !of_device_is_compatible(mpic->irqhost->domain.controller,
 				     "pasemi,pwrficient-openpic"))
 		return -ENODEV;
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 9dd7746..c2ccafa 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -250,7 +250,7 @@ static struct irq_chip qe_ic_irq_chip = {
 static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
 {
 	/* Exact match, unless qe_ic node is NULL */
-	return h->of_node == NULL || h->of_node == node;
+	return h->domain.controller == NULL || h->domain.controller == node;
 }
 
 static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h
deleted file mode 100644
index 423bbbd..0000000
--- a/arch/x86/include/asm/irq_controller.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __IRQ_CONTROLLER__
-#define __IRQ_CONTROLLER__
-
-struct irq_domain {
-	int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize,
-			u32 *out_hwirq, u32 *out_type);
-	void *priv;
-	struct device_node *controller;
-	struct list_head l;
-};
-
-#endif
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index 971e0b4..eb9d5ab 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -21,7 +21,6 @@
 #include <asm/irq.h>
 #include <asm/atomic.h>
 #include <asm/setup.h>
-#include <asm/irq_controller.h>
 
 #ifdef CONFIG_OF
 extern int of_ioapic;
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 706a9fb..651e724 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -15,64 +15,14 @@
 #include <linux/of_pci.h>
 
 #include <asm/hpet.h>
-#include <asm/irq_controller.h>
 #include <asm/apic.h>
 #include <asm/pci_x86.h>
 
 __initdata u64 initial_dtb;
 char __initdata cmd_line[COMMAND_LINE_SIZE];
-static LIST_HEAD(irq_domains);
-static DEFINE_RAW_SPINLOCK(big_irq_lock);
 
 int __initdata of_ioapic;
 
-#ifdef CONFIG_X86_IO_APIC
-static void add_interrupt_host(struct irq_domain *ih)
-{
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&big_irq_lock, flags);
-	list_add(&ih->l, &irq_domains);
-	raw_spin_unlock_irqrestore(&big_irq_lock, flags);
-}
-#endif
-
-static struct irq_domain *get_ih_from_node(struct device_node *controller)
-{
-	struct irq_domain *ih, *found = NULL;
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&big_irq_lock, flags);
-	list_for_each_entry(ih, &irq_domains, l) {
-		if (ih->controller ==  controller) {
-			found = ih;
-			break;
-		}
-	}
-	raw_spin_unlock_irqrestore(&big_irq_lock, flags);
-	return found;
-}
-
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
-{
-	struct irq_domain *ih;
-	u32 virq, type;
-	int ret;
-
-	ih = get_ih_from_node(controller);
-	if (!ih)
-		return 0;
-	ret = ih->xlate(ih, intspec, intsize, &virq, &type);
-	if (ret)
-		return 0;
-	if (type == IRQ_TYPE_NONE)
-		return virq;
-	irq_set_irq_type(virq, type);
-	return virq;
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
 	/*
@@ -366,32 +316,33 @@ static struct of_ioapic_type of_ioapic_type[] =
 	},
 };
 
-static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
-			u32 *out_hwirq, u32 *out_type)
+static unsigned int ioapic_of_irq_map(struct of_irq_domain *id,
+				      struct device_node *np,
+				      const u32 *intspec, u32 intsize)
 {
 	struct io_apic_irq_attr attr;
 	struct of_ioapic_type *it;
-	u32 line, idx, type;
+	u32 line, idx, type, hwirq;
 
 	if (intsize < 2)
-		return -EINVAL;
+		return 0;
 
 	line = *intspec;
 	idx = (u32) id->priv;
-	*out_hwirq = line + mp_gsi_routing[idx].gsi_base;
+	hwirq = line + mp_gsi_routing[idx].gsi_base;
 
 	intspec++;
 	type = *intspec;
 
 	if (type >= ARRAY_SIZE(of_ioapic_type))
-		return -EINVAL;
+		return 0;
 
 	it = of_ioapic_type + type;
-	*out_type = it->out_type;
-
 	set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
 
-	return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
+	if (io_apic_setup_irq_pin(hwirq, cpu_to_node(0), &attr))
+		return 0;
+	return hwirq;
 }
 
 static void __init ioapic_add_ofnode(struct device_node *np)
@@ -408,14 +359,14 @@ static void __init ioapic_add_ofnode(struct device_node *np)
 
 	for (i = 0; i < nr_ioapics; i++) {
 		if (r.start == mp_ioapics[i].apicaddr) {
-			struct irq_domain *id;
+			struct of_irq_domain *id;
 
 			id = kzalloc(sizeof(*id), GFP_KERNEL);
 			BUG_ON(!id);
-			id->controller = np;
-			id->xlate = ioapic_xlate;
+			id->controller = of_node_get(np);
+			id->map = ioapic_of_irq_map;
 			id->priv = (void *)i;
-			add_interrupt_host(id);
+			of_irq_domain_add(id);
 			return;
 		}
 	}
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 75b0d3c..6da0964 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -29,6 +30,123 @@
 #define NO_IRQ 0
 #endif
 
+/*
+ * Device Tree IRQ domains
+ *
+ * IRQ domains provide translation from device tree irq controller nodes to
+ * linux IRQ numbers.  IRQ controllers register an irq_domain with a .map()
+ * hook that performs everything needed to decode and configure a device
+ * tree specified interrupt.
+ */
+static LIST_HEAD(of_irq_domains);
+static DEFINE_RAW_SPINLOCK(of_irq_lock);
+static struct of_irq_domain *of_irq_default_domain;
+
+/**
+ * of_irq_domain_default_match() - Return true if the controller pointers match
+ *
+ * Default match behaviour for of_irq_domains.  If the device tree node pointer
+ * matches the value stored in the domain structure, then return true.
+ */
+static bool of_irq_domain_default_match(struct of_irq_domain *domain,
+					struct device_node *controller)
+{
+	return domain->controller == controller;
+}
+
+/**
+ * of_irq_domain_add() - Register a device tree irq domain
+ * @domain: pointer to domain structure to be registered.
+ *
+ * Adds an of_irq_domain to the global list of domains.
+ */
+void of_irq_domain_add(struct of_irq_domain *domain)
+{
+	unsigned long flags;
+
+	if (!domain->match)
+		domain->match = of_irq_domain_default_match;
+	if (!domain->map) {
+		WARN_ON(1);
+		return;
+	}
+
+	raw_spin_lock_irqsave(&of_irq_lock, flags);
+	list_add(&domain->list, &of_irq_domains);
+	raw_spin_unlock_irqrestore(&of_irq_lock, flags);
+}
+
+/**
+ * of_irq_domain_find() - Find the domain that handles a given device tree node
+ *
+ * Returns the pointer to an of_irq_domain capable of translating irq specifiers
+ * for the given irq controller device tree node.  Returns NULL if a suitable
+ * domain could not be found.
+ */
+struct of_irq_domain *of_irq_domain_find(struct device_node *controller)
+{
+	struct of_irq_domain *domain, *found = NULL;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&of_irq_lock, flags);
+	list_for_each_entry(domain, &of_irq_domains, list) {
+		if (domain->match(domain, controller)) {
+			found = domain;
+			break;
+		}
+	}
+	raw_spin_unlock_irqrestore(&of_irq_lock, flags);
+	return found;
+}
+
+/**
+ * of_irq_set_default_domain() - Set a "default" host
+ * @domain: default domain pointer
+ *
+ * For convenience, it's possible to set a "default" host that will be used
+ * whenever NULL is passed to irq_of_create_mapping(). It makes life easier
+ * for platforms that want to manipulate a few hard coded interrupt numbers
+ * that aren't properly represented in the device-tree.
+ */
+void of_irq_set_default_domain(struct of_irq_domain *domain)
+{
+	pr_debug("irq: Default host set to @0x%p\n", domain);
+	of_irq_default_domain = domain;
+}
+
+/**
+ * irq_create_of_mapping() - Map a linux irq # from a device tree specifier
+ * @controller - interrupt-controller node in the device tree
+ * @intspec - array of interrupt specifier data.  Points to an array of u32
+ *            values.  Data is *cpu-native* endian u32 values.
+ * @intsize - size of intspec array.
+ *
+ * Given an interrupt controller node pointer and an interrupt specifier, this
+ * function looks up the linux irq number.
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	struct of_irq_domain *domain;
+
+	domain = of_irq_domain_find(controller);
+	if (!domain)
+		domain = of_irq_default_domain;
+	if (!domain) {
+		pr_warn("error: no irq host found for %s !\n",
+			controller->full_name);
+#if defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE)
+		/* FIXME: make Microblaze and MIPS register irq domains */
+		return intspec[0];
+#else /* defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE) */
+		return NO_IRQ;
+#endif /* defined(CONFIG_MIPS) || defined(CONFIG_MICROBLAZE) */
+	}
+
+	return domain->map(domain, controller, intspec, intsize);
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
 /**
  * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
  * @device: Device node of the device whose interrupt is to be mapped
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 109e013..511dbc3 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -33,6 +33,37 @@ struct of_irq {
 	u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
 };
 
+/**
+ * struct of_irq_domain - Translation domain from device tree to linux irq
+ * @list: Linked list node entry
+ * @match: (optional) Called to determine if the passed device_node
+ *         interrupt-controller can be translated by this irq domain.
+ *         Returns 'true' if it can.
+ * @decode: Translation callback; returns virq, or NO_IRQ if this irq
+ *          domain cannot translate it.
+ * @controller: (optional) pointer to OF node.  By default, if
+ *              'match' is not set, then this of_irq_domain will only
+ *              be used if the device tree node passed in matches the
+ *              controller pointer.
+ * @priv: Private data pointer, not touched by core of_irq_domain code.
+ */
+struct of_irq_domain {
+	struct list_head list;
+	bool (*match)(struct of_irq_domain *d, struct device_node *np);
+	unsigned int (*map)(struct of_irq_domain *d, struct device_node *np,
+			    const u32 *intspec, u32 intsize);
+	struct device_node *controller;
+	void *priv;
+};
+
+/**
+ * of_irq_domain_add() - Add a device tree interrupt translation domain
+ * @domain: interrupt domain to add.
+ */
+extern void of_irq_domain_add(struct of_irq_domain *domain);
+extern void of_irq_set_default_domain(struct of_irq_domain *host);
+extern struct of_irq_domain *of_irq_domain_find(struct device_node *controller);
+
 /*
  * Workarounds only applied to 32bit powermac machines
  */

^ permalink raw reply related

* [PATCH 3/6] powerpc: Make struct irq_host semi-private by moving into irqhost.h
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev
In-Reply-To: <20110428192227.8979.49181.stgit@ponder>

Very few files actually need direct access to struct irq_host members.
This patch moves the irq_host definition into another file so that it
isn't brought in by default, and to prepare for the addition of
struct of_irq_domain, which will factor some of the irq_host behaviour
out into common code.  This needs to be done because of_irq_domain
will be embedded inside struct irq_host, and to do that it needs to be
guaranteed that struct of_irq_domain gets fully defined first.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/include/asm/irq.h                   |   20 +--------------
 arch/powerpc/include/asm/irqhost.h               |   29 ++++++++++++++++++++++
 arch/powerpc/kernel/irq.c                        |    1 +
 arch/powerpc/platforms/512x/mpc5121_ads_cpld.c   |    1 +
 arch/powerpc/platforms/52xx/media5200.c          |    1 +
 arch/powerpc/platforms/52xx/mpc52xx_gpt.c        |    1 +
 arch/powerpc/platforms/52xx/mpc52xx_pic.c        |    1 +
 arch/powerpc/platforms/82xx/pq2ads-pci-pic.c     |    1 +
 arch/powerpc/platforms/cell/axon_msi.c           |    1 +
 arch/powerpc/platforms/cell/spider-pic.c         |    1 +
 arch/powerpc/platforms/embedded6xx/flipper-pic.c |    1 +
 arch/powerpc/platforms/embedded6xx/hlwd-pic.c    |    1 +
 arch/powerpc/platforms/embedded6xx/wii.c         |    6 +++--
 arch/powerpc/sysdev/fsl_msi.c                    |    1 +
 arch/powerpc/sysdev/i8259.c                      |    1 +
 arch/powerpc/sysdev/ipic.c                       |    1 +
 arch/powerpc/sysdev/mpc8xxx_gpio.c               |    1 +
 arch/powerpc/sysdev/mpic.c                       |    1 +
 arch/powerpc/sysdev/mpic_msi.c                   |    1 +
 arch/powerpc/sysdev/mpic_pasemi_msi.c            |    1 +
 arch/powerpc/sysdev/qe_lib/qe_ic.c               |    1 +
 arch/powerpc/sysdev/uic.c                        |    1 +
 arch/powerpc/sysdev/xilinx_intc.c                |    1 +
 23 files changed, 54 insertions(+), 21 deletions(-)
 create mode 100644 arch/powerpc/include/asm/irqhost.h

diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 4d2cc6f..a44be93 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -104,29 +104,11 @@ struct irq_host_ops {
 		     irq_hw_number_t *out_hwirq, unsigned int *out_type);
 };
 
-struct irq_host {
-	struct list_head	link;
-
-	/* type of reverse mapping technique */
-	unsigned int		revmap_type;
+/* Reverse map types; pass into irq_alloc_host revmap_type argument */
 #define IRQ_HOST_MAP_LEGACY     0 /* legacy 8259, gets irqs 1..15 */
 #define IRQ_HOST_MAP_NOMAP	1 /* no fast reverse mapping */
 #define IRQ_HOST_MAP_LINEAR	2 /* linear map of interrupts */
 #define IRQ_HOST_MAP_TREE	3 /* radix tree */
-	union {
-		struct {
-			unsigned int size;
-			unsigned int *revmap;
-		} linear;
-		struct radix_tree_root tree;
-	} revmap_data;
-	struct irq_host_ops	*ops;
-	void			*host_data;
-	irq_hw_number_t		inval_irq;
-
-	/* Optional device node pointer */
-	struct device_node	*of_node;
-};
 
 struct irq_data;
 extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
diff --git a/arch/powerpc/include/asm/irqhost.h b/arch/powerpc/include/asm/irqhost.h
new file mode 100644
index 0000000..958e6c1
--- /dev/null
+++ b/arch/powerpc/include/asm/irqhost.h
@@ -0,0 +1,29 @@
+#ifndef _ASM_POWERPC_IRQHOST_H
+#define _ASM_POWERPC_IRQHOST_H
+
+#include <linux/list.h>
+#include <linux/radix-tree.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+
+struct irq_host {
+	struct list_head	link;
+
+	/* type of reverse mapping technique */
+	unsigned int		revmap_type;
+	union {
+		struct {
+			unsigned int size;
+			unsigned int *revmap;
+		} linear;
+		struct radix_tree_root tree;
+	} revmap_data;
+	struct irq_host_ops	*ops;
+	void			*host_data;
+	irq_hw_number_t		inval_irq;
+
+	/* Optional device node pointer */
+	struct device_node	*of_node;
+};
+
+#endif /* _ASM_POWERPC_IRQHOST_H */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5ccf38f..b961b19 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -56,6 +56,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 
+#include <asm/irqhost.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
index a8bc0d4..162bbb7 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <asm/irqhost.h>
 #include <asm/prom.h>
 
 static struct device_node *cpld_pic_node;
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 96f85e5..e03f2cb 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <asm/irqhost.h>
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 6c39b9c..55b2d26 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -67,6 +67,7 @@
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
+#include <asm/irqhost.h>
 #include <asm/div64.h>
 #include <asm/mpc52xx.h>
 
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index bb61181..65bbfd1 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -101,6 +101,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/mpc52xx.h>
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 5d6c34c..0ca79e0 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -19,6 +19,7 @@
 #include <linux/bootmem.h>
 #include <linux/slab.h>
 
+#include <asm/irqhost.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/cpm2.h>
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 1e3329e..e1469ae 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -17,6 +17,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 
+#include <asm/irqhost.h>
 #include <asm/dcr.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 34d2b99..73a5494 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/ioport.h>
 
+#include <asm/irqhost.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
 #include <asm/io.h>
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
index 77cbe4c..1b60a34 100644
--- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 
 #include "flipper-pic.h"
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
index 44b398b..4f87661 100644
--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 
 #include "hlwd-pic.h"
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 1b5dc1a..c9176a9 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -85,9 +85,11 @@ void __init wii_memory_fixups(void)
 	wii_hole_start = p[0].base + p[0].size;
 	wii_hole_size = p[1].base - wii_hole_start;
 
-	pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
+	pr_info("MEM1: <%08llx %08llx>\n",
+		(unsigned long long)p[0].base, (unsigned long long)p[0].size);
 	pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
-	pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);
+	pr_info("MEM2: <%08llx %08llx>\n",
+		(unsigned long long)p[1].base, (unsigned long long)p[1].size);
 
 	p[0].size += wii_hole_size + p[1].size;
 
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index d5679dc..2c11b3e 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/of_platform.h>
 #include <sysdev/fsl_soc.h>
+#include <asm/irqhost.h>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 142770c..30869f0 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 #include <asm/i8259.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index f0ece79..fc3751f 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -24,6 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/fsl_devices.h>
 #include <asm/irq.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/ipic.h>
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index fb4963a..f6839a7 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -17,6 +17,7 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
+#include <asm/irqhost.h>
 
 #define MPC8XXX_GPIO_PINS	32
 
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 824a94f..6e9e594 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 
+#include <asm/irqhost.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 0f67cd7..50176ed 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 #include <linux/bitmap.h>
 #include <linux/msi.h>
+#include <asm/irqhost.h>
 #include <asm/mpic.h>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 38e6238..6b11a89 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -18,6 +18,7 @@
 #include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/msi.h>
+#include <asm/irqhost.h>
 #include <asm/mpic.h>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index b2acda0..9dd7746 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -26,6 +26,7 @@
 #include <linux/device.h>
 #include <linux/bootmem.h>
 #include <linux/spinlock.h>
+#include <asm/irqhost.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 984cd20..a097f4c 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <asm/irq.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/dcr.h>
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 6183799..28d4ded 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <asm/irqhost.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/i8259.h>

^ permalink raw reply related

* [PATCH 2/6] powerpc: make irq_{alloc, free}_virt private and remove count argument
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev
In-Reply-To: <20110428192227.8979.49181.stgit@ponder>

irq_alloc_virt() and irq_free_virt() aren't called anywhere but from
arch/powerpc/kernel/irq.c, and they are only ever called with count=1.
This patch removes the prototypes from the header file, removes the
count arguments, and cuts out the dead code.

Also removes obsolete references to irq_early_init()

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/microblaze/kernel/setup.c |    2 -
 arch/powerpc/include/asm/irq.h |   32 ----------------
 arch/powerpc/kernel/irq.c      |   82 ++++++++++++++++++++--------------------
 3 files changed, 40 insertions(+), 76 deletions(-)

diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 8e2c09b..19d3ab7 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -51,8 +51,6 @@ void __init setup_arch(char **cmdline_p)
 
 	unflatten_device_tree();
 
-	/* NOTE I think that this function is not necessary to call */
-	/* irq_early_init(); */
 	setup_cpuinfo();
 
 	microblaze_cache_init();
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index e1983d5..4d2cc6f 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -264,38 +264,6 @@ extern unsigned int irq_linear_revmap(struct irq_host *host,
 				      irq_hw_number_t hwirq);
 
 
-
-/**
- * irq_alloc_virt - Allocate virtual irq numbers
- * @host: host owning these new virtual irqs
- * @count: number of consecutive numbers to allocate
- * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
- *
- * This is a low level function that is used internally by irq_create_mapping()
- * and that can be used by some irq controllers implementations for things
- * like allocating ranges of numbers for MSIs. The revmaps are left untouched.
- */
-extern unsigned int irq_alloc_virt(struct irq_host *host,
-				   unsigned int count,
-				   unsigned int hint);
-
-/**
- * irq_free_virt - Free virtual irq numbers
- * @virq: virtual irq number of the first interrupt to free
- * @count: number of interrupts to free
- *
- * This function is the opposite of irq_alloc_virt. It will not clear reverse
- * maps, this should be done previously by unmap'ing the interrupt. In fact,
- * all interrupts covered by the range being freed should have been unmapped
- * prior to calling this.
- */
-extern void irq_free_virt(unsigned int virq, unsigned int count);
-
-/**
- * irq_early_init - Init irq remapping subsystem
- */
-extern void irq_early_init(void);
-
 static __inline__ int irq_canonicalize(int irq)
 {
 	return irq;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 422672b..5ccf38f 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -647,6 +647,9 @@ void irq_set_virq_count(unsigned int count)
 		irq_virq_count = count;
 }
 
+static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint);
+static void irq_free_virt(unsigned int virq);
+
 static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 			    irq_hw_number_t hwirq)
 {
@@ -675,7 +678,7 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 errdesc:
 	irq_free_descs(virq, 1);
 error:
-	irq_free_virt(virq, 1);
+	irq_free_virt(virq);
 	return -1;
 }
 
@@ -689,7 +692,7 @@ unsigned int irq_create_direct_mapping(struct irq_host *host)
 	BUG_ON(host == NULL);
 	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP);
 
-	virq = irq_alloc_virt(host, 1, 0);
+	virq = irq_alloc_virt(host, 0);
 	if (virq == NO_IRQ) {
 		pr_debug("irq: create_direct virq allocation failed\n");
 		return NO_IRQ;
@@ -742,7 +745,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
 	} else {
 		/* Allocate a virtual interrupt number */
 		hint = hwirq % irq_virq_count;
-		virq = irq_alloc_virt(host, 1, hint);
+		virq = irq_alloc_virt(host, hint);
 		if (virq == NO_IRQ) {
 			pr_debug("irq: -> virq allocation failed\n");
 			return NO_IRQ;
@@ -856,7 +859,7 @@ void irq_dispose_mapping(unsigned int virq)
 
 	irq_free_descs(virq, 1);
 	/* Free it */
-	irq_free_virt(virq, 1);
+	irq_free_virt(virq);
 }
 EXPORT_SYMBOL_GPL(irq_dispose_mapping);
 
@@ -974,36 +977,31 @@ unsigned int irq_linear_revmap(struct irq_host *host,
 	return revmap[hwirq];
 }
 
-unsigned int irq_alloc_virt(struct irq_host *host,
-			    unsigned int count,
-			    unsigned int hint)
+/**
+ * irq_alloc_virt() - Allocate virtual irq numbers
+ * @host: host owning these new virtual irqs
+ * @hint: pass a hint number, the allocator will try to use a 1:1 mapping
+ *
+ * This is a low level function that is used internally by irq_create_mapping()
+ */
+static unsigned int irq_alloc_virt(struct irq_host *host, unsigned int hint)
 {
 	unsigned long flags;
 	unsigned int i, j, found = NO_IRQ;
 
-	if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS))
-		return NO_IRQ;
-
 	raw_spin_lock_irqsave(&irq_big_lock, flags);
 
 	/* Use hint for 1 interrupt if any */
-	if (count == 1 && hint >= NUM_ISA_INTERRUPTS &&
+	if (hint >= NUM_ISA_INTERRUPTS &&
 	    hint < irq_virq_count && irq_map[hint].host == NULL) {
 		found = hint;
 		goto hint_found;
 	}
 
-	/* Look for count consecutive numbers in the allocatable
-	 * (non-legacy) space
-	 */
+	/* Look for a free virq in the allocatable (non-legacy) space */
 	for (i = NUM_ISA_INTERRUPTS, j = 0; i < irq_virq_count; i++) {
-		if (irq_map[i].host != NULL)
-			j = 0;
-		else
-			j++;
-
-		if (j == count) {
-			found = i - count + 1;
+		if (irq_map[i].host == NULL) {
+			found = i;
 			break;
 		}
 	}
@@ -1012,36 +1010,36 @@ unsigned int irq_alloc_virt(struct irq_host *host,
 		return NO_IRQ;
 	}
  hint_found:
-	for (i = found; i < (found + count); i++) {
-		irq_map[i].hwirq = host->inval_irq;
-		smp_wmb();
-		irq_map[i].host = host;
-	}
+	irq_map[found].hwirq = host->inval_irq;
+	smp_wmb();
+	irq_map[found].host = host;
 	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
 	return found;
 }
 
-void irq_free_virt(unsigned int virq, unsigned int count)
+/**
+ * irq_free_virt() - Free virtual irq numbers
+ * @virq: virtual irq number of the first interrupt to free
+ *
+ * This function is the opposite of irq_alloc_virt. It will not clear reverse
+ * maps, this should be done previously by unmap'ing the interrupt. In fact,
+ * the interrupts being freed should have been unmapped prior to calling this.
+ */
+static void irq_free_virt(unsigned int virq)
 {
 	unsigned long flags;
-	unsigned int i;
+	struct irq_host *host;
 
-	WARN_ON (virq < NUM_ISA_INTERRUPTS);
-	WARN_ON (count == 0 || (virq + count) > irq_virq_count);
+	if ((virq < NUM_ISA_INTERRUPTS) || (virq >= irq_virq_count)) {
+		WARN_ON(1);
+		return;
+	}
 
 	raw_spin_lock_irqsave(&irq_big_lock, flags);
-	for (i = virq; i < (virq + count); i++) {
-		struct irq_host *host;
-
-		if (i < NUM_ISA_INTERRUPTS ||
-		    (virq + count) > irq_virq_count)
-			continue;
-
-		host = irq_map[i].host;
-		irq_map[i].hwirq = host->inval_irq;
-		smp_wmb();
-		irq_map[i].host = NULL;
-	}
+	host = irq_map[virq].host;
+	irq_map[virq].hwirq = host->inval_irq;
+	smp_wmb();
+	irq_map[virq].host = NULL;
 	raw_spin_unlock_irqrestore(&irq_big_lock, flags);
 }
 

^ permalink raw reply related

* [PATCH 1/6] powerpc: stop exporting irq_map
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev
In-Reply-To: <20110428192227.8979.49181.stgit@ponder>

First step in eliminating irq_map[] table entirely

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/include/asm/irq.h                   |   15 +---
 arch/powerpc/kernel/irq.c                        |   26 +++++++
 arch/powerpc/platforms/512x/mpc5121_ads_cpld.c   |    4 +
 arch/powerpc/platforms/52xx/media5200.c          |    4 +
 arch/powerpc/platforms/52xx/mpc52xx_pic.c        |   79 ++++------------------
 arch/powerpc/platforms/82xx/pq2ads-pci-pic.c     |    4 +
 arch/powerpc/platforms/85xx/socrates_fpga_pic.c  |   26 ++-----
 arch/powerpc/platforms/86xx/gef_pic.c            |   10 +--
 arch/powerpc/platforms/8xx/m8xx_setup.c          |    2 -
 arch/powerpc/platforms/cell/axon_msi.c           |    2 -
 arch/powerpc/platforms/cell/spider-pic.c         |   10 +--
 arch/powerpc/platforms/embedded6xx/flipper-pic.c |    8 +-
 arch/powerpc/platforms/embedded6xx/hlwd-pic.c    |    8 +-
 arch/powerpc/platforms/iseries/irq.c             |   10 +--
 arch/powerpc/platforms/powermac/pic.c            |   12 ++-
 arch/powerpc/platforms/pseries/ras.c             |    4 +
 arch/powerpc/platforms/pseries/xics.c            |   14 ++--
 arch/powerpc/sysdev/cpm1.c                       |    8 +-
 arch/powerpc/sysdev/cpm2_pic.c                   |   10 +--
 arch/powerpc/sysdev/ipic.c                       |   16 ++--
 arch/powerpc/sysdev/mpc8xx_pic.c                 |   10 +--
 arch/powerpc/sysdev/mpc8xxx_gpio.c               |   12 ++-
 arch/powerpc/sysdev/mpic.c                       |   28 ++++----
 arch/powerpc/sysdev/mv64x60_pic.c                |   14 ++--
 arch/powerpc/sysdev/qe_lib/qe_ic.c               |    6 +-
 arch/powerpc/sysdev/uic.c                        |   12 +--
 arch/powerpc/sysdev/xilinx_intc.c                |    8 +-
 27 files changed, 147 insertions(+), 215 deletions(-)

diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index 67ab5fb..e1983d5 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -128,19 +128,10 @@ struct irq_host {
 	struct device_node	*of_node;
 };
 
-/* The main irq map itself is an array of NR_IRQ entries containing the
- * associate host and irq number. An entry with a host of NULL is free.
- * An entry can be allocated if it's free, the allocator always then sets
- * hwirq first to the host's invalid irq number and then fills ops.
- */
-struct irq_map_entry {
-	irq_hw_number_t	hwirq;
-	struct irq_host	*host;
-};
-
-extern struct irq_map_entry irq_map[NR_IRQS];
-
+struct irq_data;
+extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
 extern irq_hw_number_t virq_to_hw(unsigned int virq);
+extern struct irq_host *virq_to_host(unsigned int virq);
 
 /**
  * irq_alloc_host - Allocate a new irq_host data structure
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index f621b7d..422672b 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -477,20 +477,42 @@ void do_softirq(void)
  * IRQ controller and virtual interrupts
  */
 
+/* The main irq map itself is an array of NR_IRQ entries containing the
+ * associate host and irq number. An entry with a host of NULL is free.
+ * An entry can be allocated if it's free, the allocator always then sets
+ * hwirq first to the host's invalid irq number and then fills ops.
+ */
+struct irq_map_entry {
+	irq_hw_number_t	hwirq;
+	struct irq_host	*host;
+};
+
 static LIST_HEAD(irq_hosts);
 static DEFINE_RAW_SPINLOCK(irq_big_lock);
 static unsigned int revmap_trees_allocated;
 static DEFINE_MUTEX(revmap_trees_mutex);
-struct irq_map_entry irq_map[NR_IRQS];
+static struct irq_map_entry irq_map[NR_IRQS];
 static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_host *irq_default_host;
 
+irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
+{
+	return irq_map[d->irq].hwirq;
+}
+EXPORT_SYMBOL_GPL(irqd_to_hwirq);
+
 irq_hw_number_t virq_to_hw(unsigned int virq)
 {
 	return irq_map[virq].hwirq;
 }
 EXPORT_SYMBOL_GPL(virq_to_hw);
 
+struct irq_host *virq_to_host(unsigned int virq)
+{
+	return irq_map[virq].host;
+}
+EXPORT_SYMBOL_GPL(virq_to_host);
+
 static int default_irq_host_match(struct irq_host *h, struct device_node *np)
 {
 	return h->of_node != NULL && h->of_node == np;
@@ -1098,7 +1120,7 @@ static int virq_debug_show(struct seq_file *m, void *private)
 			struct irq_chip *chip;
 
 			seq_printf(m, "%5d  ", i);
-			seq_printf(m, "0x%05lx  ", virq_to_hw(i));
+			seq_printf(m, "0x%05lx  ", irq_map[i].hwirq);
 
 			chip = irq_desc_get_chip(desc);
 			if (chip && chip->name)
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
index cfc4b20..a8bc0d4 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
@@ -61,7 +61,7 @@ irq_to_pic_bit(unsigned int irq)
 static void
 cpld_mask_irq(struct irq_data *d)
 {
-	unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int cpld_irq = (unsigned int)irqd_to_hwirq(d);
 	void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
 
 	out_8(pic_mask,
@@ -71,7 +71,7 @@ cpld_mask_irq(struct irq_data *d)
 static void
 cpld_unmask_irq(struct irq_data *d)
 {
-	unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int cpld_irq = (unsigned int)irqd_to_hwirq(d);
 	void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
 
 	out_8(pic_mask,
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 57a6a34..96f85e5 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -56,7 +56,7 @@ static void media5200_irq_unmask(struct irq_data *d)
 
 	spin_lock_irqsave(&media5200_irq.lock, flags);
 	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
-	val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq);
+	val |= 1 << (MEDIA5200_IRQ_SHIFT + irqd_to_hwirq(d));
 	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
 	spin_unlock_irqrestore(&media5200_irq.lock, flags);
 }
@@ -68,7 +68,7 @@ static void media5200_irq_mask(struct irq_data *d)
 
 	spin_lock_irqsave(&media5200_irq.lock, flags);
 	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
-	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq));
+	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irqd_to_hwirq(d)));
 	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
 	spin_unlock_irqrestore(&media5200_irq.lock, flags);
 }
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 1dd1540..bb61181 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -157,48 +157,30 @@ static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
  */
 static void mpc52xx_extirq_mask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_clrbit(&intr->ctrl, 11 - l2irq);
 }
 
 static void mpc52xx_extirq_unmask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_setbit(&intr->ctrl, 11 - l2irq);
 }
 
 static void mpc52xx_extirq_ack(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_setbit(&intr->ctrl, 27-l2irq);
 }
 
 static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	u32 ctrl_reg, type;
-	int irq;
-	int l2irq;
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	void *handler = handle_level_irq;
 
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
-	pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
+	pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__,
+		(int) irqd_to_hwirq(d), l2irq, flow_type);
 
 	switch (flow_type) {
 	case IRQF_TRIGGER_HIGH: type = 0; break;
@@ -237,23 +219,13 @@ static int mpc52xx_null_set_type(struct irq_data *d, unsigned int flow_type)
 
 static void mpc52xx_main_mask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_setbit(&intr->main_mask, 16 - l2irq);
 }
 
 static void mpc52xx_main_unmask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_clrbit(&intr->main_mask, 16 - l2irq);
 }
 
@@ -270,23 +242,13 @@ static struct irq_chip mpc52xx_main_irqchip = {
  */
 static void mpc52xx_periph_mask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_setbit(&intr->per_mask, 31 - l2irq);
 }
 
 static void mpc52xx_periph_unmask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_clrbit(&intr->per_mask, 31 - l2irq);
 }
 
@@ -303,34 +265,19 @@ static struct irq_chip mpc52xx_periph_irqchip = {
  */
 static void mpc52xx_sdma_mask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_setbit(&sdma->IntMask, l2irq);
 }
 
 static void mpc52xx_sdma_unmask(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	io_be_clrbit(&sdma->IntMask, l2irq);
 }
 
 static void mpc52xx_sdma_ack(struct irq_data *d)
 {
-	int irq;
-	int l2irq;
-
-	irq = irq_map[d->irq].hwirq;
-	l2irq = irq & MPC52xx_IRQ_L2_MASK;
-
+	int l2irq = irqd_to_hwirq(d) & MPC52xx_IRQ_L2_MASK;
 	out_be32(&sdma->IntPend, 1 << l2irq);
 }
 
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 4a4eb6f..5d6c34c 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -42,7 +42,7 @@ struct pq2ads_pci_pic {
 static void pq2ads_pci_mask_irq(struct irq_data *d)
 {
 	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
-	int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
+	int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;
 
 	if (irq != -1) {
 		unsigned long flags;
@@ -58,7 +58,7 @@ static void pq2ads_pci_mask_irq(struct irq_data *d)
 static void pq2ads_pci_unmask_irq(struct irq_data *d)
 {
 	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
-	int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
+	int irq = NUM_IRQS - irqd_to_hwirq(d) - 1;
 
 	if (irq != -1) {
 		unsigned long flags;
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
index db86462..12cb9bb 100644
--- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -48,8 +48,6 @@ static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
 	[8] = {0, IRQ_TYPE_LEVEL_HIGH},
 };
 
-#define socrates_fpga_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
-
 static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
 
 static void __iomem *socrates_fpga_pic_iobase;
@@ -110,11 +108,9 @@ void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
 static void socrates_fpga_pic_ack(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq, irq_line;
+	unsigned int irq_line, hwirq = irqd_to_hwirq(d);
 	uint32_t mask;
 
-	hwirq = socrates_fpga_irq_to_hw(d->irq);
-
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -127,12 +123,10 @@ static void socrates_fpga_pic_ack(struct irq_data *d)
 static void socrates_fpga_pic_mask(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(d->irq);
-
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -145,12 +139,10 @@ static void socrates_fpga_pic_mask(struct irq_data *d)
 static void socrates_fpga_pic_mask_ack(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(d->irq);
-
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -164,12 +156,10 @@ static void socrates_fpga_pic_mask_ack(struct irq_data *d)
 static void socrates_fpga_pic_unmask(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(d->irq);
-
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -182,12 +172,10 @@ static void socrates_fpga_pic_unmask(struct irq_data *d)
 static void socrates_fpga_pic_eoi(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(d->irq);
-
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
@@ -201,12 +189,10 @@ static int socrates_fpga_pic_set_type(struct irq_data *d,
 		unsigned int flow_type)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	int polarity;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(d->irq);
-
 	if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
 		return -EINVAL;
 
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
index 0beec7d..94594e5 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.c
+++ b/arch/powerpc/platforms/86xx/gef_pic.c
@@ -46,8 +46,6 @@
 #define GEF_PIC_CPU0_MCP_MASK	GEF_PIC_MCP_MASK(0)
 #define GEF_PIC_CPU1_MCP_MASK	GEF_PIC_MCP_MASK(1)
 
-#define gef_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
-
 
 static DEFINE_RAW_SPINLOCK(gef_pic_lock);
 
@@ -113,11 +111,9 @@ void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
 static void gef_pic_mask(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	u32 mask;
 
-	hwirq = gef_irq_to_hw(d->irq);
-
 	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
 	mask &= ~(1 << hwirq);
@@ -136,11 +132,9 @@ static void gef_pic_mask_ack(struct irq_data *d)
 static void gef_pic_unmask(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int hwirq;
+	unsigned int hwirq = irqd_to_hwirq(d);
 	u32 mask;
 
-	hwirq = gef_irq_to_hw(d->irq);
-
 	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
 	mask |= (1 << hwirq);
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 9ecce99..1e12108 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -150,7 +150,7 @@ void __init mpc8xx_calibrate_decr(void)
 	 */
 	cpu = of_find_node_by_type(NULL, "cpu");
 	virq= irq_of_parse_and_map(cpu, 0);
-	irq = irq_map[virq].hwirq;
+	irq = virq_to_hw(virq);
 
 	sys_tmr2 = immr_map(im_sit);
 	out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index bb5ebf8..1e3329e 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -113,7 +113,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 		pr_devel("axon_msi: woff %x roff %x msi %x\n",
 			  write_offset, msic->read_offset, msi);
 
-		if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
+		if (msi < NR_IRQS && virq_to_host(msi) == msic->irq_host) {
 			generic_handle_irq(msi);
 			msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
 		} else {
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index c5cf50e..34d2b99 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -70,7 +70,7 @@ static struct spider_pic spider_pics[SPIDER_CHIP_COUNT];
 
 static struct spider_pic *spider_virq_to_pic(unsigned int virq)
 {
-	return irq_map[virq].host->host_data;
+	return virq_to_host(virq)->host_data;
 }
 
 static void __iomem *spider_get_irq_config(struct spider_pic *pic,
@@ -82,7 +82,7 @@ static void __iomem *spider_get_irq_config(struct spider_pic *pic,
 static void spider_unmask_irq(struct irq_data *d)
 {
 	struct spider_pic *pic = spider_virq_to_pic(d->irq);
-	void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
+	void __iomem *cfg = spider_get_irq_config(pic, irqd_to_hwirq(d));
 
 	out_be32(cfg, in_be32(cfg) | 0x30000000u);
 }
@@ -90,7 +90,7 @@ static void spider_unmask_irq(struct irq_data *d)
 static void spider_mask_irq(struct irq_data *d)
 {
 	struct spider_pic *pic = spider_virq_to_pic(d->irq);
-	void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
+	void __iomem *cfg = spider_get_irq_config(pic, irqd_to_hwirq(d));
 
 	out_be32(cfg, in_be32(cfg) & ~0x30000000u);
 }
@@ -98,7 +98,7 @@ static void spider_mask_irq(struct irq_data *d)
 static void spider_ack_irq(struct irq_data *d)
 {
 	struct spider_pic *pic = spider_virq_to_pic(d->irq);
-	unsigned int src = irq_map[d->irq].hwirq;
+	unsigned int src = irqd_to_hwirq(d);
 
 	/* Reset edge detection logic if necessary
 	 */
@@ -117,7 +117,7 @@ static int spider_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
 	struct spider_pic *pic = spider_virq_to_pic(d->irq);
-	unsigned int hw = irq_map[d->irq].hwirq;
+	unsigned int hw = irqd_to_hwirq(d);
 	void __iomem *cfg = spider_get_irq_config(pic, hw);
 	u32 old_mask;
 	u32 ic;
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
index 12aa62b..77cbe4c 100644
--- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -48,7 +48,7 @@
 
 static void flipper_pic_mask_and_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 	u32 mask = 1 << irq;
 
@@ -59,7 +59,7 @@ static void flipper_pic_mask_and_ack(struct irq_data *d)
 
 static void flipper_pic_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	/* this is at least needed for RSW */
@@ -68,7 +68,7 @@ static void flipper_pic_ack(struct irq_data *d)
 
 static void flipper_pic_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	clrbits32(io_base + FLIPPER_IMR, 1 << irq);
@@ -76,7 +76,7 @@ static void flipper_pic_mask(struct irq_data *d)
 
 static void flipper_pic_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	setbits32(io_base + FLIPPER_IMR, 1 << irq);
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
index 2bdddfc..44b398b 100644
--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -43,7 +43,7 @@
 
 static void hlwd_pic_mask_and_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 	u32 mask = 1 << irq;
 
@@ -53,7 +53,7 @@ static void hlwd_pic_mask_and_ack(struct irq_data *d)
 
 static void hlwd_pic_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
@@ -61,7 +61,7 @@ static void hlwd_pic_ack(struct irq_data *d)
 
 static void hlwd_pic_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
@@ -69,7 +69,7 @@ static void hlwd_pic_mask(struct irq_data *d)
 
 static void hlwd_pic_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 52a6889..375c21c 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -171,7 +171,7 @@ static void iseries_enable_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
 
 	/* The IRQ has already been locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -188,7 +188,7 @@ static unsigned int iseries_startup_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
 
 	bus = REAL_IRQ_TO_BUS(rirq);
 	function = REAL_IRQ_TO_FUNC(rirq);
@@ -234,7 +234,7 @@ static void iseries_shutdown_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
 
 	/* irq should be locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -257,7 +257,7 @@ static void iseries_disable_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
 
 	/* The IRQ has already been locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -271,7 +271,7 @@ static void iseries_disable_IRQ(struct irq_data *d)
 
 static void iseries_end_IRQ(struct irq_data *d)
 {
-	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int rirq = (unsigned int)irqd_to_hwirq(d);
 
 	HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
 		(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 023f240..2f34ad0 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -84,7 +84,7 @@ static void __pmac_retrigger(unsigned int irq_nr)
 
 static void pmac_mask_and_ack_irq(struct irq_data *d)
 {
-	unsigned int src = irq_map[d->irq].hwirq;
+	unsigned int src = irqd_to_hwirq(d);
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
         unsigned long flags;
@@ -106,7 +106,7 @@ static void pmac_mask_and_ack_irq(struct irq_data *d)
 
 static void pmac_ack_irq(struct irq_data *d)
 {
-	unsigned int src = irq_map[d->irq].hwirq;
+	unsigned int src = irqd_to_hwirq(d);
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
         unsigned long flags;
@@ -152,7 +152,7 @@ static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
 static unsigned int pmac_startup_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[d->irq].hwirq;
+	unsigned int src = irqd_to_hwirq(d);
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
 
@@ -169,7 +169,7 @@ static unsigned int pmac_startup_irq(struct irq_data *d)
 static void pmac_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[d->irq].hwirq;
+	unsigned int src = irqd_to_hwirq(d);
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
         __clear_bit(src, ppc_cached_irq_mask);
@@ -180,7 +180,7 @@ static void pmac_mask_irq(struct irq_data *d)
 static void pmac_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[d->irq].hwirq;
+	unsigned int src = irqd_to_hwirq(d);
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
 	__set_bit(src, ppc_cached_irq_mask);
@@ -193,7 +193,7 @@ static int pmac_retrigger(struct irq_data *d)
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
-	__pmac_retrigger(irq_map[d->irq].hwirq);
+	__pmac_retrigger(irqd_to_hwirq(d));
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 	return 1;
 }
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index c55d7ad..164a8eb 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -122,7 +122,7 @@ static irqreturn_t ras_epow_interrupt(int irq, void *dev_id)
 
 	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
 			   RTAS_VECTOR_EXTERNAL_INTERRUPT,
-			   irq_map[irq].hwirq,
+			   virq_to_hw(irq),
 			   RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
 			   critical, __pa(&ras_log_buf),
 				rtas_get_error_log_max());
@@ -157,7 +157,7 @@ static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
 
 	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
 			   RTAS_VECTOR_EXTERNAL_INTERRUPT,
-			   irq_map[irq].hwirq,
+			   virq_to_hw(irq),
 			   RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
 			   __pa(&ras_log_buf),
 				rtas_get_error_log_max());
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index d690133..784e614 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -210,7 +210,7 @@ static void xics_unmask_irq(struct irq_data *d)
 
 	pr_devel("xics: unmask virq %d\n", d->irq);
 
-	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	hwirq = (unsigned int)irqd_to_hwirq(d);
 	pr_devel(" -> map to hwirq 0x%x\n", hwirq);
 	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return;
@@ -280,7 +280,7 @@ static void xics_mask_irq(struct irq_data *d)
 
 	pr_devel("xics: mask virq %d\n", d->irq);
 
-	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	hwirq = (unsigned int)irqd_to_hwirq(d);
 	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return;
 	xics_mask_real_irq(hwirq);
@@ -373,7 +373,7 @@ static unsigned char pop_cppr(void)
 
 static void xics_eoi_direct(struct irq_data *d)
 {
-	unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int hwirq = (unsigned int)irqd_to_hwirq(d);
 
 	iosync();
 	direct_xirr_info_set((pop_cppr() << 24) | hwirq);
@@ -381,7 +381,7 @@ static void xics_eoi_direct(struct irq_data *d)
 
 static void xics_eoi_lpar(struct irq_data *d)
 {
-	unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int hwirq = (unsigned int)irqd_to_hwirq(d);
 
 	iosync();
 	lpar_xirr_info_set((pop_cppr() << 24) | hwirq);
@@ -395,7 +395,7 @@ xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
 	int xics_status[2];
 	int irq_server;
 
-	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	hwirq = (unsigned int)irqd_to_hwirq(d);
 	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return -1;
 
@@ -900,9 +900,9 @@ void xics_migrate_irqs_away(void)
 		/* We can't set affinity on ISA interrupts */
 		if (virq < NUM_ISA_INTERRUPTS)
 			continue;
-		if (irq_map[virq].host != xics_host)
+		if (virq_to_host(virq) != xics_host)
 			continue;
-		hwirq = (unsigned int)irq_map[virq].hwirq;
+		hwirq = (unsigned int)virq_to_hw(virq);
 		/* We need to get IPIs still. */
 		if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 			continue;
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index e0bc944..350787c 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -58,21 +58,21 @@ static struct irq_host *cpm_pic_host;
 
 static void cpm_mask_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d);
 
 	clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
 }
 
 static void cpm_unmask_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d);
 
 	setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
 }
 
 static void cpm_end_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irqd_to_hwirq(d);
 
 	out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
 }
@@ -157,7 +157,7 @@ unsigned int cpm_pic_init(void)
 		goto end;
 
 	/* Initialize the CPM interrupt controller. */
-	hwirq = (unsigned int)irq_map[sirq].hwirq;
+	hwirq = (unsigned int)virq_to_hw(sirq);
 	out_be32(&cpic_reg->cpic_cicr,
 	    (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
 		((hwirq/2) << 13) | CICR_HP_MASK);
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 5495c1b..bcab50e 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -81,7 +81,7 @@ static const u_char irq_to_siubit[] = {
 static void cpm2_mask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(d->irq);
+	unsigned int irq_nr = irqd_to_hwirq(d);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -93,7 +93,7 @@ static void cpm2_mask_irq(struct irq_data *d)
 static void cpm2_unmask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(d->irq);
+	unsigned int irq_nr = irqd_to_hwirq(d);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -105,7 +105,7 @@ static void cpm2_unmask_irq(struct irq_data *d)
 static void cpm2_ack(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(d->irq);
+	unsigned int irq_nr = irqd_to_hwirq(d);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -116,7 +116,7 @@ static void cpm2_ack(struct irq_data *d)
 static void cpm2_end_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(d->irq);
+	unsigned int irq_nr = irqd_to_hwirq(d);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -133,7 +133,7 @@ static void cpm2_end_irq(struct irq_data *d)
 
 static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	unsigned int src = virq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned int vold, vnew, edibit;
 
 	/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index fa438be..f0ece79 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -521,12 +521,10 @@ static inline struct ipic * ipic_from_irq(unsigned int virq)
 	return primary_ipic;
 }
 
-#define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
-
 static void ipic_unmask_irq(struct irq_data *d)
 {
 	struct ipic *ipic = ipic_from_irq(d->irq);
-	unsigned int src = ipic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 temp;
 
@@ -542,7 +540,7 @@ static void ipic_unmask_irq(struct irq_data *d)
 static void ipic_mask_irq(struct irq_data *d)
 {
 	struct ipic *ipic = ipic_from_irq(d->irq);
-	unsigned int src = ipic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 temp;
 
@@ -562,7 +560,7 @@ static void ipic_mask_irq(struct irq_data *d)
 static void ipic_ack_irq(struct irq_data *d)
 {
 	struct ipic *ipic = ipic_from_irq(d->irq);
-	unsigned int src = ipic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 temp;
 
@@ -581,7 +579,7 @@ static void ipic_ack_irq(struct irq_data *d)
 static void ipic_mask_irq_and_ack(struct irq_data *d)
 {
 	struct ipic *ipic = ipic_from_irq(d->irq);
-	unsigned int src = ipic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 temp;
 
@@ -604,7 +602,7 @@ static void ipic_mask_irq_and_ack(struct irq_data *d)
 static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct ipic *ipic = ipic_from_irq(d->irq);
-	unsigned int src = ipic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned int vold, vnew, edibit;
 
 	if (flow_type == IRQ_TYPE_NONE)
@@ -793,7 +791,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
 int ipic_set_priority(unsigned int virq, unsigned int priority)
 {
 	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned int src = virq_to_hw(virq);
 	u32 temp;
 
 	if (priority > 7)
@@ -821,7 +819,7 @@ int ipic_set_priority(unsigned int virq, unsigned int priority)
 void ipic_set_highest_priority(unsigned int virq)
 {
 	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned int src = virq_to_hw(virq);
 	u32 temp;
 
 	temp = ipic_read(ipic->regs, IPIC_SICFR);
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index a88800f..20924f2 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -28,7 +28,7 @@ int cpm_get_irq(struct pt_regs *regs);
 static void mpc8xx_unmask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -40,7 +40,7 @@ static void mpc8xx_unmask_irq(struct irq_data *d)
 static void mpc8xx_mask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -52,7 +52,7 @@ static void mpc8xx_mask_irq(struct irq_data *d)
 static void mpc8xx_ack(struct irq_data *d)
 {
 	int	bit;
-	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
 
 	bit = irq_nr & 0x1f;
 	out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
@@ -61,7 +61,7 @@ static void mpc8xx_ack(struct irq_data *d)
 static void mpc8xx_end_irq(struct irq_data *d)
 {
 	int bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -73,7 +73,7 @@ static void mpc8xx_end_irq(struct irq_data *d)
 static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
 	if (flow_type & IRQ_TYPE_EDGE_FALLING) {
-		irq_hw_number_t hw = (unsigned int)irq_map[d->irq].hwirq;
+		irq_hw_number_t hw = (unsigned int)irqd_to_hwirq(d);
 		unsigned int siel = in_be32(&siu_reg->sc_siel);
 
 		/* only external IRQ senses are programmable */
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index 0892a28..fb4963a 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -163,7 +163,7 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
 
 	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 
 	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
@@ -176,7 +176,7 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
 
 	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 
 	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
@@ -186,7 +186,7 @@ static void mpc8xxx_irq_ack(struct irq_data *d)
 	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 
-	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 }
 
 static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
@@ -199,14 +199,14 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 	case IRQ_TYPE_EDGE_FALLING:
 		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		setbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 		break;
 
 	case IRQ_TYPE_EDGE_BOTH:
 		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		clrbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
+			  mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 		break;
 
@@ -221,7 +221,7 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long gpio = virq_to_hw(d->irq);
+	unsigned long gpio = irqd_to_hwirq(d);
 	void __iomem *reg;
 	unsigned int shift;
 	unsigned long flags;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index f91c065..824a94f 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -607,8 +607,6 @@ static int irq_choose_cpu(const struct cpumask *mask)
 }
 #endif
 
-#define mpic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
-
 /* Find an mpic associated with a given linux interrupt */
 static struct mpic *mpic_find(unsigned int irq)
 {
@@ -621,7 +619,7 @@ static struct mpic *mpic_find(unsigned int irq)
 /* Determine if the linux irq is an IPI */
 static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
 {
-	unsigned int src = mpic_irq_to_hw(irq);
+	unsigned int src = virq_to_hw(irq);
 
 	return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
 }
@@ -674,7 +672,7 @@ void mpic_unmask_irq(struct irq_data *d)
 {
 	unsigned int loops = 100000;
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
 
@@ -695,7 +693,7 @@ void mpic_mask_irq(struct irq_data *d)
 {
 	unsigned int loops = 100000;
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
 
@@ -733,7 +731,7 @@ void mpic_end_irq(struct irq_data *d)
 static void mpic_unmask_ht_irq(struct irq_data *d)
 {
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 	mpic_unmask_irq(d);
 
@@ -744,7 +742,7 @@ static void mpic_unmask_ht_irq(struct irq_data *d)
 static unsigned int mpic_startup_ht_irq(struct irq_data *d)
 {
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 	mpic_unmask_irq(d);
 	mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
@@ -755,7 +753,7 @@ static unsigned int mpic_startup_ht_irq(struct irq_data *d)
 static void mpic_shutdown_ht_irq(struct irq_data *d)
 {
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 	mpic_shutdown_ht_interrupt(mpic, src);
 	mpic_mask_irq(d);
@@ -764,7 +762,7 @@ static void mpic_shutdown_ht_irq(struct irq_data *d)
 static void mpic_end_ht_irq(struct irq_data *d)
 {
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 #ifdef DEBUG_IRQ
 	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
@@ -785,7 +783,7 @@ static void mpic_end_ht_irq(struct irq_data *d)
 static void mpic_unmask_ipi(struct irq_data *d)
 {
 	struct mpic *mpic = mpic_from_ipi(d);
-	unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
+	unsigned int src = virq_to_hw(d->irq) - mpic->ipi_vecs[0];
 
 	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
 	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
@@ -816,7 +814,7 @@ int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
 		      bool force)
 {
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 
 	if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
 		int cpuid = irq_choose_cpu(cpumask);
@@ -862,7 +860,7 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
 int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct mpic *mpic = mpic_from_irq_data(d);
-	unsigned int src = mpic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned int vecpri, vold, vnew;
 
 	DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
@@ -898,7 +896,7 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 void mpic_set_vector(unsigned int virq, unsigned int vector)
 {
 	struct mpic *mpic = mpic_from_irq(virq);
-	unsigned int src = mpic_irq_to_hw(virq);
+	unsigned int src = virq_to_hw(virq);
 	unsigned int vecpri;
 
 	DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
@@ -916,7 +914,7 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
 void mpic_set_destination(unsigned int virq, unsigned int cpuid)
 {
 	struct mpic *mpic = mpic_from_irq(virq);
-	unsigned int src = mpic_irq_to_hw(virq);
+	unsigned int src = virq_to_hw(virq);
 
 	DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
 	    mpic, virq, src, cpuid);
@@ -1427,7 +1425,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 {
 	struct mpic *mpic = mpic_find(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	unsigned int src = virq_to_hw(irq);
 	unsigned long flags;
 	u32 reg;
 
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index e9c633c..14d1302 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -78,7 +78,7 @@ static struct irq_host *mv64x60_irq_host;
 
 static void mv64x60_mask_low(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -91,7 +91,7 @@ static void mv64x60_mask_low(struct irq_data *d)
 
 static void mv64x60_unmask_low(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -115,7 +115,7 @@ static struct irq_chip mv64x60_chip_low = {
 
 static void mv64x60_mask_high(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -128,7 +128,7 @@ static void mv64x60_mask_high(struct irq_data *d)
 
 static void mv64x60_unmask_high(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -152,7 +152,7 @@ static struct irq_chip mv64x60_chip_high = {
 
 static void mv64x60_mask_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -165,7 +165,7 @@ static void mv64x60_mask_gpp(struct irq_data *d)
 
 static void mv64x60_mask_ack_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -180,7 +180,7 @@ static void mv64x60_mask_ack_gpp(struct irq_data *d)
 
 static void mv64x60_unmask_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 832d692..b2acda0 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -197,12 +197,10 @@ static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
 	return irq_data_get_irq_chip_data(d);
 }
 
-#define virq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
-
 static void qe_ic_unmask_irq(struct irq_data *d)
 {
 	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
-	unsigned int src = virq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 temp;
 
@@ -218,7 +216,7 @@ static void qe_ic_unmask_irq(struct irq_data *d)
 static void qe_ic_mask_irq(struct irq_data *d)
 {
 	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
-	unsigned int src = virq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 temp;
 
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 5d91385..984cd20 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -41,8 +41,6 @@
 #define UIC_VR		0x7
 #define UIC_VCR		0x8
 
-#define uic_irq_to_hw(virq)	(irq_map[virq].hwirq)
-
 struct uic *primary_uic;
 
 struct uic {
@@ -58,7 +56,7 @@ struct uic {
 static void uic_unmask_irq(struct irq_data *d)
 {
 	struct uic *uic = irq_data_get_irq_chip_data(d);
-	unsigned int src = uic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 er, sr;
 
@@ -76,7 +74,7 @@ static void uic_unmask_irq(struct irq_data *d)
 static void uic_mask_irq(struct irq_data *d)
 {
 	struct uic *uic = irq_data_get_irq_chip_data(d);
-	unsigned int src = uic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 er;
 
@@ -90,7 +88,7 @@ static void uic_mask_irq(struct irq_data *d)
 static void uic_ack_irq(struct irq_data *d)
 {
 	struct uic *uic = irq_data_get_irq_chip_data(d);
-	unsigned int src = uic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&uic->lock, flags);
@@ -101,7 +99,7 @@ static void uic_ack_irq(struct irq_data *d)
 static void uic_mask_ack_irq(struct irq_data *d)
 {
 	struct uic *uic = irq_data_get_irq_chip_data(d);
-	unsigned int src = uic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	u32 er, sr;
 
@@ -126,7 +124,7 @@ static void uic_mask_ack_irq(struct irq_data *d)
 static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
 	struct uic *uic = irq_data_get_irq_chip_data(d);
-	unsigned int src = uic_irq_to_hw(d->irq);
+	unsigned int src = irqd_to_hwirq(d);
 	unsigned long flags;
 	int trigger, polarity;
 	u32 tr, pr, mask;
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 0a13fc1..6183799 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -71,7 +71,7 @@ static unsigned char xilinx_intc_map_senses[] = {
  */
 static void xilinx_intc_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("mask: %d\n", irq);
 	out_be32(regs + XINTC_CIE, 1 << irq);
@@ -87,7 +87,7 @@ static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
  */
 static void xilinx_intc_level_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("unmask: %d\n", irq);
 	out_be32(regs + XINTC_SIE, 1 << irq);
@@ -112,7 +112,7 @@ static struct irq_chip xilinx_intc_level_irqchip = {
  */
 static void xilinx_intc_edge_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void *regs = irq_data_get_irq_chip_data(d);
 	pr_debug("unmask: %d\n", irq);
 	out_be32(regs + XINTC_SIE, 1 << irq);
@@ -120,7 +120,7 @@ static void xilinx_intc_edge_unmask(struct irq_data *d)
 
 static void xilinx_intc_edge_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(d->irq);
+	int irq = irqd_to_hwirq(d);
 	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("ack: %d\n", irq);
 	out_be32(regs + XINTC_IAR, 1 << irq);

^ permalink raw reply related

* [PATCH 0/6] General device tree irq domain infrastructure
From: Grant Likely @ 2011-04-28 20:01 UTC (permalink / raw)
  To: Michal Simek, Benjamin Herrenschmidt, Sebastian Andrzej Siewior,
	linux-kernel, Ralf Baechle, hpa, Dirk Brandewie, Thomas Gleixner
  Cc: devicetree-discuss, x86, linuxppc-dev

A lot of this series ends up being fixups to powerpc code; but the 4th
patch is of importance to every architecture using CONFIG_OF (except
SPARC, which has its own solution).

This series (finally!) factors out device tree irq domain decoding
from arch/powerpc and makes it generic for all architectures.  The
infrastructure is quite simple.  Any interrupt controller can embed
the of_irq_domain structure and register it with the core code.  After
that, device nodes referencing interrupts on that device tree node
will trigger a call to the domain's map function.

PowerPC and x86 have been converted to use of_irq_domain.  MIPS and
Microblaze have it enabled, but nothing actually registers domains
yet, so a workaround is in place to preserve the current behaviour
until it is fixed.

I'd really like to get patches 1-4 merged into 2.6.40.  Please test.
I'm also running through build testing here, and when it's complete
I'll push it out to a 'devicetree/irq-domain' branch on
git://git.secretlab.ca/git/linux-2.6

It needs testing.  I've booted it on a powerpc board here without any
apparent regressions, but that isn't a very big sample.  I've also
build tested on everything I think is affected.

I'd also like to get it into linux-next.  Ben, if things checkout okay
over the next few days, would you be okay with me adding it to
linux-next, say around Wednesday next week?  As for merging, I think
this should probably go via your powerpc tree since the that's where
the bulk of the changes are, but I'm open to other suggestions).

Patches 5 & 6 are follow-on cleanup work to powerpc, but patch 6 is
RFC only since there is a locking problem that I haven't fixed yet.

Cheers,
g.

---

Grant Likely (6):
      powerpc: stop exporting irq_map
      powerpc: make irq_{alloc,free}_virt private and remove count argument
      powerpc: Make struct irq_host semi-private by moving into irqhost.h
      dt: generalize of_irq_parse_and_map()
      powerpc: move irq_alloc_descs_at() call into irq_alloc_virt()
      powerpc: use irq_alloc_desc() to manage irq allocations


 arch/microblaze/kernel/irq.c                     |    7 -
 arch/microblaze/kernel/setup.c                   |    2 
 arch/mips/kernel/prom.c                          |   14 -
 arch/powerpc/include/asm/irq.h                   |   88 +------
 arch/powerpc/include/asm/irqhost.h               |   27 ++
 arch/powerpc/kernel/irq.c                        |  260 ++++++++++++----------
 arch/powerpc/platforms/512x/mpc5121_ads_cpld.c   |    5 
 arch/powerpc/platforms/52xx/media5200.c          |    5 
 arch/powerpc/platforms/52xx/mpc52xx_gpt.c        |    1 
 arch/powerpc/platforms/52xx/mpc52xx_pic.c        |   80 +------
 arch/powerpc/platforms/82xx/pq2ads-pci-pic.c     |    5 
 arch/powerpc/platforms/85xx/socrates_fpga_pic.c  |   26 +-
 arch/powerpc/platforms/86xx/gef_pic.c            |   10 -
 arch/powerpc/platforms/8xx/m8xx_setup.c          |    2 
 arch/powerpc/platforms/cell/axon_msi.c           |   15 +
 arch/powerpc/platforms/cell/spider-pic.c         |   19 +-
 arch/powerpc/platforms/embedded6xx/flipper-pic.c |    9 -
 arch/powerpc/platforms/embedded6xx/hlwd-pic.c    |    9 -
 arch/powerpc/platforms/embedded6xx/wii.c         |    6 -
 arch/powerpc/platforms/iseries/irq.c             |   10 -
 arch/powerpc/platforms/powermac/pic.c            |   12 +
 arch/powerpc/platforms/pseries/ras.c             |    4 
 arch/powerpc/platforms/pseries/xics.c            |   14 +
 arch/powerpc/sysdev/cpm1.c                       |    8 -
 arch/powerpc/sysdev/cpm2_pic.c                   |   10 -
 arch/powerpc/sysdev/fsl_msi.c                    |    3 
 arch/powerpc/sysdev/i8259.c                      |    3 
 arch/powerpc/sysdev/ipic.c                       |   19 +-
 arch/powerpc/sysdev/mpc8xx_pic.c                 |   10 -
 arch/powerpc/sysdev/mpc8xxx_gpio.c               |   13 +
 arch/powerpc/sysdev/mpic.c                       |   33 +--
 arch/powerpc/sysdev/mpic_msi.c                   |    3 
 arch/powerpc/sysdev/mpic_pasemi_msi.c            |    5 
 arch/powerpc/sysdev/mv64x60_pic.c                |   14 +
 arch/powerpc/sysdev/qe_lib/qe_ic.c               |    9 -
 arch/powerpc/sysdev/uic.c                        |   13 +
 arch/powerpc/sysdev/xilinx_intc.c                |    9 -
 arch/x86/include/asm/irq_controller.h            |   12 -
 arch/x86/include/asm/prom.h                      |    1 
 arch/x86/kernel/devicetree.c                     |   77 +------
 drivers/of/irq.c                                 |  118 ++++++++++
 include/linux/of_irq.h                           |   31 +++
 42 files changed, 504 insertions(+), 517 deletions(-)
 create mode 100644 arch/powerpc/include/asm/irqhost.h
 delete mode 100644 arch/x86/include/asm/irq_controller.h

^ permalink raw reply

* Re: device not available because of BAR 0 collisions
From: Steven A. Falco @ 2011-04-28 17:29 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <4DB873B6.1000809@harris.com>

On 04/27/2011 03:51 PM, Steven A. Falco wrote:
> On 04/26/2011 07:39 PM, Benjamin Herrenschmidt wrote:
>> On Tue, 2011-04-26 at 09:38 -0400, Steven A. Falco wrote:
>>> On 04/25/2011 08:01 PM, Benjamin Herrenschmidt wrote:
>>>> On Mon, 2011-04-25 at 16:10 -0400, Steven A. Falco wrote:
>>>>> I'm getting an error message when trying to talk to some custom
>>>>> hardware:
>>>>>
>>>>> dx83xx 0001:43:00.0: device not available because of BAR 0
>>>>> [0xa1000000-0xa1ffffff] collisions

I believe I've gotten to the root cause of this issue.  Turns out the
ASIC is reporting a class code of 0000, in violation of the PCI spec.

As a result, Linux is refusing to set up the ASIC, and so it remains
with the settings made in U-Boot, which are in conflict with the
allocation Linux makes for the bridge the ASIC is connected to.

So Ben, you are absolutely right that there was some left-over
configuration.

My choices appear to be:

1) Fix the ASIC (yeah, right)

2) Force Linux to use the U-Boot settings

3) Hack Linux to set up a device with a bogus class.

I'm not sure why this hardware works in x86 - I guess it is less
fussy.

	Steve

>>>>>
>>>>> I see in setup-res.c that this message comes out when there is no
>>>>> parent for
>>>>> a device resource.
>>>>
>>>>  .../...
>>>>
>>>> It mostly happens in arch/powerpc/kernel/pci-common.c and the generic
>>>> setup-res.c
>>>>
>>>> Try #define DEBUG at the top (before the #includes) of pci-common.c and
>>>> pci_32.c (remove the exiting #undef in the last one) and send us the
>>>> full dmesg log, along with the output of cat /proc/iomem
>>
>> Have you set any specific flags ? IE. Modified the value of
>> ppc_pci_flags from what the 4xx code sets originally ?
> 
> For fun, I just tried changing:
> 
> ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
> 
> to:
> 
> ppc_pci_set_flags(PPC_PCI_PROBE_ONLY);
> 
> I realize that is the exact opposite of what you were suggesting, but
> please bear with me for a bit.
> 
> I also changed the PCIE 0 ranges from:
> 
> ranges = <0x02000000 0x00000000 0x80000000 0x90000000 0x00000000 0x10000000
>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
> 
> ranges = <0x02000000 0x00000000 0x90000000 0x90000000 0x00000000 0x10000000
>           0x01000000 0x00000000 0x00000000 0xe8010000 0x00000000 0x00010000>;
> 
> I changed the ranges not because I wanted a 1:1 map, but because 90000000 is
> what U-Boot chooses when it scans PCIe 1.
> 
> At this point, everything is working.  Here is /proc/iomap:
> 
> 90000000-9fffffff : /plb/pciex@0c0000000
>   90000000-94ffffff : PCI Bus 0001:41
>     90000000-9001ffff : 0001:41:00.0
>     90100000-94ffffff : PCI Bus 0001:42
>       90100000-92ffffff : PCI Bus 0001:43
>         91000000-91ffffff : 0001:43:00.0  //<--- was missing before
>         92000000-92ffffff : 0001:43:00.0  //<--- was missing before
>       93000000-94ffffff : PCI Bus 0001:44
>         93000000-93ffffff : 0001:44:00.0  //<--- was missing before
>         94000000-94ffffff : 0001:44:00.0  //<--- was missing before
> e0000000-e7ffffff : /plb/pciex@0a0000000
>   e0000000-e7ffffff : PCI Bus 0000:01
>     e0000000-e00fffff : 0000:01:00.0
>     e0100000-e01fffff : 0000:01:00.0
>     e4000000-e7ffffff : 0000:01:00.0
> ef600200-ef600207 : serial
> ef600300-ef600307 : serial
> ef600600-ef600606 : spi_ppc4xx_of
> ef6c0000-ef6cffff : dwc_otg.0
>   ef6c0000-ef6cffff : dwc_otg
> fc000000-ffffffff : fc000000.nor_flash
> 
> Now I see the bars for the ASICs (flagged above).  I could stop here,
> and declare success, but I don't really like this solution, because it
> requires me to be sure the dts has the same bus addresses that U-Boot
> will choose.  Seems risky.
> 
> Tentative conclusion:  Either I still have something set wrong in my dts
> or there is a bug in the Linux PCI bus mapping code.
> 
> 	Steve
> 
>>
>> It does look to me like some of your device BARs have been setup already
>> by the firmware in a way that conflict with the way you configure your
>> ranges, and the kernel doesn't appear to detect nor try to remap that
>> which would happen if you have the "probe only" flag set.
>>
>> IE. On your c0000000 bus, you have memory at 90000000 CPU space mapped
>> to 80000000 PCI space. However, when probing, the kernel finds:
>>
>> pci 0001:41:00.0: reg 10 32bit mmio: [0x90000000-0x9001ffff]
>>
>> IE. A BAR was already set with a value of 90000000 PCI-side which is out
>> of the bounds you have for your bus.
>>
>> Maybe you really want to configure that second bus to have CPU 90000000
>> mapped to 90000000 PCI-side ? (IE. a 1:1 mapping). That would be
>> something to fix in your "ranges" property.
>>
>> Cheers,
>> Ben.
> 
> 


-- 
A: Because it makes the logic of the discussion difficult to follow.
Q: Why shouldn't I top post?
A: No.
Q: Should I top post?

^ permalink raw reply

* Re: [PATCH] powerpc/44x: Add multiple chip select support to NDFC driver
From: Artem Bityutskiy @ 2011-04-28 17:08 UTC (permalink / raw)
  To: Felix Radensky; +Cc: linux-mtd, sr, linuxppc-dev
In-Reply-To: <1303810606-2068-1-git-send-email-felix@embedded-sol.com>

On Tue, 2011-04-26 at 12:36 +0300, Felix Radensky wrote:
> This patch extends NDFC driver to support all 4 chip selects
> available in NDFC NAND controller. Tested on custom 460EX board
> with 2 chip select NAND device.
> 
> Signed-off-by: Felix Radensky <felix@embedded-sol.com>
> ---
> 
> I'd appreciate some testing on 44x boards with multiple NAND
> devices, like bamboo or DU440, as I don't have access to these 
> boards.
> 
>  drivers/mtd/nand/ndfc.c |   52 +++++++++++++++++++++++++++++++---------------
>  1 files changed, 35 insertions(+), 17 deletions(-)

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

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

^ permalink raw reply

* [PATCH] powerpc: convert old cpumask API into new one
From: KOSAKI Motohiro @ 2011-04-28 15:07 UTC (permalink / raw)
  To: LKML, Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev
  Cc: kosaki.motohiro

Adapt new API.

Almost change is trivial. Most important change is the below line
because we plan to change task->cpus_allowed implementation.

-       ctx->cpus_allowed = current->cpus_allowed;

Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: linuxppc-dev@lists.ozlabs.org
---
 arch/powerpc/include/asm/cputhreads.h        |   12 +++++-----
 arch/powerpc/include/asm/kexec.h             |    2 +-
 arch/powerpc/kernel/crash.c                  |   32 +++++++++++++-------------
 arch/powerpc/kernel/setup-common.c           |    4 +-
 arch/powerpc/kernel/smp.c                    |    4 +-
 arch/powerpc/kernel/traps.c                  |    2 +-
 arch/powerpc/mm/numa.c                       |    2 +-
 arch/powerpc/platforms/cell/beat_smp.c       |    2 +-
 arch/powerpc/platforms/cell/cbe_regs.c       |   11 +++++----
 arch/powerpc/platforms/cell/smp.c            |   13 +++++-----
 arch/powerpc/platforms/cell/spufs/sched.c    |    2 +-
 arch/powerpc/platforms/pseries/hotplug-cpu.c |    2 +-
 arch/powerpc/xmon/xmon.c                     |   16 ++++++------
 13 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h
index f71bb4c..ce516e5 100644
--- a/arch/powerpc/include/asm/cputhreads.h
+++ b/arch/powerpc/include/asm/cputhreads.h
@@ -37,16 +37,16 @@ extern cpumask_t threads_core_mask;
  * This can typically be used for things like IPI for tlb invalidations
  * since those need to be done only once per core/TLB
  */
-static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
+static inline cpumask_t cpu_thread_mask_to_cores(const struct cpumask *threads)
 {
 	cpumask_t	tmp, res;
 	int		i;
 
-	res = CPU_MASK_NONE;
+	cpumask_clear(&res);
 	for (i = 0; i < NR_CPUS; i += threads_per_core) {
-		cpus_shift_left(tmp, threads_core_mask, i);
-		if (cpus_intersects(threads, tmp))
-			cpu_set(i, res);
+		cpumask_shift_left(&tmp, &threads_core_mask, i);
+		if (cpumask_intersects(threads, &tmp))
+			cpumask_set_cpu(i, &res);
 	}
 	return res;
 }
@@ -58,7 +58,7 @@ static inline int cpu_nr_cores(void)
 
 static inline cpumask_t cpu_online_cores_map(void)
 {
-	return cpu_thread_mask_to_cores(cpu_online_map);
+	return cpu_thread_mask_to_cores(cpu_online_mask);
 }
 
 #ifdef CONFIG_SMP
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index f54408d..8a33698 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -76,7 +76,7 @@ extern void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *));
 extern cpumask_t cpus_in_sr;
 static inline int kexec_sr_activated(int cpu)
 {
-	return cpu_isset(cpu,cpus_in_sr);
+	return cpumask_test_cpu(cpu, &cpus_in_sr);
 }
 
 struct kimage;
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 3d3d416..88e294f 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -64,9 +64,9 @@ void crash_ipi_callback(struct pt_regs *regs)
 		return;
 
 	hard_irq_disable();
-	if (!cpu_isset(cpu, cpus_in_crash))
+	if (!cpumask_test_cpu(cpu, &cpus_in_crash))
 		crash_save_cpu(regs, cpu);
-	cpu_set(cpu, cpus_in_crash);
+	cpumask_set_cpu(cpu, &cpus_in_crash);
 
 	/*
 	 * Entered via soft-reset - could be the kdump
@@ -77,8 +77,8 @@ void crash_ipi_callback(struct pt_regs *regs)
 	 * Tell the kexec CPU that entered via soft-reset and ready
 	 * to go down.
 	 */
-	if (cpu_isset(cpu, cpus_in_sr)) {
-		cpu_clear(cpu, cpus_in_sr);
+	if (cpumask_test_cpu(cpu, &cpus_in_sr)) {
+		cpumask_clear_cpu(cpu, &cpus_in_sr);
 		atomic_inc(&enter_on_soft_reset);
 	}
 
@@ -87,7 +87,7 @@ void crash_ipi_callback(struct pt_regs *regs)
 	 * This barrier is needed to make sure that all CPUs are stopped.
 	 * If not, soft-reset will be invoked to bring other CPUs.
 	 */
-	while (!cpu_isset(crashing_cpu, cpus_in_crash))
+	while (!cpumask_test_cpu(crashing_cpu, &cpus_in_crash))
 		cpu_relax();
 
 	if (ppc_md.kexec_cpu_down)
@@ -109,7 +109,7 @@ static void crash_soft_reset_check(int cpu)
 {
 	unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
 
-	cpu_clear(cpu, cpus_in_sr);
+	cpumask_clear_cpu(cpu, &cpus_in_sr);
 	while (atomic_read(&enter_on_soft_reset) != ncpus)
 		cpu_relax();
 }
@@ -132,7 +132,7 @@ static void crash_kexec_prepare_cpus(int cpu)
 	 */
 	printk(KERN_EMERG "Sending IPI to other cpus...\n");
 	msecs = 10000;
-	while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+	while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) {
 		cpu_relax();
 		mdelay(1);
 	}
@@ -144,20 +144,20 @@ static void crash_kexec_prepare_cpus(int cpu)
 	 * user to do soft reset such that we get all.
 	 * Soft-reset will be used until better mechanism is implemented.
 	 */
-	if (cpus_weight(cpus_in_crash) < ncpus) {
+	if (cpumask_weight(&cpus_in_crash) < ncpus) {
 		printk(KERN_EMERG "done waiting: %d cpu(s) not responding\n",
-			ncpus - cpus_weight(cpus_in_crash));
+			ncpus - cpumask_weight(&cpus_in_crash));
 		printk(KERN_EMERG "Activate soft-reset to stop other cpu(s)\n");
-		cpus_in_sr = CPU_MASK_NONE;
+		cpumask_clear(&cpus_in_sr);
 		atomic_set(&enter_on_soft_reset, 0);
-		while (cpus_weight(cpus_in_crash) < ncpus)
+		while (cpumask_weight(&cpus_in_crash) < ncpus)
 			cpu_relax();
 	}
 	/*
 	 * Make sure all CPUs are entered via soft-reset if the kdump is
 	 * invoked using soft-reset.
 	 */
-	if (cpu_isset(cpu, cpus_in_sr))
+	if (cpumask_test_cpu(cpu, &cpus_in_sr))
 		crash_soft_reset_check(cpu);
 	/* Leave the IPI callback set */
 }
@@ -212,7 +212,7 @@ void crash_kexec_secondary(struct pt_regs *regs)
 			 * exited using 'x'(exit and recover) or
 			 * kexec_should_crash() failed for all running tasks.
 			 */
-			cpu_clear(cpu, cpus_in_sr);
+			cpumask_clear_cpu(cpu, &cpus_in_sr);
 			local_irq_restore(flags);
 			return;
 		}
@@ -226,7 +226,7 @@ void crash_kexec_secondary(struct pt_regs *regs)
 		 * then start kexec boot.
 		 */
 		crash_soft_reset_check(cpu);
-		cpu_set(crashing_cpu, cpus_in_crash);
+		cpumask_set_cpu(crashing_cpu, &cpus_in_crash);
 		if (ppc_md.kexec_cpu_down)
 			ppc_md.kexec_cpu_down(1, 0);
 		machine_kexec(kexec_crash_image);
@@ -253,7 +253,7 @@ static void crash_kexec_prepare_cpus(int cpu)
 
 void crash_kexec_secondary(struct pt_regs *regs)
 {
-	cpus_in_sr = CPU_MASK_NONE;
+	cpumask_clear(&cpus_in_sr);
 }
 #endif
 
@@ -345,7 +345,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
 	crashing_cpu = smp_processor_id();
 	crash_save_cpu(regs, crashing_cpu);
 	crash_kexec_prepare_cpus(crashing_cpu);
-	cpu_set(crashing_cpu, cpus_in_crash);
+	cpumask_set_cpu(crashing_cpu, &cpus_in_crash);
 	crash_kexec_wait_realmode(crashing_cpu);
 
 	machine_kexec_mask_interrupts();
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 21f30cb..1475df6 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -381,7 +381,7 @@ static void __init cpu_init_thread_core_maps(int tpc)
 	int i;
 
 	threads_per_core = tpc;
-	threads_core_mask = CPU_MASK_NONE;
+	cpumask_clear(&threads_core_mask);
 
 	/* This implementation only supports power of 2 number of threads
 	 * for simplicity and performance
@@ -390,7 +390,7 @@ static void __init cpu_init_thread_core_maps(int tpc)
 	BUG_ON(tpc != (1 << threads_shift));
 
 	for (i = 0; i < tpc; i++)
-		cpu_set(i, threads_core_mask);
+		cpumask_set_cpu(i, &threads_core_mask);
 
 	printk(KERN_INFO "CPU maps initialized for %d thread%s per core\n",
 	       tpc, tpc > 1 ? "s" : "");
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9f9c204..da584a9 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -507,7 +507,7 @@ int cpu_first_thread_of_core(int core)
 }
 EXPORT_SYMBOL_GPL(cpu_first_thread_of_core);
 
-/* Must be called when no change can occur to cpu_present_map,
+/* Must be called when no change can occur to cpu_present_mask,
  * i.e. during cpu online or offline.
  */
 static struct device_node *cpu_to_l2cache(int cpu)
@@ -608,7 +608,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
 	 * se we pin us down to CPU 0 for a short while
 	 */
 	alloc_cpumask_var(&old_mask, GFP_NOWAIT);
-	cpumask_copy(old_mask, &current->cpus_allowed);
+	cpumask_copy(old_mask, tsk_cpus_allowed(current));
 	set_cpus_allowed_ptr(current, cpumask_of(boot_cpuid));
 	
 	if (smp_ops && smp_ops->setup_cpu)
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5ddb801..af1f8f4 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -221,7 +221,7 @@ void system_reset_exception(struct pt_regs *regs)
 	}
 
 #ifdef CONFIG_KEXEC
-	cpu_set(smp_processor_id(), cpus_in_sr);
+	cpumask_set_cpu(smp_processor_id(), &cpus_in_sr);
 #endif
 
 	die("System Reset", regs, SIGABRT);
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 5ec1dad..d6cc587 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1453,7 +1453,7 @@ int arch_update_cpu_topology(void)
 	unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
 	struct sys_device *sysdev;
 
-	for_each_cpu_mask(cpu, cpu_associativity_changes_mask) {
+	for_each_cpu(cpu,&cpu_associativity_changes_mask) {
 		vphn_get_associativity(cpu, associativity);
 		nid = associativity_to_nid(associativity);
 
diff --git a/arch/powerpc/platforms/cell/beat_smp.c b/arch/powerpc/platforms/cell/beat_smp.c
index 26efc20..fd3cdb4 100644
--- a/arch/powerpc/platforms/cell/beat_smp.c
+++ b/arch/powerpc/platforms/cell/beat_smp.c
@@ -85,7 +85,7 @@ static void smp_beatic_message_pass(int target, int msg)
 
 static int __init smp_beatic_probe(void)
 {
-	return cpus_weight(cpu_possible_map);
+	return cpumask_weight(cpu_possible_mask);
 }
 
 static void __devinit smp_beatic_setup_cpu(int cpu)
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index dbc338f..f3917e7 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -45,8 +45,8 @@ static struct cbe_thread_map
 	unsigned int cbe_id;
 } cbe_thread_map[NR_CPUS];
 
-static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE };
-static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE;
+static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = {CPU_BITS_NONE} };
+static cpumask_t cbe_first_online_cpu = { CPU_BITS_NONE };
 
 static struct cbe_regs_map *cbe_find_map(struct device_node *np)
 {
@@ -159,7 +159,8 @@ EXPORT_SYMBOL_GPL(cbe_cpu_to_node);
 
 u32 cbe_node_to_cpu(int node)
 {
-	return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t));
+	return cpumask_first(&cbe_local_mask[node]);
+
 }
 EXPORT_SYMBOL_GPL(cbe_node_to_cpu);
 
@@ -268,9 +269,9 @@ void __init cbe_regs_init(void)
 				thread->regs = map;
 				thread->cbe_id = cbe_id;
 				map->be_node = thread->be_node;
-				cpu_set(i, cbe_local_mask[cbe_id]);
+				cpumask_set_cpu(i, &cbe_local_mask[cbe_id]);
 				if(thread->thread_id == 0)
-					cpu_set(i, cbe_first_online_cpu);
+					cpumask_set_cpu(i, &cbe_first_online_cpu);
 			}
 		}
 
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index f774530..56e8fa0 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -77,7 +77,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 	unsigned int pcpu;
 	int start_cpu;
 
-	if (cpu_isset(lcpu, of_spin_map))
+	if (cpumask_test_cpu(lcpu, &of_spin_map))
 		/* Already started by OF and sitting in spin loop */
 		return 1;
 
@@ -123,7 +123,7 @@ static int __init smp_iic_probe(void)
 {
 	iic_request_IPIs();
 
-	return cpus_weight(cpu_possible_map);
+	return cpumask_weight(cpu_possible_mask);
 }
 
 static void __devinit smp_cell_setup_cpu(int cpu)
@@ -186,13 +186,12 @@ void __init smp_init_cell(void)
 	if (cpu_has_feature(CPU_FTR_SMT)) {
 		for_each_present_cpu(i) {
 			if (cpu_thread_in_core(i) == 0)
-				cpu_set(i, of_spin_map);
+				cpumask_set_cpu(i, &of_spin_map);
 		}
-	} else {
-		of_spin_map = cpu_present_map;
-	}
+	} else
+		cpumask_copy(&of_spin_map, cpu_present_mask);
 
-	cpu_clear(boot_cpuid, of_spin_map);
+	cpumask_clear_cpu(boot_cpuid, &of_spin_map);
 
 	/* Non-lpar has additional take/give timebase */
 	if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 6520385..32cb4e6 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -141,7 +141,7 @@ void __spu_update_sched_info(struct spu_context *ctx)
 	 * runqueue. The context will be rescheduled on the proper node
 	 * if it is timesliced or preempted.
 	 */
-	ctx->cpus_allowed = current->cpus_allowed;
+	cpumask_copy(&ctx->cpus_allowed, tsk_cpus_allowed(current));
 
 	/* Save the current cpu id for spu interrupt routing. */
 	ctx->last_ran = raw_smp_processor_id();
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index ef8c454..7be7c20 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -280,7 +280,7 @@ static int pseries_add_processor(struct device_node *np)
 	}
 
 	for_each_cpu(cpu, tmp) {
-		BUG_ON(cpumask_test_cpu(cpu, cpu_present_mask));
+		BUG_ON(cpu_present(cpu));
 		set_cpu_present(cpu, true);
 		set_hard_smp_processor_id(cpu, *intserv++);
 	}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 33794c1..c160361 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -334,7 +334,7 @@ static void release_output_lock(void)
 
 int cpus_are_in_xmon(void)
 {
-	return !cpus_empty(cpus_in_xmon);
+	return !cpumask_empty(&cpus_in_xmon);
 }
 #endif
 
@@ -373,7 +373,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
 
 #ifdef CONFIG_SMP
 	cpu = smp_processor_id();
-	if (cpu_isset(cpu, cpus_in_xmon)) {
+	if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
 		get_output_lock();
 		excprint(regs);
 		printf("cpu 0x%x: Exception %lx %s in xmon, "
@@ -396,7 +396,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
 	}
 
 	xmon_fault_jmp[cpu] = recurse_jmp;
-	cpu_set(cpu, cpus_in_xmon);
+	cpumask_set_cpu(cpu, &cpus_in_xmon);
 
 	bp = NULL;
 	if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) == (MSR_IR|MSR_SF))
@@ -440,7 +440,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
 			smp_send_debugger_break(MSG_ALL_BUT_SELF);
 			/* wait for other cpus to come in */
 			for (timeout = 100000000; timeout != 0; --timeout) {
-				if (cpus_weight(cpus_in_xmon) >= ncpus)
+				if (cpumask_weight(&cpus_in_xmon) >= ncpus)
 					break;
 				barrier();
 			}
@@ -484,7 +484,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
 		}
 	}
  leave:
-	cpu_clear(cpu, cpus_in_xmon);
+	cpumask_clear_cpu(cpu, &cpus_in_xmon);
 	xmon_fault_jmp[cpu] = NULL;
 #else
 	/* UP is simple... */
@@ -630,7 +630,7 @@ static int xmon_iabr_match(struct pt_regs *regs)
 static int xmon_ipi(struct pt_regs *regs)
 {
 #ifdef CONFIG_SMP
-	if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
+	if (in_xmon && !cpumask_test_cpu(smp_processor_id(), &cpus_in_xmon))
 		xmon_core(regs, 1);
 #endif
 	return 0;
@@ -976,7 +976,7 @@ static int cpu_cmd(void)
 		printf("cpus stopped:");
 		count = 0;
 		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
-			if (cpu_isset(cpu, cpus_in_xmon)) {
+			if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
 				if (count == 0)
 					printf(" %x", cpu);
 				++count;
@@ -992,7 +992,7 @@ static int cpu_cmd(void)
 		return 0;
 	}
 	/* try to switch to cpu specified */
-	if (!cpu_isset(cpu, cpus_in_xmon)) {
+	if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
 		printf("cpu 0x%x isn't in xmon\n", cpu);
 		return 0;
 	}
-- 
1.7.3.1

^ permalink raw reply related

* Re: [PATCH] powerpc: convert old cpumask API into new one
From: KOSAKI Motohiro @ 2011-04-28 15:25 UTC (permalink / raw)
  To: Thiago Farina; +Cc: linuxppc-dev, Paul Mackerras, LKML, kosaki.motohiro
In-Reply-To: <BANLkTi=EvC6E_p+XSpzZUvhu0Q_gStROcQ@mail.gmail.com>

> > @@ -268,9 +269,9 @@ void __init cbe_regs_init(void)
> >                                thread->regs = map;
> >                                thread->cbe_id = cbe_id;
> >                                map->be_node = thread->be_node;
> > -                               cpu_set(i, cbe_local_mask[cbe_id]);
> > +                               cpumask_set_cpu(i, &cbe_local_mask[cbe_id]);
> >                                if(thread->thread_id == 0)
> while you are here, could you add a space between if and ( ?


Oh, this is NOT a part of my change. I don't want to insert unrelated
cleanup.

^ permalink raw reply

* Re: [PATCH] powerpc: convert old cpumask API into new one
From: Thiago Farina @ 2011-04-28 15:19 UTC (permalink / raw)
  To: KOSAKI Motohiro; +Cc: linuxppc-dev, Paul Mackerras, LKML
In-Reply-To: <20110429000901.3D66.A69D9226@jp.fujitsu.com>

On Thu, Apr 28, 2011 at 12:07 PM, KOSAKI Motohiro
<kosaki.motohiro@jp.fujitsu.com> wrote:
> Adapt new API.
>
> Almost change is trivial. Most important change is the below line
> because we plan to change task->cpus_allowed implementation.
>
> - =C2=A0 =C2=A0 =C2=A0 ctx->cpus_allowed =3D current->cpus_allowed;
>
> Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: linuxppc-dev@lists.ozlabs.org
> ---
> =C2=A0arch/powerpc/include/asm/cputhreads.h =C2=A0 =C2=A0 =C2=A0 =C2=A0| =
=C2=A0 12 +++++-----
> =C2=A0arch/powerpc/include/asm/kexec.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 | =C2=A0 =C2=A02 +-
> =C2=A0arch/powerpc/kernel/crash.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 32 +++++++++++++-------------
> =C2=A0arch/powerpc/kernel/setup-common.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 | =C2=A0 =C2=A04 +-
> =C2=A0arch/powerpc/kernel/smp.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 =C2=A04 +-
> =C2=A0arch/powerpc/kernel/traps.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0| =C2=A0 =C2=A02 +-
> =C2=A0arch/powerpc/mm/numa.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A02 +-
> =C2=A0arch/powerpc/platforms/cell/beat_smp.c =C2=A0 =C2=A0 =C2=A0 | =C2=
=A0 =C2=A02 +-
> =C2=A0arch/powerpc/platforms/cell/cbe_regs.c =C2=A0 =C2=A0 =C2=A0 | =C2=
=A0 11 +++++----
> =C2=A0arch/powerpc/platforms/cell/smp.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0| =C2=A0 13 +++++-----
> =C2=A0arch/powerpc/platforms/cell/spufs/sched.c =C2=A0 =C2=A0| =C2=A0 =C2=
=A02 +-
> =C2=A0arch/powerpc/platforms/pseries/hotplug-cpu.c | =C2=A0 =C2=A02 +-
> =C2=A0arch/powerpc/xmon/xmon.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 16 ++++++------
> =C2=A013 files changed, 52 insertions(+), 52 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include=
/asm/cputhreads.h
> index f71bb4c..ce516e5 100644
> --- a/arch/powerpc/include/asm/cputhreads.h
> +++ b/arch/powerpc/include/asm/cputhreads.h
> @@ -37,16 +37,16 @@ extern cpumask_t threads_core_mask;
> =C2=A0* This can typically be used for things like IPI for tlb invalidati=
ons
> =C2=A0* since those need to be done only once per core/TLB
> =C2=A0*/
> -static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
> +static inline cpumask_t cpu_thread_mask_to_cores(const struct cpumask *t=
hreads)
> =C2=A0{
> =C2=A0 =C2=A0 =C2=A0 =C2=A0cpumask_t =C2=A0 =C2=A0 =C2=A0 tmp, res;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0int =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
i;
>
> - =C2=A0 =C2=A0 =C2=A0 res =3D CPU_MASK_NONE;
> + =C2=A0 =C2=A0 =C2=A0 cpumask_clear(&res);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i < NR_CPUS; i +=3D threads_per_=
core) {
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpus_shift_left(tmp, t=
hreads_core_mask, i);
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (cpus_intersects(th=
reads, tmp))
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 cpu_set(i, res);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_shift_left(&tm=
p, &threads_core_mask, i);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (cpumask_intersects=
(threads, &tmp))
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 cpumask_set_cpu(i, &res);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> =C2=A0 =C2=A0 =C2=A0 =C2=A0return res;
> =C2=A0}
> @@ -58,7 +58,7 @@ static inline int cpu_nr_cores(void)
>
> =C2=A0static inline cpumask_t cpu_online_cores_map(void)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 return cpu_thread_mask_to_cores(cpu_online_map);
> + =C2=A0 =C2=A0 =C2=A0 return cpu_thread_mask_to_cores(cpu_online_mask);
> =C2=A0}
>
> =C2=A0#ifdef CONFIG_SMP
> diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/=
kexec.h
> index f54408d..8a33698 100644
> --- a/arch/powerpc/include/asm/kexec.h
> +++ b/arch/powerpc/include/asm/kexec.h
> @@ -76,7 +76,7 @@ extern void crash_send_ipi(void (*crash_ipi_callback)(s=
truct pt_regs *));
> =C2=A0extern cpumask_t cpus_in_sr;
> =C2=A0static inline int kexec_sr_activated(int cpu)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 return cpu_isset(cpu,cpus_in_sr);
> + =C2=A0 =C2=A0 =C2=A0 return cpumask_test_cpu(cpu, &cpus_in_sr);
> =C2=A0}
>
> =C2=A0struct kimage;
> diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
> index 3d3d416..88e294f 100644
> --- a/arch/powerpc/kernel/crash.c
> +++ b/arch/powerpc/kernel/crash.c
> @@ -64,9 +64,9 @@ void crash_ipi_callback(struct pt_regs *regs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return;
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0hard_irq_disable();
> - =C2=A0 =C2=A0 =C2=A0 if (!cpu_isset(cpu, cpus_in_crash))
> + =C2=A0 =C2=A0 =C2=A0 if (!cpumask_test_cpu(cpu, &cpus_in_crash))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0crash_save_cpu(reg=
s, cpu);
> - =C2=A0 =C2=A0 =C2=A0 cpu_set(cpu, cpus_in_crash);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(cpu, &cpus_in_crash);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/*
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * Entered via soft-reset - could be the kdump
> @@ -77,8 +77,8 @@ void crash_ipi_callback(struct pt_regs *regs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * Tell the kexec CPU that entered via soft-re=
set and ready
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * to go down.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> - =C2=A0 =C2=A0 =C2=A0 if (cpu_isset(cpu, cpus_in_sr)) {
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_clear(cpu, cpus_in=
_sr);
> + =C2=A0 =C2=A0 =C2=A0 if (cpumask_test_cpu(cpu, &cpus_in_sr)) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_clear_cpu(cpu,=
 &cpus_in_sr);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0atomic_inc(&enter_=
on_soft_reset);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>
> @@ -87,7 +87,7 @@ void crash_ipi_callback(struct pt_regs *regs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * This barrier is needed to make sure that al=
l CPUs are stopped.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * If not, soft-reset will be invoked to bring=
 other CPUs.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> - =C2=A0 =C2=A0 =C2=A0 while (!cpu_isset(crashing_cpu, cpus_in_crash))
> + =C2=A0 =C2=A0 =C2=A0 while (!cpumask_test_cpu(crashing_cpu, &cpus_in_cr=
ash))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_relax();
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0if (ppc_md.kexec_cpu_down)
> @@ -109,7 +109,7 @@ static void crash_soft_reset_check(int cpu)
> =C2=A0{
> =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned int ncpus =3D num_online_cpus() - 1;/=
* Excluding the panic cpu */
>
> - =C2=A0 =C2=A0 =C2=A0 cpu_clear(cpu, cpus_in_sr);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_clear_cpu(cpu, &cpus_in_sr);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0while (atomic_read(&enter_on_soft_reset) !=3D =
ncpus)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_relax();
> =C2=A0}
> @@ -132,7 +132,7 @@ static void crash_kexec_prepare_cpus(int cpu)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0printk(KERN_EMERG "Sending IPI to other cpus..=
.\n");
> =C2=A0 =C2=A0 =C2=A0 =C2=A0msecs =3D 10000;
> - =C2=A0 =C2=A0 =C2=A0 while ((cpus_weight(cpus_in_crash) < ncpus) && (--=
msecs > 0)) {
> + =C2=A0 =C2=A0 =C2=A0 while ((cpumask_weight(&cpus_in_crash) < ncpus) &&=
 (--msecs > 0)) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_relax();
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0mdelay(1);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> @@ -144,20 +144,20 @@ static void crash_kexec_prepare_cpus(int cpu)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * user to do soft reset such that we get all.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * Soft-reset will be used until better mechan=
ism is implemented.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> - =C2=A0 =C2=A0 =C2=A0 if (cpus_weight(cpus_in_crash) < ncpus) {
> + =C2=A0 =C2=A0 =C2=A0 if (cpumask_weight(&cpus_in_crash) < ncpus) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printk(KERN_EMERG =
"done waiting: %d cpu(s) not responding\n",
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 ncpus - cpus_weight(cpus_in_crash));
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 ncpus - cpumask_weight(&cpus_in_crash));
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printk(KERN_EMERG =
"Activate soft-reset to stop other cpu(s)\n");
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpus_in_sr =3D CPU_MAS=
K_NONE;
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_clear(&cpus_in=
_sr);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0atomic_set(&enter_=
on_soft_reset, 0);
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 while (cpus_weight(cpu=
s_in_crash) < ncpus)
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 while (cpumask_weight(=
&cpus_in_crash) < ncpus)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0cpu_relax();
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/*
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * Make sure all CPUs are entered via soft-res=
et if the kdump is
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * invoked using soft-reset.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> - =C2=A0 =C2=A0 =C2=A0 if (cpu_isset(cpu, cpus_in_sr))
> + =C2=A0 =C2=A0 =C2=A0 if (cpumask_test_cpu(cpu, &cpus_in_sr))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0crash_soft_reset_c=
heck(cpu);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Leave the IPI callback set */
> =C2=A0}
> @@ -212,7 +212,7 @@ void crash_kexec_secondary(struct pt_regs *regs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 * exited using 'x'(exit and recover) or
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 * kexec_should_crash() failed for all running tasks.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 */
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 cpu_clear(cpu, cpus_in_sr);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 cpumask_clear_cpu(cpu, &cpus_in_sr);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0local_irq_restore(flags);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0return;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> @@ -226,7 +226,7 @@ void crash_kexec_secondary(struct pt_regs *regs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * then start kexe=
c boot.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0crash_soft_reset_c=
heck(cpu);
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_set(crashing_cpu, =
cpus_in_crash);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(crashi=
ng_cpu, &cpus_in_crash);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (ppc_md.kexec_c=
pu_down)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0ppc_md.kexec_cpu_down(1, 0);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0machine_kexec(kexe=
c_crash_image);
> @@ -253,7 +253,7 @@ static void crash_kexec_prepare_cpus(int cpu)
>
> =C2=A0void crash_kexec_secondary(struct pt_regs *regs)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 cpus_in_sr =3D CPU_MASK_NONE;
> + =C2=A0 =C2=A0 =C2=A0 cpumask_clear(&cpus_in_sr);
> =C2=A0}
> =C2=A0#endif
>
> @@ -345,7 +345,7 @@ void default_machine_crash_shutdown(struct pt_regs *r=
egs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0crashing_cpu =3D smp_processor_id();
> =C2=A0 =C2=A0 =C2=A0 =C2=A0crash_save_cpu(regs, crashing_cpu);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0crash_kexec_prepare_cpus(crashing_cpu);
> - =C2=A0 =C2=A0 =C2=A0 cpu_set(crashing_cpu, cpus_in_crash);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(crashing_cpu, &cpus_in_crash);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0crash_kexec_wait_realmode(crashing_cpu);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0machine_kexec_mask_interrupts();
> diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/set=
up-common.c
> index 21f30cb..1475df6 100644
> --- a/arch/powerpc/kernel/setup-common.c
> +++ b/arch/powerpc/kernel/setup-common.c
> @@ -381,7 +381,7 @@ static void __init cpu_init_thread_core_maps(int tpc)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0int i;
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0threads_per_core =3D tpc;
> - =C2=A0 =C2=A0 =C2=A0 threads_core_mask =3D CPU_MASK_NONE;
> + =C2=A0 =C2=A0 =C2=A0 cpumask_clear(&threads_core_mask);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/* This implementation only supports power of =
2 number of threads
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * for simplicity and performance
> @@ -390,7 +390,7 @@ static void __init cpu_init_thread_core_maps(int tpc)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0BUG_ON(tpc !=3D (1 << threads_shift));
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i < tpc; i++)
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_set(i, threads_cor=
e_mask);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(i, &th=
reads_core_mask);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0printk(KERN_INFO "CPU maps initialized for %d =
thread%s per core\n",
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 tpc, tpc > 1 ? "s" : "")=
;
> diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
> index 9f9c204..da584a9 100644
> --- a/arch/powerpc/kernel/smp.c
> +++ b/arch/powerpc/kernel/smp.c
> @@ -507,7 +507,7 @@ int cpu_first_thread_of_core(int core)
> =C2=A0}
> =C2=A0EXPORT_SYMBOL_GPL(cpu_first_thread_of_core);
>
> -/* Must be called when no change can occur to cpu_present_map,
> +/* Must be called when no change can occur to cpu_present_mask,
> =C2=A0* i.e. during cpu online or offline.
> =C2=A0*/
> =C2=A0static struct device_node *cpu_to_l2cache(int cpu)
> @@ -608,7 +608,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * se we pin us down to CPU 0 for a short whil=
e
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0alloc_cpumask_var(&old_mask, GFP_NOWAIT);
> - =C2=A0 =C2=A0 =C2=A0 cpumask_copy(old_mask, &current->cpus_allowed);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_copy(old_mask, tsk_cpus_allowed(current));
> =C2=A0 =C2=A0 =C2=A0 =C2=A0set_cpus_allowed_ptr(current, cpumask_of(boot_=
cpuid));
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0if (smp_ops && smp_ops->setup_cpu)
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index 5ddb801..af1f8f4 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -221,7 +221,7 @@ void system_reset_exception(struct pt_regs *regs)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>
> =C2=A0#ifdef CONFIG_KEXEC
> - =C2=A0 =C2=A0 =C2=A0 cpu_set(smp_processor_id(), cpus_in_sr);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(smp_processor_id(), &cpus_in_sr);
> =C2=A0#endif
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0die("System Reset", regs, SIGABRT);
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index 5ec1dad..d6cc587 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -1453,7 +1453,7 @@ int arch_update_cpu_topology(void)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned int associativity[VPHN_ASSOC_BUFSIZE]=
 =3D {0};
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct sys_device *sysdev;
>
> - =C2=A0 =C2=A0 =C2=A0 for_each_cpu_mask(cpu, cpu_associativity_changes_m=
ask) {
> + =C2=A0 =C2=A0 =C2=A0 for_each_cpu(cpu,&cpu_associativity_changes_mask) =
{
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0vphn_get_associati=
vity(cpu, associativity);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0nid =3D associativ=
ity_to_nid(associativity);
>
> diff --git a/arch/powerpc/platforms/cell/beat_smp.c b/arch/powerpc/platfo=
rms/cell/beat_smp.c
> index 26efc20..fd3cdb4 100644
> --- a/arch/powerpc/platforms/cell/beat_smp.c
> +++ b/arch/powerpc/platforms/cell/beat_smp.c
> @@ -85,7 +85,7 @@ static void smp_beatic_message_pass(int target, int msg=
)
>
> =C2=A0static int __init smp_beatic_probe(void)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 return cpus_weight(cpu_possible_map);
> + =C2=A0 =C2=A0 =C2=A0 return cpumask_weight(cpu_possible_mask);
> =C2=A0}
>
> =C2=A0static void __devinit smp_beatic_setup_cpu(int cpu)
> diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platfo=
rms/cell/cbe_regs.c
> index dbc338f..f3917e7 100644
> --- a/arch/powerpc/platforms/cell/cbe_regs.c
> +++ b/arch/powerpc/platforms/cell/cbe_regs.c
> @@ -45,8 +45,8 @@ static struct cbe_thread_map
> =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned int cbe_id;
> =C2=A0} cbe_thread_map[NR_CPUS];
>
> -static cpumask_t cbe_local_mask[MAX_CBE] =3D { [0 ... MAX_CBE-1] =3D CPU=
_MASK_NONE };
> -static cpumask_t cbe_first_online_cpu =3D CPU_MASK_NONE;
> +static cpumask_t cbe_local_mask[MAX_CBE] =3D { [0 ... MAX_CBE-1] =3D {CP=
U_BITS_NONE} };
> +static cpumask_t cbe_first_online_cpu =3D { CPU_BITS_NONE };
>
> =C2=A0static struct cbe_regs_map *cbe_find_map(struct device_node *np)
> =C2=A0{
> @@ -159,7 +159,8 @@ EXPORT_SYMBOL_GPL(cbe_cpu_to_node);
>
> =C2=A0u32 cbe_node_to_cpu(int node)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 return find_first_bit( (unsigned long *) &cbe_loca=
l_mask[node], sizeof(cpumask_t));
> + =C2=A0 =C2=A0 =C2=A0 return cpumask_first(&cbe_local_mask[node]);
> +
> =C2=A0}
> =C2=A0EXPORT_SYMBOL_GPL(cbe_node_to_cpu);
>
> @@ -268,9 +269,9 @@ void __init cbe_regs_init(void)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0thread->regs =3D map;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0thread->cbe_id =3D cbe_id;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0map->be_node =3D thread->be_node;
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_set(i, cbe_local_mask[cbe_id]);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(i, &cbe_local_mask[cbe_i=
d]);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if(thread->thread_id =3D=3D 0)
while you are here, could you add a space between if and ( ?

> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_set(i, c=
be_first_online_cpu);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_set_=
cpu(i, &cbe_first_online_cpu);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0}
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>
> diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/c=
ell/smp.c
> index f774530..56e8fa0 100644
> --- a/arch/powerpc/platforms/cell/smp.c
> +++ b/arch/powerpc/platforms/cell/smp.c
> @@ -77,7 +77,7 @@ static inline int __devinit smp_startup_cpu(unsigned in=
t lcpu)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0unsigned int pcpu;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0int start_cpu;
>
> - =C2=A0 =C2=A0 =C2=A0 if (cpu_isset(lcpu, of_spin_map))
> + =C2=A0 =C2=A0 =C2=A0 if (cpumask_test_cpu(lcpu, &of_spin_map))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Already started=
 by OF and sitting in spin loop */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;
>
> @@ -123,7 +123,7 @@ static int __init smp_iic_probe(void)
> =C2=A0{
> =C2=A0 =C2=A0 =C2=A0 =C2=A0iic_request_IPIs();
>
> - =C2=A0 =C2=A0 =C2=A0 return cpus_weight(cpu_possible_map);
> + =C2=A0 =C2=A0 =C2=A0 return cpumask_weight(cpu_possible_mask);
> =C2=A0}
>
> =C2=A0static void __devinit smp_cell_setup_cpu(int cpu)
> @@ -186,13 +186,12 @@ void __init smp_init_cell(void)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0if (cpu_has_feature(CPU_FTR_SMT)) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for_each_present_c=
pu(i) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0if (cpu_thread_in_core(i) =3D=3D 0)
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpu_set(i, of_spin_map);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(i, &of_spin_map);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> - =C2=A0 =C2=A0 =C2=A0 } else {
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 of_spin_map =3D cpu_pr=
esent_map;
> - =C2=A0 =C2=A0 =C2=A0 }
> + =C2=A0 =C2=A0 =C2=A0 } else
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cpumask_copy(&of_spin_=
map, cpu_present_mask);
>
> - =C2=A0 =C2=A0 =C2=A0 cpu_clear(boot_cpuid, of_spin_map);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_clear_cpu(boot_cpuid, &of_spin_map);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Non-lpar has additional take/give timebase =
*/
> =C2=A0 =C2=A0 =C2=A0 =C2=A0if (rtas_token("freeze-time-base") !=3D RTAS_U=
NKNOWN_SERVICE) {
> diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/pla=
tforms/cell/spufs/sched.c
> index 6520385..32cb4e6 100644
> --- a/arch/powerpc/platforms/cell/spufs/sched.c
> +++ b/arch/powerpc/platforms/cell/spufs/sched.c
> @@ -141,7 +141,7 @@ void __spu_update_sched_info(struct spu_context *ctx)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * runqueue. The context will be rescheduled o=
n the proper node
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 * if it is timesliced or preempted.
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
> - =C2=A0 =C2=A0 =C2=A0 ctx->cpus_allowed =3D current->cpus_allowed;
> + =C2=A0 =C2=A0 =C2=A0 cpumask_copy(&ctx->cpus_allowed, tsk_cpus_allowed(=
current));
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Save the current cpu id for spu interrupt r=
outing. */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0ctx->last_ran =3D raw_smp_processor_id();
> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/=
platforms/pseries/hotplug-cpu.c
> index ef8c454..7be7c20 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> @@ -280,7 +280,7 @@ static int pseries_add_processor(struct device_node *=
np)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0for_each_cpu(cpu, tmp) {
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 BUG_ON(cpumask_test_cp=
u(cpu, cpu_present_mask));
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 BUG_ON(cpu_present(cpu=
));
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0set_cpu_present(cp=
u, true);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0set_hard_smp_proce=
ssor_id(cpu, *intserv++);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 33794c1..c160361 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -334,7 +334,7 @@ static void release_output_lock(void)
>
> =C2=A0int cpus_are_in_xmon(void)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 return !cpus_empty(cpus_in_xmon);
> + =C2=A0 =C2=A0 =C2=A0 return !cpumask_empty(&cpus_in_xmon);
> =C2=A0}
> =C2=A0#endif
>
> @@ -373,7 +373,7 @@ static int xmon_core(struct pt_regs *regs, int fromip=
i)
>
> =C2=A0#ifdef CONFIG_SMP
> =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu =3D smp_processor_id();
> - =C2=A0 =C2=A0 =C2=A0 if (cpu_isset(cpu, cpus_in_xmon)) {
> + =C2=A0 =C2=A0 =C2=A0 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0get_output_lock();
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0excprint(regs);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("cpu 0x%x: =
Exception %lx %s in xmon, "
> @@ -396,7 +396,7 @@ static int xmon_core(struct pt_regs *regs, int fromip=
i)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0xmon_fault_jmp[cpu] =3D recurse_jmp;
> - =C2=A0 =C2=A0 =C2=A0 cpu_set(cpu, cpus_in_xmon);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_set_cpu(cpu, &cpus_in_xmon);
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0bp =3D NULL;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) =3D=
=3D (MSR_IR|MSR_SF))
> @@ -440,7 +440,7 @@ static int xmon_core(struct pt_regs *regs, int fromip=
i)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0smp_send_debugger_break(MSG_ALL_BUT_SELF);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0/* wait for other cpus to come in */
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0for (timeout =3D 100000000; timeout !=3D 0; --timeout) {
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (cpus_weight(cpus_in_xmon) >=3D ncpus=
)
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (cpumask_weight(&cpus_in_xmon) >=3D n=
cpus)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0break;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0barrier();
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0}
> @@ -484,7 +484,7 @@ static int xmon_core(struct pt_regs *regs, int fromip=
i)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> =C2=A0leave:
> - =C2=A0 =C2=A0 =C2=A0 cpu_clear(cpu, cpus_in_xmon);
> + =C2=A0 =C2=A0 =C2=A0 cpumask_clear_cpu(cpu, &cpus_in_xmon);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0xmon_fault_jmp[cpu] =3D NULL;
> =C2=A0#else
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/* UP is simple... */
> @@ -630,7 +630,7 @@ static int xmon_iabr_match(struct pt_regs *regs)
> =C2=A0static int xmon_ipi(struct pt_regs *regs)
> =C2=A0{
> =C2=A0#ifdef CONFIG_SMP
> - =C2=A0 =C2=A0 =C2=A0 if (in_xmon && !cpu_isset(smp_processor_id(), cpus=
_in_xmon))
> + =C2=A0 =C2=A0 =C2=A0 if (in_xmon && !cpumask_test_cpu(smp_processor_id(=
), &cpus_in_xmon))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0xmon_core(regs, 1)=
;
> =C2=A0#endif
> =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> @@ -976,7 +976,7 @@ static int cpu_cmd(void)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("cpus stopp=
ed:");
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0count =3D 0;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (cpu =3D 0; cp=
u < NR_CPUS; ++cpu) {
> - =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 if (cpu_isset(cpu, cpus_in_xmon)) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (count =3D=3D 0)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf(" =
%x", cpu);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0++count;
> @@ -992,7 +992,7 @@ static int cpu_cmd(void)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> =C2=A0 =C2=A0 =C2=A0 =C2=A0/* try to switch to cpu specified */
> - =C2=A0 =C2=A0 =C2=A0 if (!cpu_isset(cpu, cpus_in_xmon)) {
> + =C2=A0 =C2=A0 =C2=A0 if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("cpu 0x%x i=
sn't in xmon\n", cpu);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0}
> --
> 1.7.3.1
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" i=
n
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =C2=A0http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at =C2=A0http://www.tux.org/lkml/
>

^ permalink raw reply

* Re: [PATCH] PCI: portdrv: fix irq initialization on FSL pcie host controller
From: Xu Lei @ 2011-04-28  8:01 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-pci, kumar.gala, linuxppc-dev
In-Reply-To: <1303458219-31915-1-git-send-email-B33228@freescale.com>


	Any feedback on this patch? Thanks.

On Friday, 2011-04-22 at 15:43 +0800, Lei Xu wrote:
> Root complex ports for Freescale PCIe host controller only receive
> interrupts, so if there is no irq setting for RC, it should not return
> error, otherwise it may result the PCIe host controller is disabled.
> 
> Signed-off-by: Lei Xu <B33228@freescale.com>
> ---
>  drivers/pci/pcie/portdrv_core.c |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
> index 595654a..95e64c8 100644
> --- a/drivers/pci/pcie/portdrv_core.c
> +++ b/drivers/pci/pcie/portdrv_core.c
> @@ -209,7 +209,10 @@ static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
>  		irqs[i] = irq;
>  	irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
>  
> -	if (irq < 0)
> +	/* Root complex ports for Freescale PCIe host controller only
> +	 * receive interrupts, so if there is no irq setting for RC,
> +	 * it should not return error. */
> +	if ((irq < 0) && (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT))
>  		return -ENODEV;
>  	return 0;
>  }

-- 
Regards

Lei

^ permalink raw reply

* [PATCH] powerpc/85xx:Create dts of each core in CAMP mode for P1020RDB
From: Prabhakar Kushwaha @ 2011-04-28  7:00 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss; +Cc: meet2prabhu, Prabhakar Kushwaha

Create the dts files for each core and splits the devices between the two cores
for P1020RDB.

Core0 has core0 to have memory, l2, i2c, spi, gpio, tdm, dma, usb, eth1, eth2,
sdhc, crypto, global-util, message, pci0, pci1, msi.
Core1 has l2, eth0, crypto.

MPIC is shared between two cores but each core will protect its interrupts from
other core by using "protected-sources" of mpic.

Fix compatible property for global-util node of P1020si.dtsi.

Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
---
 Based upon git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git(branch master)
 
 This patch depends on following patch
 	"powerpc/85xx: P1020 DTS : re-organize dts files"

 arch/powerpc/boot/dts/p1020rdb_camp_core0.dts |  213 +++++++++++++++++++++++++
 arch/powerpc/boot/dts/p1020rdb_camp_core1.dts |  148 +++++++++++++++++
 arch/powerpc/boot/dts/p1020si.dtsi            |    2 +-
 3 files changed, 362 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
 create mode 100644 arch/powerpc/boot/dts/p1020rdb_camp_core1.dts

diff --git a/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
new file mode 100644
index 0000000..f0bf7f4
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
@@ -0,0 +1,213 @@
+/*
+ * P1020 RDB  Core0 Device Tree Source in CAMP mode.
+ *
+ * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
+ * can be shared, all the other devices must be assigned to one core only.
+ * This dts file allows core0 to have memory, l2, i2c, spi, gpio, tdm, dma, usb,
+ * eth1, eth2, sdhc, crypto, global-util, message, pci0, pci1, msi.
+ *
+ * Please note to add "-b 0" for core0's dts compiling.
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1020si.dtsi"
+
+/ {
+	model = "fsl,P1020RDB";
+	compatible = "fsl,P1020RDB", "fsl,MPC85XXRDB-CAMP";
+
+	aliases {
+		ethernet1 = &enet1;
+		ethernet2 = &enet2;
+		serial0 = &serial0;
+		pci0 = &pci0;
+		pci1 = &pci1;
+	};
+
+	cpus {
+		PowerPC,P1020@1 {
+		status = "disabled";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@ffe05000 {
+		status = "disabled";
+	};
+
+	soc@ffe00000 {
+		i2c@3000 {
+			rtc@68 {
+				compatible = "dallas,ds1339";
+				reg = <0x68>;
+			};
+		};
+
+		serial1: serial@4600 {
+			status = "disabled";
+		};
+
+		spi@7000 {
+			fsl_m25p80@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,espi-flash";
+				reg = <0>;
+				linux,modalias = "fsl_m25p80";
+				spi-max-frequency = <40000000>;
+
+				partition@0 {
+					/* 512KB for u-boot Bootloader Image */
+					reg = <0x0 0x00080000>;
+					label = "SPI (RO) U-Boot Image";
+					read-only;
+				};
+
+				partition@80000 {
+					/* 512KB for DTB Image */
+					reg = <0x00080000 0x00080000>;
+					label = "SPI (RO) DTB Image";
+					read-only;
+				};
+
+				partition@100000 {
+					/* 4MB for Linux Kernel Image */
+					reg = <0x00100000 0x00400000>;
+					label = "SPI (RO) Linux Kernel Image";
+					read-only;
+				};
+
+				partition@500000 {
+					/* 4MB for Compressed RFS Image */
+					reg = <0x00500000 0x00400000>;
+					label = "SPI (RO) Compressed RFS Image";
+					read-only;
+				};
+
+				partition@900000 {
+					/* 7MB for JFFS2 based RFS */
+					reg = <0x00900000 0x00700000>;
+					label = "SPI (RW) JFFS2 RFS";
+				};
+			};
+		};
+
+		mdio@24000 {
+			phy0: ethernet-phy@0 {
+				interrupt-parent = <&mpic>;
+				interrupts = <3 1>;
+				reg = <0x0>;
+			};
+			phy1: ethernet-phy@1 {
+				interrupt-parent = <&mpic>;
+				interrupts = <2 1>;
+				reg = <0x1>;
+			};
+		};
+
+		mdio@25000 {
+			tbi0: tbi-phy@11 {
+				reg = <0x11>;
+				device_type = "tbi-phy";
+			};
+		};
+
+		enet0: ethernet@b0000 {
+			status = "disabled";
+		};
+
+		enet1: ethernet@b1000 {
+			phy-handle = <&phy0>;
+			tbi-handle = <&tbi0>;
+			phy-connection-type = "sgmii";
+		};
+
+		enet2: ethernet@b2000 {
+			phy-handle = <&phy1>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		usb@22000 {
+			phy_type = "ulpi";
+		};
+
+		/* USB2 is shared with localbus, so it must be disabled
+		   by default. We can't put 'status = "disabled";' here
+		   since U-Boot doesn't clear the status property when
+		   it enables USB2. OTOH, U-Boot does create a new node
+		   when there isn't any. So, just comment it out.
+		usb@23000 {
+			phy_type = "ulpi";
+		};
+		*/
+
+		mpic: pic@40000 {
+			protected-sources = <
+			42 29 30 34	/* serial1, enet0-queue-group0 */
+			17 18 24 45	/* enet0-queue-group1, crypto */
+			>;
+		};
+
+	};
+
+	pci0: pcie@ffe09000 {
+		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x4 0x1
+			0000 0x0 0x0 0x2 &mpic 0x5 0x1
+			0000 0x0 0x0 0x3 &mpic 0x6 0x1
+			0000 0x0 0x0 0x4 &mpic 0x7 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0xa0000000
+				  0x2000000 0x0 0xa0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci1: pcie@ffe0a000 {
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0000 0x0 0x0 0x4 &mpic 0x3 0x1
+			>;
+		pcie@0 {
+			reg = <0x0 0x0 0x0 0x0 0x0>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			device_type = "pci";
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
new file mode 100644
index 0000000..8498988
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
@@ -0,0 +1,148 @@
+/*
+ * P1020 RDB Core1 Device Tree Source in CAMP mode.
+ *
+ * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
+ * can be shared, all the other devices must be assigned to one core only.
+ * This dts allows core1 to have l2, eth0, crypto.
+ *
+ * Please note to add "-b 1" for core1's dts compiling.
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "p1020si.dtsi"
+
+/ {
+	model = "fsl,P1020RDB";
+	compatible = "fsl,P1020RDB", "fsl,MPC85XXRDB-CAMP";
+
+	aliases {
+		ethernet0 = &enet0;
+		serial0 = &serial1;
+		};
+
+	cpus {
+		PowerPC,P1020@0 {
+		status = "disabled";
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	localbus@ffe05000 {
+		status = "disabled";
+	};
+
+	soc@ffe00000 {
+		ecm-law@0 {
+			status = "disabled";
+		};
+
+		ecm@1000 {
+			status = "disabled";
+		};
+
+		memory-controller@2000 {
+			status = "disabled";
+		};
+
+		i2c@3000 {
+			status = "disabled";
+		};
+
+		i2c@3100 {
+			status = "disabled";
+		};
+
+		serial0: serial@4500 {
+			status = "disabled";
+		};
+
+		spi@7000 {
+			status = "disabled";
+		};
+
+		gpio: gpio-controller@f000 {
+			status = "disabled";
+		};
+
+		dma@21300 {
+			status = "disabled";
+		};
+
+		mdio@24000 {
+			status = "disabled";
+		};
+
+		mdio@25000 {
+			status = "disabled";
+		};
+
+		enet0: ethernet@b0000 {
+			fixed-link = <1 1 1000 0 0>;
+			phy-connection-type = "rgmii-id";
+
+		};
+
+		enet1: ethernet@b1000 {
+			status = "disabled";
+		};
+
+		enet2: ethernet@b2000 {
+			status = "disabled";
+		};
+
+		usb@22000 {
+			status = "disabled";
+		};
+
+		sdhci@2e000 {
+			status = "disabled";
+		};
+
+		mpic: pic@40000 {
+			protected-sources = <
+			16 		/* ecm, mem, L2, pci0, pci1 */
+			43 42 59	/* i2c, serial0, spi */
+			47 63 62 	/* gpio, tdm */
+			20 21 22 23	/* dma */
+			03 02 		/* mdio */
+			35 36 40	/* enet1-queue-group0 */
+			51 52 67	/* enet1-queue-group1 */
+			31 32 33	/* enet2-queue-group0 */
+			25 26 27	/* enet2-queue-group1 */
+			28 72 58 	/* usb, sdhci, crypto */
+			0xb0 0xb1 0xb2	/* message */
+			0xb3 0xb4 0xb5
+			0xb6 0xb7
+			0xe0 0xe1 0xe2	/* msi */
+			0xe3 0xe4 0xe5
+			0xe6 0xe7		/* sdhci, crypto , pci */
+			>;
+		};
+
+		msi@41600 {
+			status = "disabled";
+		};
+
+		global-utilities@e0000 {	//global utilities block
+			status = "disabled";
+		};
+
+	};
+
+	pci0: pcie@ffe09000 {
+		status = "disabled";
+	};
+
+	pci1: pcie@ffe0a000 {
+		status = "disabled";
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1020si.dtsi b/arch/powerpc/boot/dts/p1020si.dtsi
index f6f1100..5c5acb6 100644
--- a/arch/powerpc/boot/dts/p1020si.dtsi
+++ b/arch/powerpc/boot/dts/p1020si.dtsi
@@ -343,7 +343,7 @@
 		};
 
 		global-utilities@e0000 {	//global utilities block
-			compatible = "fsl,p1020-guts";
+			compatible = "fsl,p1020-guts","fsl,p2020-guts";
 			reg = <0xe0000 0x1000>;
 			fsl,has-rstcr;
 		};
-- 
1.7.3

^ 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